feat: 引入deepseek结构化输出

This commit is contained in:
yangshilin
2026-03-19 11:27:43 +08:00
parent f3629efec3
commit 4c75c6f4f4
10 changed files with 74 additions and 26 deletions

View File

@@ -16,6 +16,7 @@ from app.agents.chat.prompts_profile import (
get_profile_followup_prompt,
get_profile_greeting_prompt,
)
from app.features.memoir.memoir_images.json_payload import extract_json_payload
logger = get_logger(__name__)
@@ -58,9 +59,13 @@ class ProfileAgent:
prompt = get_profile_extraction_prompt(
user_message, missing_fields, recent_dialogue=recent_dialogue or None
)
response = await self.llm.ainvoke(prompt)
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=512,
)
response = await json_llm.ainvoke(prompt)
content = response.content.strip()
parsed = json.loads(content)
parsed = json.loads(extract_json_payload(content))
result = {}
if "birth_year" in parsed and parsed["birth_year"] is not None:
raw = parsed["birth_year"]

View File

@@ -52,7 +52,11 @@ class ExtractionAgent:
for k, v in (stage_slots or {}).items()
},
)
response = llm.invoke(prompt)
json_llm = llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=1024,
)
response = json_llm.invoke(prompt)
parsed = json.loads(extract_json_payload(response.content))
detected_stage = parsed.get("detected_stage", detected_stage)
raw_slots = parsed.get("slots", {}) or {}

View File

@@ -15,6 +15,7 @@ from app.agents.memoir.prompts import (
get_text_rewrite_prompt,
inject_image_placeholder_template,
)
from app.features.memoir.memoir_images.json_payload import extract_json_payload
logger = get_logger(__name__)
@@ -64,17 +65,14 @@ class MemoryAgent:
prompt = get_text_rewrite_prompt(
segments_text, chapter_category, existing_content or ""
)
response = await self.llm.ainvoke(prompt)
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=4096,
)
response = await json_llm.ainvoke(prompt)
content = response.content if hasattr(response, "content") else str(response)
content = content.strip()
if content.startswith("```json"):
content = content[7:]
if content.startswith("```"):
content = content[3:]
if content.endswith("```"):
content = content[:-3]
content = content.strip()
result = json.loads(content)
result = json.loads(extract_json_payload(content))
result["content"] = inject_image_placeholder_template(
result.get("content") or ""
)

View File

@@ -69,7 +69,11 @@ class NarrativeAgent:
user_profile=user_profile,
birth_year=birth_year,
)
response = llm.invoke(prompt)
json_llm = llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=4096,
)
response = json_llm.invoke(prompt)
return (response.content or "").strip()
except Exception as e:
logger.warning("NarrativeAgent 生成叙事失败: %s", e)

View File

@@ -13,6 +13,7 @@ from app.core.logging import get_logger
from app.core.task_tracker import task_tracker
from app.agents.state_schema import MemoirStateSchema
from app.features.memoir.memoir_images.json_payload import extract_json_payload
from app.agents.memoir.prompts import (
get_creative_title_prompt,
get_narrative_json_prompt,
@@ -82,9 +83,13 @@ class ContentAnalyzer:
current_stage=current_state.current_stage,
stage_slots=current_state.slots.get(detected_stage, {}),
)
response = await self.llm.ainvoke(prompt)
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=1024,
)
response = await json_llm.ainvoke(prompt)
content = response.content.strip()
parsed = json.loads(content)
parsed = json.loads(extract_json_payload(content))
detected_stage = parsed.get("detected_stage", detected_stage)
extracted_slots = parsed.get("slots", {}) or {}
emotion = parsed.get("emotion", emotion)
@@ -147,7 +152,11 @@ class MemoirGenerator:
new_content=new_content,
existing_content=existing_content,
)
response = await self.llm.ainvoke(prompt)
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=4096,
)
response = await json_llm.ainvoke(prompt)
return response.content.strip()
except Exception as e:
logger.error("生成叙事失败: %s", e)

View File

@@ -57,7 +57,11 @@ class MemoirImagePromptService:
if self.llm:
raw_response = None
try:
response = self.llm.invoke(
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=512,
)
response = json_llm.invoke(
"Return JSON only with keys prompt, style, size. "
"Convert the memoir scene into an image-generation prompt.\n"
+ json.dumps(llm_input, ensure_ascii=False)
@@ -113,7 +117,11 @@ class MemoirImagePromptService:
if self.llm:
try:
response = self.llm.invoke(
json_llm = self.llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=512,
)
response = json_llm.invoke(
"Return JSON only with keys prompt, style, size. "
"Create an image-generation prompt for a memoir chapter COVER. "
"Emphasize: hero composition, evocative scene, chapter cover aesthetic.\n"

View File

@@ -798,7 +798,11 @@ def generate_chapter_content(self, user_id: str, stage: str, new_content: str):
new_content=new_content,
existing_content=existing_content,
)
response = llm.invoke(prompt)
json_llm = llm.bind(
model_kwargs={"response_format": {"type": "json_object"}},
max_tokens=4096,
)
response = json_llm.invoke(prompt)
new_narrative = response.content.strip()
if _is_json_narrative(new_narrative):
narrative = new_narrative