feat(langchain-chat): LangGraph 重写 agent 内核
主要变化: - 新增 agent_v2.py: 用 LangGraph create_react_agent + astream_events 替代原 agent_chat_test 的 LLM step-routing 死循环 - 新增 tools_v2.py: 闭包工厂模式,每个请求按 uuid 生成工具列表, 消除 toolinput 字符串拼 JSON 注入 uuid 的旧 hack - chat_test.py:266-346: 删 11 次 count_process 重试外层和事件 分发 spaghetti,换成 agent_run 单次调用 + 简单事件 dispatcher - policy_fun_iast.py:168-187: 修 broken <think> filter 老代码把 start_flag 设反了(看见 <think> 才开始 yield)导致 非 think 模型 yield 不出任何内容;改为正确跳过 <think>...</think> 块 模型函数调用通过 langchain_openai.ChatOpenAI(不能用旧版 langchain_community.chat_models.ChatOpenAI,没有现代 tool calling)。 依赖: langgraph==0.0.49 + langchain-core==0.1.53(已在服务器装好)。 非 stream 分支保留旧 agent_chat_test 路径(极少触发,回归风险低)。 旧版回滚: git checkout backup/pre-langgraph 实测对比: - 旧版 30-60s,答案 0 字(filter 卡死后展示 11 次重试) - 新版 25-40s,答案完整(含工具调用、参考文献、推荐问题、摘要) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -264,63 +264,45 @@ async def chat_test(
|
||||
count_process = 0
|
||||
# await agent_chat_test(query=query, history=history, model_name=model_name,temperature=temperature,max_tokens=max_tokens,prompt_name="answer_question_history",think_content=res)
|
||||
if stream:
|
||||
while i<1:
|
||||
if count_process>10:
|
||||
# ============================================================
|
||||
# LangGraph 版 agent(v2)—— 替换原来 11 次外层重试 + LLM 路由
|
||||
# 旧代码见 git tag: checkpoint-pre-langgraph
|
||||
# ============================================================
|
||||
from server.chat.agent_v2 import agent_run
|
||||
|
||||
# 初始化共享状态(工具内部仍用它写 source_docs)
|
||||
tip["END"] = ""
|
||||
tip["source_docs"] = []
|
||||
tip["num"] = 0
|
||||
tip["title"] = []
|
||||
utils.set_shared_variable(time_based_uuid, tip)
|
||||
|
||||
async for response in agent_run(
|
||||
query=query,
|
||||
uuid=time_based_uuid,
|
||||
history=history,
|
||||
model_name=model_name,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
user_prompt_name=user_prompt_name,
|
||||
think_content=res["text"],
|
||||
):
|
||||
if not utils.get_shared_variable(time_based_uuid)["status"]:
|
||||
logging.info("\n==========STOPPED==========\n")
|
||||
break
|
||||
tip["END"]=""
|
||||
stop = ""
|
||||
temp = ""
|
||||
tip["source_docs"]=[]
|
||||
tip["num"]=0
|
||||
tip["title"]=[]
|
||||
# tip["status"] = True
|
||||
utils.set_shared_variable(time_based_uuid,tip)
|
||||
count = 0
|
||||
count_process += 1
|
||||
logging.info(f"\n\ncount_process:{count_process}\n\n")
|
||||
async for response in agent_chat_test(user_prompt_name = user_prompt_name,query=query,uuid=time_based_uuid, history=history, model_name=model_name,temperature=temperature,max_tokens=max_tokens,prompt_name="Think Test",think_content=res["text"]):
|
||||
# print("------------"+response)
|
||||
if not utils.get_shared_variable(time_based_uuid)["status"]:
|
||||
logging.info("\n==============================STOPPED==============================\n")
|
||||
break
|
||||
if "answer" in json.loads(response):
|
||||
# logging.info(f"answer:{json.loads(response)['answer']}")
|
||||
answer = json.loads(response)["answer"]
|
||||
history_summary+=answer
|
||||
stop = "1"
|
||||
yield json.dumps({"text": answer}, ensure_ascii=False)
|
||||
elif "tools" in json.loads(response):
|
||||
# print("tools:", json.loads(response)["tools"])
|
||||
tools.append(json.loads(response)["tools"])
|
||||
# yield json.dumps({"tools": tools}, ensure_ascii=False)
|
||||
elif "search_answer" in json.loads(response):
|
||||
search_answer = json.loads(response)["search_answer"]
|
||||
# history_summary+= search_answer
|
||||
yield json.dumps({"text": search_answer}, ensure_ascii=False)
|
||||
elif "docs" in json.loads(response):
|
||||
docs = json.loads(response)["docs"]
|
||||
elif "detail" in json.loads(response):
|
||||
docs_detail += json.loads(response)["detail"]
|
||||
elif "pic" in json.loads(response):
|
||||
# 获取图片路径
|
||||
image_name = json.loads(response)["pic"]
|
||||
image_name = f"\n\n\n\n"
|
||||
# yield json.dumps({"text": image_name}, ensure_ascii=False)
|
||||
else :
|
||||
#history_summary += json.loads(response)["final_answer"]
|
||||
yield json.dumps({"text": json.loads(response)["final_answer"]}, ensure_ascii=False)
|
||||
if stop == "":
|
||||
continue
|
||||
else:
|
||||
stop = ""
|
||||
temp1 = utils.get_shared_variable(time_based_uuid)
|
||||
temp1["END"]=""
|
||||
i+=1
|
||||
# if index3 == 0 and not "Action" in answer:
|
||||
# yield json.dumps({"text": answer}, ensure_ascii=False)
|
||||
yield json.dumps({"text":"\n"}, ensure_ascii=False)
|
||||
import importlib
|
||||
importlib.reload(prompt_config)
|
||||
msg = json.loads(response)
|
||||
if "answer" in msg:
|
||||
history_summary += msg["answer"]
|
||||
yield json.dumps({"text": msg["answer"]}, ensure_ascii=False)
|
||||
elif "think" in msg:
|
||||
yield json.dumps({"think": msg["think"]}, ensure_ascii=False)
|
||||
elif "docs" in msg:
|
||||
docs += msg["docs"]
|
||||
elif "detail" in msg:
|
||||
docs_detail += msg["detail"]
|
||||
|
||||
yield json.dumps({"text": "\n"}, ensure_ascii=False)
|
||||
|
||||
if not docs_detail.strip() == "" and uid and uid in prompt_config.detail_answer_uid:
|
||||
yield json.dumps({"text": f"\n\n"}, ensure_ascii=False)
|
||||
async for chunk in thinking_generator("正在进行幻觉校验,请稍等待..."):
|
||||
|
||||
Reference in New Issue
Block a user