feat:LLM 分析文件并生成结构化建议
This commit is contained in:
@@ -11,7 +11,7 @@ from app.processor.nodes.intent_node import IntentNode
|
||||
from app.processor.nodes.qa_node import QANode
|
||||
from app.processor.nodes.screen_agent_node import ScreenAgentNode
|
||||
from app.processor.nodes.wait_for_user_node import WaitForUserNode
|
||||
from app.processor.state import QueryState
|
||||
from app.processor.state import QueryState, RunContext
|
||||
|
||||
|
||||
def build_checkpoint_serde() -> JsonPlusSerializer:
|
||||
@@ -47,7 +47,7 @@ def route_after_wait(state: QueryState) -> str:
|
||||
|
||||
|
||||
def build_graph(checkpointer=None):
|
||||
workflow = StateGraph(QueryState)
|
||||
workflow = StateGraph(QueryState, context_schema=RunContext)
|
||||
nodes = {
|
||||
"input_node": InputNode(),
|
||||
"intent_node": IntentNode(),
|
||||
|
||||
@@ -10,11 +10,10 @@ from langchain_core.messages import AIMessageChunk, HumanMessage
|
||||
from langchain_core.output_parsers import StrOutputParser
|
||||
from langgraph.config import get_stream_writer
|
||||
|
||||
from app.agent.data_tools import DataContext
|
||||
from app.agent.qa_agent import QAContext, get_qa_agent
|
||||
from app.processor.base import BaseNode
|
||||
from app.processor.history import history_messages
|
||||
from app.processor.state import QueryState
|
||||
from app.processor.state import QueryState, run_data
|
||||
from app.processor.summary import data_file_summary
|
||||
|
||||
# 模型在一次回答里分几次输出文字(例如查询前后各说一段)时,段落之间空一行
|
||||
@@ -56,7 +55,7 @@ class QANode(BaseNode):
|
||||
HumanMessage(content=json.dumps(payload, ensure_ascii=False)),
|
||||
]
|
||||
},
|
||||
context=QAContext(data=DataContext(tuple(context.data_files))),
|
||||
context=QAContext(data=run_data()),
|
||||
stream_mode="messages",
|
||||
):
|
||||
# 工具结果、工具调用和中间件插入的消息都不推送
|
||||
|
||||
@@ -7,12 +7,11 @@ import json
|
||||
|
||||
from langchain_core.messages import HumanMessage
|
||||
|
||||
from app.agent.data_tools import DataContext
|
||||
from app.agent.screen_agent import AgentReply, get_screen_agent
|
||||
from app.agent.tools import ScreenAgentContext
|
||||
from app.processor.base import BaseNode
|
||||
from app.processor.history import history_messages
|
||||
from app.processor.state import QueryState
|
||||
from app.processor.state import QueryState, run_data
|
||||
from app.processor.summary import request_summary
|
||||
from app.resources.component import get_catalog_cache
|
||||
|
||||
@@ -68,7 +67,7 @@ class ScreenAgentNode(BaseNode):
|
||||
context=ScreenAgentContext(
|
||||
screen=context.screen,
|
||||
catalog=catalog,
|
||||
data=DataContext(tuple(context.data_files)),
|
||||
data=run_data(),
|
||||
),
|
||||
)
|
||||
if result.get("structured_response") is None:
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Literal, NotRequired, TypedDict
|
||||
|
||||
from langgraph.runtime import get_runtime
|
||||
|
||||
from app.agent.data_tools import DataContext
|
||||
from app.schemas.actions import Action
|
||||
from app.schemas.base import JsonObject
|
||||
from app.schemas.clarification import Clarification
|
||||
@@ -25,3 +29,21 @@ class QueryState(TypedDict):
|
||||
status: NotRequired[
|
||||
Literal["running", "waiting_for_input", "completed", "cancelled", "failed"]
|
||||
] # 后端处理、等待补充、处理完成、用户取消或失败,完成不代表前端已执行
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RunContext:
|
||||
"""图的运行上下文:本次运行要用、但不进检查点的依赖,每次启动和恢复时由调用方传入"""
|
||||
|
||||
# 本会话的数据文件;状态里的 input_context.data_files 只有摘要,列概况和路径在这里
|
||||
data: DataContext = field(default_factory=DataContext)
|
||||
|
||||
|
||||
def run_data() -> DataContext:
|
||||
"""当前运行可用的数据表;单独调用节点(不在图里执行)或调用方没传 context 时为空"""
|
||||
try:
|
||||
runtime = get_runtime(RunContext)
|
||||
except RuntimeError:
|
||||
return DataContext()
|
||||
context = runtime.context if runtime is not None else None
|
||||
return context.data if context is not None else DataContext()
|
||||
|
||||
Reference in New Issue
Block a user