diff --git a/src/backend/bisheng/api/services/linsight/workbench_impl.py b/src/backend/bisheng/api/services/linsight/workbench_impl.py index c28824387..ddf66d42a 100644 --- a/src/backend/bisheng/api/services/linsight/workbench_impl.py +++ b/src/backend/bisheng/api/services/linsight/workbench_impl.py @@ -424,7 +424,7 @@ class LinsightWorkbenchImpl: raise cls.ToolsInitializationError(f"初始化灵思工作台工具失败: {str(e)}") @classmethod - async def _prepare_file_list(cls, session_version: LinsightSessionVersion) -> List[str]: + async def prepare_file_list(cls, session_version: LinsightSessionVersion) -> List[str]: """准备文件列表""" file_list = [] template_str = """@{filename}的文件储存信息:{{'文件储存在语义检索库中的id':'{file_id}','文件储存地址':'{markdown}'}}@""" @@ -437,7 +437,7 @@ class LinsightWorkbenchImpl: return file_list @classmethod - async def _prepare_knowledge_list(cls, knowledge_list: list[KnowledgeRead]) -> List[str]: + async def prepare_knowledge_list(cls, knowledge_list: list[KnowledgeRead]) -> List[str]: res = [] if not knowledge_list: return res @@ -495,8 +495,8 @@ class LinsightWorkbenchImpl: history_summary: List[str], knowledge_list: List[KnowledgeRead] = None) -> AsyncGenerator: """生成SOP内容""" - file_list = await cls._prepare_file_list(session_version) - knowledge_list = await cls._prepare_knowledge_list(knowledge_list) + file_list = await cls.prepare_file_list(session_version) + knowledge_list = await cls.prepare_knowledge_list(knowledge_list) if feedback_content is None: # 检索SOP模板 @@ -861,7 +861,7 @@ class LinsightWorkbenchImpl: feedback: 反馈内容 """ try: - file_list = await cls._prepare_file_list(session_version_model) + file_list = await cls.prepare_file_list(session_version_model) # 创建LLM和工具 llm, workbench_conf = await cls._get_llm() diff --git a/src/backend/bisheng/linsight/task_exec.py b/src/backend/bisheng/linsight/task_exec.py index f0b636e8a..654cb4ecd 100644 --- a/src/backend/bisheng/linsight/task_exec.py +++ b/src/backend/bisheng/linsight/task_exec.py @@ -303,7 +303,8 @@ class LinsightWorkflowTask: async def agent_execution(): """智能体执行任务""" - async for event in agent.ainvoke(task_info, session_model.sop): + file_list = await LinsightWorkbenchImpl.prepare_file_list(session_model) + async for event in agent.ainvoke(task_info, session_model.sop, file_list=file_list): await self._handle_event(agent, event, session_model) return True @@ -315,6 +316,7 @@ class LinsightWorkflowTask: try: # 创建两个并发任务 + # 准备用户上传的文件 agent_task = asyncio.create_task(agent_execution()) monitor_task = asyncio.create_task(termination_monitor()) diff --git a/src/backend/bisheng_langchain/linsight/agent.py b/src/backend/bisheng_langchain/linsight/agent.py index 5fbd8d8bf..525676693 100644 --- a/src/backend/bisheng_langchain/linsight/agent.py +++ b/src/backend/bisheng_langchain/linsight/agent.py @@ -37,7 +37,7 @@ class LinsightAgent(BaseModel): if file_list: file_list_str = "\n".join(file_list[:self.exec_config.max_file_num]) if len(file_list) > self.exec_config.max_file_num: - file_list_str += f"用户上传了{len(file_list)}份文件,此处只展示{self.exec_config.max_file_num}份。都储存在./目录下。" + file_list_str += f"\n用户上传了{len(file_list)}份文件,此处只展示{self.exec_config.max_file_num}份。都储存在./目录下。" file_list_str = f"<用户上传文件列表>\n{file_list_str}\n" return file_list_str @@ -144,17 +144,19 @@ class LinsightAgent(BaseModel): return TaskManage.completion_task_tree_info(tasks) - async def ainvoke(self, tasks: list[dict], sop: str) -> AsyncIterator[BaseEvent]: + async def ainvoke(self, tasks: list[dict], sop: str, file_list: list[str] = None) -> AsyncIterator[BaseEvent]: """ Run the agent's main functionality. :param tasks: List of tasks to be processed by the agent. :param sop: Final SOP to be used in the agent's processing. + :param file_list: Optional list of files uploaded by the user. """ + file_list_str = await self.parse_file_list_str(file_list) # Add main functionality logic here if not self.task_manager: self.task_manager = TaskManage(tasks=tasks, tools=self.tools, task_mode=self.task_mode) self.task_manager.rebuild_tasks(query=self.query, llm=self.llm, file_dir=self.file_dir, sop=sop, - exec_config=self.exec_config) + exec_config=self.exec_config, file_list_str=file_list_str) async for one in self.task_manager.ainvoke_task(): yield one diff --git a/src/backend/bisheng_langchain/linsight/manage.py b/src/backend/bisheng_langchain/linsight/manage.py index 1138251c5..c05f449d6 100644 --- a/src/backend/bisheng_langchain/linsight/manage.py +++ b/src/backend/bisheng_langchain/linsight/manage.py @@ -42,7 +42,7 @@ class TaskManage(BaseModel): return self def rebuild_tasks(self, query: str, llm: BaseLanguageModel, file_dir: str, sop: str, - exec_config: ExecConfig) -> None: + exec_config: ExecConfig, file_list_str: str = '') -> None: res = [] child_map = {} # task_id: [child_task] for task in self.tasks: @@ -55,7 +55,8 @@ class TaskManage(BaseModel): llm=llm, file_dir=file_dir, finally_sop=sop, - exec_config=exec_config) + exec_config=exec_config, + file_list_str=file_list_str) else: task_instance = ReactTask(**task, query=query, @@ -63,7 +64,8 @@ class TaskManage(BaseModel): llm=llm, file_dir=file_dir, finally_sop=sop, - exec_config=exec_config) + exec_config=exec_config, + file_list_str=file_list_str) if task_instance.parent_id is None: res.append(task_instance) continue diff --git a/src/backend/bisheng_langchain/linsight/react_prompt.py b/src/backend/bisheng_langchain/linsight/react_prompt.py index 2e08ed755..900f00366 100644 --- a/src/backend/bisheng_langchain/linsight/react_prompt.py +++ b/src/backend/bisheng_langchain/linsight/react_prompt.py @@ -2,7 +2,7 @@ # variables -> profile: task角色; current_time: 当前时间;file_dir: 用户上传的文件路径; # tools_json: 可用的工具列表;sop: 用户SOP;query: 用户最终问题; # step_list: 任务整体规划;processed_steps: 已经处理的步骤;input_str: 用户输入信息;step_id: 当前任务id -# target: prompt;single_sop: 当前任务遵循的SOP; history: 已经执行的步骤 +# target: prompt;single_sop: 当前任务遵循的SOP; history: 已经执行的步骤; file_list_str: 用户上传的文件列表 ReactSingleAgentPrompt = """你是一个强大的{profile},可以使用以下工具来回答用户问题并执行任务。 请使用ReAct (Reasoning + Acting)方法,思考并使用工具解决问题。 每一步都要清晰地思考你需要做什么,然后采取行动。 @@ -12,6 +12,8 @@ ReactSingleAgentPrompt = """你是一个强大的{profile},可以使用以下 当前时间:{current_time} 当前路径:{file_dir} +{file_list_str} + 可用工具列表: {tools_json} @@ -87,7 +89,7 @@ ReactSingleAgentPrompt = """你是一个强大的{profile},可以使用以下 # 二级子任务的prompt模板 # variables -> profile: agent的角色;current_time: 当前时间;file_dir: 用户上传的文件路径;tools_json: 可用的工具列表; # original_query: 总体任务目标;original_method: 总体方法;original_done: 已经完成的内容;last_answer: 上步骤的答案 -# single_sop: 当前任务遵循的SOP;step_id: 当前任务id; target: 当前任务目标;history: 历史记录 +# single_sop: 当前任务遵循的SOP;step_id: 当前任务id; target: 当前任务目标;history: 历史记录; file_list_str: 文件列表字符串 ReactLoopAgentPrompt = """你是一个强大的{profile},可以使用以下工具来回答用户问题并执行任务。 请使用ReAct (Reasoning + Acting)方法,思考并使用工具解决问题。 每一步都要清晰地思考你需要做什么,然后采取行动。 @@ -97,6 +99,8 @@ ReactLoopAgentPrompt = """你是一个强大的{profile},可以使用以下工 当前时间:{current_time} 当前路径:{file_dir} +{file_list_str} + 可用工具: {tools_json} diff --git a/src/backend/bisheng_langchain/linsight/react_task.py b/src/backend/bisheng_langchain/linsight/react_task.py index 82cfe7574..b30f03a12 100644 --- a/src/backend/bisheng_langchain/linsight/react_task.py +++ b/src/backend/bisheng_langchain/linsight/react_task.py @@ -64,7 +64,8 @@ class ReactTask(BaseTask): single_sop=self.sop, step_id=self.step_id, target=self.target, - history=history_str) + history=history_str, + file_list_str=self.file_list_str) else: prompt = ReactSingleAgentPrompt.format(profile=self.profile, current_time=current_time, @@ -78,7 +79,8 @@ class ReactTask(BaseTask): step_id=self.step_id, target=self.target, single_sop=self.sop, - history=history_str) + history=history_str, + file_list_str=self.file_list_str) return [HumanMessage(content=prompt)] async def parse_react_result(self, content: str) -> (BaseMessage, bool): diff --git a/src/backend/bisheng_langchain/linsight/task.py b/src/backend/bisheng_langchain/linsight/task.py index 0f07a12f7..24d9cba5e 100644 --- a/src/backend/bisheng_langchain/linsight/task.py +++ b/src/backend/bisheng_langchain/linsight/task.py @@ -38,6 +38,7 @@ class BaseTask(BaseModel): task_manager: Optional[Any] = Field(None, description='Task manager for handling tasks and workflows') user_input: Optional[str] = Field(default=None, description='用户输入的内容') exec_config: ExecConfig = Field(default_factory=ExecConfig, description='执行过程中的配置') + file_list_str: Optional[str] = Field(default='', description='用户上传的文件列表字符串') # llm generate task field step_id: str = Field(default='', description='Step ID')