"""大模型直接回答节点
输入: state['input_semantic_trans'] 语义转写节点补全后的提问
输出: state['direct_out'] 大模型的回答
state['output'] 同一份回答,直接作为整张图的最终输出
这是 is_zhongyi_intent 为 False 时走的兜底分支:提问跟中医无关,图谱里查不到东西,
不必再走实体抽取和 cypher 那一串,交给大模型自由回答。
两个键写同一份内容:direct_out 记录"这一轮是直接回答的",output 是图的统一出口,
下游(_005_ 的接口)只读 output,不用关心答案是从图谱来的还是模型直接给的。
"""
from langchain_core.messages import HumanMessage, SystemMessage
from _004_langgraph_more_nodes.agent_state import AgentState
from common.llm import my_llm
llm = my_llm
SYSTEM_PROMPT = (
"你是一个乐于助人的中文助手。请直接、简洁地回答用户的问题。\n"
"如果用户的问题涉及中医药,只做常识性说明,并提示具体用药需遵医嘱。\n"
"不要编造事实,不知道就说不知道。"
)
def llm_direct_out_node(state: AgentState) -> AgentState:
print("直接回答节点执行开始了")
# 读转写结果而不是 state['input']:多轮里"那第二呢?"必须补全成完整问题才答得对
user_input = (state.get("input_semantic_trans") or "").strip()
# 空输入不必调用大模型,两个键仍然要写满,下游只读 output 不用判空
if not user_input:
state["direct_out"] = ""
state["output"] = ""
print("完成直接回答: 空输入")
return state
messages = [
SystemMessage(content=SYSTEM_PROMPT),
HumanMessage(content=user_input),
]
model_answer = llm.invoke(messages).content.strip()
# 存入 state
state["direct_out"] = model_answer
state["output"] = model_answer
history_messages = state.get("history_messages", [])
history_messages.append({"role": "assistant", "content": model_answer})
state["history_messages"] = history_messages
print(f"完成直接回答: {len(model_answer)} 字")
return state
if __name__ == "__main__":
for text in [
"今天上海天气怎么样?",
"帮我写一段 Python 快排代码",
"解释下什么是大模型",
"",
]:
result = llm_direct_out_node({"input_semantic_trans": text})
print(f"\n提问: {text!r}")
print(f" direct_out: {result['direct_out'][:120]}")
print(f" output 与 direct_out 一致: {result['output'] == result['direct_out']}")