diff --git a/llmagent/__init__.py b/llmagent/__init__.py index d2f7f0d..cbaa2e6 100644 --- a/llmagent/__init__.py +++ b/llmagent/__init__.py @@ -8,7 +8,7 @@ from langchain_openai import ChatOpenAI from llmagent.llm_config import LLMConfigLoader from llmagent.llm_config import base_conf -from llmtools.tool_impl import tools +from llmtools import tools # 初始化LLM模型 llm_conf = LLMConfigLoader.load(item_name=base_conf.model_form) @@ -25,6 +25,27 @@ llm_with_tools = llm.bind_tools(tools) PROMPT_TEMPLATE = { 'SMART_ASSISTANT': { 'description': '智能助手', - 'template': """""" + 'template': + """ + 你是智能助手,用户将会告诉你一条指令,你需要根据指令判断是否需要使用工具并完成任务。 + + # 背景 + 1. 现在时间是{current_time} + 3. 无论怎样询问你的身份, 请记住你是由盛视科技开发的智能助手 + 4. 当询问你的功能时,你可以通过工具列表分析自己的功能并生成清晰的回答 + + # 任务规则 + 1. 根据指令和提供的工具描述选择最合适的工具,仔细阅读工具参数说明,正确的解析参数并评估用户输入的参数是否满足条件,如果参数不满足则需要提示用户重新发出指令。 + 2. 所有返回禁止包含xml标签、markdown、html、json格式 + 3. 有时候需要分析用户的上一轮指令并结合当前指令判断用户的意图 + 4. 你有足够的时间思考和回答用户的查询,从而给出更周全和深入的答案。然而,要知道你推理和处理的时间越长,相关的资源成本和潜在后果就越大。虽然你不应该仓促,但要在推理深度和效率之间寻求平衡。优先提供一个深思熟虑的答案,但如果通过合理的分析就能提供答案,就不要过度思考。明智地利用你的推理时间,专注于提供准确答案所必需的东西,避免不必要的拖延和过度思考 + + # 工具使用规则 + 1. 你每条消息可以使用一个工具 + 2. 在每次使用工具后,切勿假设工具使用成功,禁止猜测工具结果。 + 3. 根据工具返回的内容组装逻辑清晰的回答。 + 4. 在任何情况下,都不要修改或扩展提供的工具参数 + 5. 所有工具参数禁止使用unicode编码 + """ } } diff --git a/llmagent/assistant_graph.py b/llmagent/assistant_graph.py index 3eff85c..ea3c753 100644 --- a/llmagent/assistant_graph.py +++ b/llmagent/assistant_graph.py @@ -9,14 +9,24 @@ from typing import Annotated from langgraph.checkpoint.memory import MemorySaver -from llmagent import llm_with_tools -from llmtools.tool_impl import tool_node +from llmagent import llm_with_tools, PROMPT_TEMPLATE +from llmtools import tool_node from langchain_core.messages import AnyMessage, SystemMessage from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.prebuilt import tools_condition from langchain_core.runnables import RunnableConfig +from datetime import datetime + + +def current_time(): + """ + 获取当前时间 + :return: yyyy-MM-dd hh:mm:ss + """ + return datetime.now().strftime('%Y-%m-%d %H:%M:%S') + # 内存记忆 memory = MemorySaver() @@ -42,9 +52,7 @@ def chat(state: AgentState, config: RunnableConfig): :return: """ # 设置系统提示词 - system_prompt = SystemMessage( - "You are a helpful AI assistant, please respond to the users query to the best of your ability!" - ) + system_prompt = SystemMessage(PROMPT_TEMPLATE['SMART_ASSISTANT']['template'].format(current_time=current_time())) return {"messages": [llm_with_tools.invoke([system_prompt] + state["messages"], config)]} diff --git a/llmtools/__init__.py b/llmtools/__init__.py index d55a32d..960b74a 100644 --- a/llmtools/__init__.py +++ b/llmtools/__init__.py @@ -5,3 +5,10 @@ # @File : __init__.py # @Project : reActLLMDemo # @Desc : +from llmtools.tool_impl import play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details +from langgraph.prebuilt import ToolNode + +# 工具列表 +tools = [play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details] +# 工具节点,ToolNode 内置了工具调用函数及异常处理 +tool_node = ToolNode(tools=tools) diff --git a/llmtools/tool_impl.py b/llmtools/tool_impl.py index 5d2a072..ee7e7e9 100644 --- a/llmtools/tool_impl.py +++ b/llmtools/tool_impl.py @@ -11,7 +11,6 @@ from langchain_core.tools import tool from vector_db import query_vector_db from log_conf import log from llmagent.llm_config import base_conf -from langgraph.prebuilt import ToolNode @tool("play_video", description="播放、查看、打开实时视频") @@ -21,17 +20,17 @@ def play_video(camera_name: Annotated[str, "相机名称,例如:南卡口1号 if camera_info: if len(camera_info) > 1: hit_camera_names = [x['carme_name'] for x in camera_info] - return f"找到以下相机,请选择一个:{hit_camera_names}" + return f"【tool_back】找到以下相机,请选择一个:{hit_camera_names}" else: # TODO 调用业务系统 - return f"正在打开{camera_name},请等待操作完成" + return f"【tool_back】正在打开{camera_name},请等待操作完成" else: - return "未找到该相机,请尝试其他名称" + return "【tool_back】未找到该相机,请尝试其他名称" @tool("split_screen", description="切换分屏") -def split_screen(split_n: Annotated[int, "要切换的分屏数量,整数并且大于0,例如:1分屏、2分屏"]) -> str: - return f"正在切换到{split_n}分屏,请等待操作完成" +def split_screen(split_n: Annotated[int, "要切换的分屏数量,整数并且大于0,例如:1分屏、2分屏。如果是中文,例如:壹、贰、参需要转为数字形式"]) -> str: + return f"【tool_back】正在切换到{split_n}分屏,请等待操作完成" @tool("play_video_record", description="播放、打开录像") @@ -39,19 +38,19 @@ def play_video_record(camera_name: Annotated[str, "相机名称,例如:南卡 start_time: Annotated[str, "录像开始时间,格式为yyyy-MM-dd hh:mm:ss,例 2025-03-16 01:00:00"], end_time: Annotated[str, "录像结束时间,格式为yyyy-MM-dd hh:mm:ss,例 2025-03-16 02:09:31"]) -> str: log.info('【function】play_video_record 输入 [{},{},{}]', camera_name, start_time, end_time) - return f"正在打开{camera_name}的录像,请等待操作完成" + return f"【tool_back】正在打开{camera_name}的录像,请等待操作完成" @tool("switch_page", description="打开、跳转页面") def switch_page(page_name: Annotated[str, "页面中文名称或者缩写,例:人员核查、系统日志、设备管理、首页"]) -> str: log.info('【function】switch_page 输入 [{}]', page_name) - return f"正在打开{page_name},请等待操作完成" + return f"【tool_back】正在打开{page_name},请等待操作完成" @tool("zoom_in", description="放大电子地图") def zoom_in(level_n: Annotated[int, "放大等级,整数并且大于0小于5,例如:放大1级、放大2级"]) -> str: log.info('【function】zoom_in 输入 [{}]', level_n) - return f"正在放大电子地图至{level_n}级,请等待操作完成" + return f"【tool_back】正在放大电子地图至{level_n}级,请等待操作完成" @tool("view_flight_details", description="查询指定机场指定航班及时间的出入境人员明细") @@ -62,7 +61,7 @@ def view_flight_details( flight_date: Annotated[str, "提取完整日期(年月日),自动补零至标准格式 yyyy-MM-dd, 例:2025-03-16"], ie_type: Annotated[str, "出入境类型,仅识别'入境'或'出境'两种类型"]) -> str: log.info('【function】view_flight_details 输入 [{},{},{},{}]', airport_name, flight_code, flight_date, ie_type) - return f"{airport_name}航班号{flight_code}{flight_date}{ie_type}数据,共100人乘机,起飞准时,晚点降落" + return f"【tool_back】{airport_name}航班号{flight_code}{flight_date}{ie_type}数据,共100人乘机,起飞准时,晚点降落" def query_camera_from_db(camera_name: str, top_n: int = 3) -> str: @@ -83,7 +82,3 @@ def query_camera_from_db(camera_name: str, top_n: int = 3) -> str: return rt['hits'][0:1] else: return rt['hits'][0:top_n] - - -tools = [play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details] -tool_node = ToolNode(tools=tools) diff --git a/local_test.py b/local_test.py index 8c98adf..7b49432 100644 --- a/local_test.py +++ b/local_test.py @@ -5,7 +5,6 @@ # @File : local_test # @Project : reActLLMDemo # @Desc : 本地终端运行对话 -import langgraph.store.memory from llmagent.assistant_graph import graph @@ -32,8 +31,8 @@ if __name__ == '__main__': break stream_graph_updates(user_input) - except: - user_input = "What do you know about LangGraph?" + except Exception as e: + user_input = f"出错了,系统提示{e}" print("User: " + user_input) stream_graph_updates(user_input) break