Files
life-echo/api/docs/llm-json-mode.md

39 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LLM JSON 模式使用约定
本文档说明 Life Echo API 中 **结构化输出****自然语言输出** 的分工,以及与 [DeepSeek JSON Output](https://api-docs.deepseek.com/guides/json_mode) 的对齐方式。
## 实现位置
- **绑定方式**[`app/core/langchain_llm.py`](../app/core/langchain_llm.py) 中的 `bind_json_object_mode`(等价于 `response_format={"type": "json_object"}`)。**禁止**使用已废弃的 `model_kwargs={"response_format": ...}` 绑定方式(见 [`app/adapters/llm/deepseek.py`](../app/adapters/llm/deepseek.py) 注释)。
- **统一调用**`invoke_json_object` / `ainvoke_json_object`(同文件)在 JSON 模式下提供空内容检测、可选一次重试与结构化日志(`agent``prompt_sha12`)。
## 何时必须使用 `json_object`
以下路径需要稳定 `json.loads` / 下游解析,**必须**通过 `bind_json_object_mode``invoke_json_object` / `ainvoke_json_object` 调用:
| 能力 | 代码入口 |
|------|----------|
| 用户资料字段抽取 | `ProfileAgent.extract_profile_from_message` |
| 回忆录阶段与 slots 抽取 | `ExtractionAgent.extract` |
| 叙事段落 JSON`paragraphs` | `NarrativeAgent.generate_narrative` |
| Story 路由 / 批量规划 | `StoryRouteAgent.decide` / `plan_batch` |
| 回忆录配图 prompt | `MemoirImagePromptService.build_prompt` / `build_cover_prompt` |
## 何时保持普通文本(禁止强行 JSON
- 访谈对话、资料追问开场与跟进:自然口语与 `[SPLIT]` 分条,使用 `ChatOpenAI` 默认输出(`InterviewAgent``ProfileAgent` 中非 extraction 方法)。
- 章节分类、创意标题等若仍为纯文本解析:由业务选择是否后续改为小 JSON见产品决策
## DeepSeek 官方建议对齐
1. `response_format`:已由 `bind_json_object_mode` 设置。
2. Prompt 中应包含 **json** 字样及与解析代码一致的 **字段示例**(各 `prompts_*.py` 中维护)。
**集中兜底**[`ensure_json_object_prompt_has_json_keyword`](../app/core/langchain_llm.py) 在 `invoke_json_object` / `ainvoke_json_object``llm_json_call` / `allm_json_call` 发请求前会检测;若整段 prompt 中仍无子串 `json`(大小写不敏感),会自动追加一行中文 JSON 说明,避免 OpenAI/DeepSeek 返回 400。
3. `max_tokens`:在 `invoke_json_object(..., max_tokens=...)` 与绑定处统一传入;长叙事等场景按需调大。
4. 偶发空内容:由 `invoke_json_object` 记录并重试一次;仍失败则由各 Agent 既有 `try/except` 回退。
## 架构注意
- `app/core` 仅承载跨切 LLM 约定,**不**依赖 `features/*` 或具体 Agent。
- Service 层通过 `get_llm_provider().langchain_llm` 获取 Runnable**不**直接 import `adapters`