ai写作修改
This commit is contained in:
1 parent
67152f1c83
commit
95baa44a1c
1 file changed
+64
-20
+64
-20
@@ -83,11 +83,16 @@ _SYSTEM_TEMPLATE = """你是一名写作助手。
|
||||
|
||||
_USER_TEMPLATE = """用户写作意图:{user_intent}
|
||||
|
||||
请分析并输出以下 JSON(如果意图中未明确某字段,给出合理默认值):
|
||||
用户在表单中已指定写作配置(以下三项必须原样输出,不要自行修改):
|
||||
- 文章类型(article_type):{preconfigured_article_type}
|
||||
- 目标读者(target_audience):{preconfigured_audience}
|
||||
- 目标字数(word_count_target):{preconfigured_word_count}
|
||||
|
||||
请输出以下 JSON,article_type / target_audience / word_count_target 必须与上述一致,只需根据用户意图精炼 refined_intent:
|
||||
{{{{
|
||||
"article_type": "{type_options} 之一",
|
||||
"target_audience": "目标读者描述",
|
||||
"word_count_target": 800,
|
||||
"article_type": "{preconfigured_article_type}",
|
||||
"target_audience": "{preconfigured_audience}",
|
||||
"word_count_target": {preconfigured_word_count},
|
||||
"refined_intent": "精炼后的写作意图(一句话)"
|
||||
}}}}"""
|
||||
|
||||
@@ -124,6 +129,44 @@ def _coerce_word_count(raw) -> int | None:
|
||||
return value if value > 0 else None
|
||||
|
||||
|
||||
def _resolve_intent_fields(
|
||||
state: AIWritingState,
|
||||
result: dict,
|
||||
fallback_result: dict,
|
||||
valid_keys: list[str],
|
||||
default_key: str,
|
||||
) -> tuple[str, str, int, str]:
|
||||
"""合并 LLM 解析结果与用户表单预填字段;预填字段优先(见 AI_WRITING_BACKEND_DEV_ZH §intent_parser)。"""
|
||||
fallback_type = fallback_result["article_type"]
|
||||
if fallback_type not in valid_keys:
|
||||
fallback_type = default_key
|
||||
|
||||
raw_type = result.get("article_type", "")
|
||||
llm_type = raw_type if raw_type in valid_keys else fallback_type
|
||||
|
||||
preconfigured_type = (state.get("article_type") or "").strip()
|
||||
if preconfigured_type in valid_keys:
|
||||
final_article_type = preconfigured_type
|
||||
else:
|
||||
final_article_type = llm_type
|
||||
|
||||
preconfigured_audience = (state.get("target_audience") or "").strip()
|
||||
if preconfigured_audience:
|
||||
final_target_audience = preconfigured_audience
|
||||
else:
|
||||
final_target_audience = result.get("target_audience") or fallback_result["target_audience"]
|
||||
|
||||
preconfigured_wc = state.get("word_count_target")
|
||||
if isinstance(preconfigured_wc, int) and preconfigured_wc > 0:
|
||||
final_word_count = preconfigured_wc
|
||||
else:
|
||||
word_count = _coerce_word_count(result.get("word_count_target"))
|
||||
final_word_count = word_count if word_count is not None else fallback_result["word_count_target"]
|
||||
|
||||
final_refined_intent = result.get("refined_intent") or state["user_intent"]
|
||||
return final_article_type, final_target_audience, final_word_count, final_refined_intent
|
||||
|
||||
|
||||
async def intent_parser_node(state: AIWritingState, config: RunnableConfig) -> dict:
|
||||
# 从 configurable 读取动态类型列表,未配置时退回默认值
|
||||
configurable = (config or {}).get("configurable", {})
|
||||
@@ -137,10 +180,6 @@ async def intent_parser_node(state: AIWritingState, config: RunnableConfig) -> d
|
||||
|
||||
type_options = _build_type_options(valid_article_types)
|
||||
system = _SYSTEM_TEMPLATE.format(type_options=type_options)
|
||||
user = _USER_TEMPLATE.format(
|
||||
user_intent=state["user_intent"],
|
||||
type_options=" | ".join(valid_keys),
|
||||
)
|
||||
|
||||
fallback_type = state.get("article_type", default_key)
|
||||
if fallback_type not in valid_keys:
|
||||
@@ -153,6 +192,17 @@ async def intent_parser_node(state: AIWritingState, config: RunnableConfig) -> d
|
||||
"refined_intent": state["user_intent"],
|
||||
}
|
||||
|
||||
preconfigured_wc = fallback_result["word_count_target"]
|
||||
if not isinstance(preconfigured_wc, int) or preconfigured_wc <= 0:
|
||||
preconfigured_wc = 800
|
||||
|
||||
user = _USER_TEMPLATE.format(
|
||||
user_intent=state["user_intent"],
|
||||
preconfigured_article_type=fallback_type,
|
||||
preconfigured_audience=fallback_result["target_audience"],
|
||||
preconfigured_word_count=preconfigured_wc,
|
||||
)
|
||||
|
||||
# 流式调用:与 writer_outline / writer_draft 同套机制 —— LLM 逐字吐出 JSON,
|
||||
# 通过 ``intent_chunk`` 推给前端打字机;完成后 ``parse_json`` 解析结构化结果,
|
||||
# 再通过 ``intent_ready`` 推一份结构化字段给前端结果卡片。
|
||||
@@ -193,13 +243,9 @@ async def intent_parser_node(state: AIWritingState, config: RunnableConfig) -> d
|
||||
"detail": f"意图解析失败,已按默认配置兜底。原因:{llm_error}",
|
||||
})
|
||||
|
||||
# 校验 LLM 返回的 article_type 是否在有效范围内,不合法时回退到默认值
|
||||
raw_type = result.get("article_type", "")
|
||||
final_article_type = raw_type if raw_type in valid_keys else fallback_type
|
||||
final_target_audience = result.get("target_audience") or fallback_result["target_audience"]
|
||||
word_count = _coerce_word_count(result.get("word_count_target"))
|
||||
final_word_count = word_count if word_count is not None else fallback_result["word_count_target"]
|
||||
final_refined_intent = result.get("refined_intent") or state["user_intent"]
|
||||
final_article_type, final_target_audience, final_word_count, final_refined_intent = _resolve_intent_fields(
|
||||
state, result, fallback_result, valid_keys, default_key
|
||||
)
|
||||
|
||||
# 推送结构化结果给前端 —— 结果卡片显示文章类型 / 目标读者 / 字数 / 精炼意图
|
||||
writer({
|
||||
@@ -214,11 +260,9 @@ async def intent_parser_node(state: AIWritingState, config: RunnableConfig) -> d
|
||||
|
||||
updates: dict = {"status": "researching", "progress_events": progress_events}
|
||||
updates["article_type"] = final_article_type
|
||||
if result.get("target_audience"):
|
||||
updates["target_audience"] = final_target_audience
|
||||
if word_count is not None:
|
||||
updates["word_count_target"] = final_word_count
|
||||
if result.get("refined_intent"):
|
||||
updates["target_audience"] = final_target_audience
|
||||
updates["word_count_target"] = final_word_count
|
||||
if final_refined_intent != state["user_intent"]:
|
||||
updates["user_intent"] = final_refined_intent
|
||||
|
||||
return updates
|
||||
Reference in new issue
Block a user