diff --git a/README.md b/README.md index 9b8c5d7..7719021 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ uv sync docker run --name marqo -it --privileged -p 8882:8882 --add-host host.docker.internal:host-gateway marqoai/marqo:latest ``` -初始化:执行[vector_db.py](vector_db.py) create_and_set_index()方法 +初始化:执行[vector_db.py](src/vector_db.py) create_and_set_index()方法 -测试:执行[vector_db.py](vector_db.py) query_vector_db() 方法,参数为任意字符串 +测试:执行[vector_db.py](src/vector_db.py) query_vector_db() 方法,参数为任意字符串 4.配置文件 -[env.toml](env.toml) +[env.toml](src/env.toml) ```toml [base] @@ -57,11 +57,11 @@ streaming = true # 本地测试 -环境搭建完成后,本地运行[local_test.py](local_test.py) 即可在终端体验对话 +环境搭建完成后,本地运行[local_test.py](src/local_test.py) 即可在终端体验对话 # 服务端简单实现 -服务端使用fastapi实现,启动[server.py](server.py) 即可, 完整接口文档请访问 http://ip:port/docs +服务端使用fastapi实现,启动[server.py](src/server.py) 即可, 完整接口文档请访问 http://ip:port/docs 1. 建立sse连接,用于接收模型返回(流式) [GET] http://ip:port/sse/{client_id} diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..d55a32d --- /dev/null +++ b/src/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Time : 2025/4/17 15:40 +# @Author : old-tom +# @File : __init__.py +# @Project : reActLLMDemo +# @Desc : diff --git a/env.toml b/src/env.toml similarity index 83% rename from env.toml rename to src/env.toml index 5c82f06..bb476ff 100644 --- a/env.toml +++ b/src/env.toml @@ -3,6 +3,8 @@ similarity_threshold = 0.93 # 模型供应商 model_form = 'siliconflow' +# 提示词类型(普通,较为宽松的场景:SMART_ASSISTANT 强制使用工具:SMART_ASSISTANT_STRICT) +prompt_type = 'SMART_ASSISTANT' [siliconflow] # 硅基流动 diff --git a/llmagent/__init__.py b/src/llmagent/__init__.py similarity index 52% rename from llmagent/__init__.py rename to src/llmagent/__init__.py index 39fca0c..e41fb2b 100644 --- a/llmagent/__init__.py +++ b/src/llmagent/__init__.py @@ -6,9 +6,9 @@ # @Project : reActLLMDemo # @Desc : from langchain_openai import ChatOpenAI -from llmagent.llm_config import LLMConfigLoader -from llmagent.llm_config import base_conf -from llmtools import tools +from src.llmagent.llm_config import LLMConfigLoader +from src.llmagent.llm_config import base_conf +from src.llmtools import tools # 初始化LLM模型 llm_conf = LLMConfigLoader.load(item_name=base_conf.model_form) @@ -24,7 +24,7 @@ llm_with_tools = llm.bind_tools(tools) # 提示词模版 PROMPT_TEMPLATE = { 'SMART_ASSISTANT': { - 'description': '智能助手', + 'description': '普通版本提示词', 'template': """ 你是智能助手,用户将会告诉你一条指令,你需要根据指令分析意图并完成任务。 @@ -35,8 +35,8 @@ PROMPT_TEMPLATE = { 3. 当询问你的功能时,你可以通过工具列表分析自己的功能并生成清晰的回答 # 任务规则 - 1. 根据指令分析意图并判断是否使用工具,如果不需要使用工具请直接回答 - 2. 如果需要使用工具,根据指令和提供的工具描述选择最合适的工具,仔细阅读工具参数说明,正确的解析参数并评估用户输入的参数是否满足条件,如果参数不满足则需要提示用户重新发出指令。 + 1. 根据指令分析意图并判断是否使用工具,如果不需要使用工具请提供简洁、清晰明了的回答 + 2. 如果需要使用工具,根据指令和提供的工具描述选择最合适的工具,仔细阅读工具参数说明,正确的解析参数。 3. 所有返回禁止包含xml标签、markdown、html、json格式 4. 有时候需要分析用户的上一轮指令并结合当前指令判断用户的意图 5. 你有足够的时间思考和回答用户的查询,从而给出更周全和深入的答案。然而,要知道你推理和处理的时间越长,相关的资源成本和潜在后果就越大。虽然你不应该仓促,但要在推理深度和效率之间寻求平衡。优先提供一个深思熟虑的答案,但如果通过合理的分析就能提供答案,就不要过度思考。明智地利用你的推理时间,专注于提供准确答案所必需的东西,避免不必要的拖延和过度思考 @@ -48,5 +48,29 @@ PROMPT_TEMPLATE = { 4. 在任何情况下,都不要修改或扩展提供的工具参数 5. 所有工具参数禁止使用unicode编码 """ + }, + 'SMART_ASSISTANT_STRICT': { + 'description': '严格版本提示词,强制使用工具', + 'template': """ + 你是智能助手,用户将会告诉你一条指令,你需要根据指令分析意图并完成任务。 + + # 背景 + 1. 现在时间是{current_time} + 2. 无论怎样询问你的身份, 请记住你是由盛视科技开发的智能助手 + 3. 当询问你的功能时,你可以通过工具列表分析自己的功能并生成清晰的回答 + + # 任务规则 + 1. 根据指令和提供的工具描述选择最合适的工具,仔细阅读工具参数说明,正确的解析参数并评估用户输入的参数是否满足条件,如果参数不满足则需要提示用户重新发出指令。 + 2. 所有返回禁止包含xml标签、markdown、html、json格式 + 3. 有时候需要分析用户的上一轮指令并结合当前指令判断用户的意图 + 4. 你有足够的时间思考和回答用户的查询,从而给出更周全和深入的答案。然而,要知道你推理和处理的时间越长,相关的资源成本和潜在后果就越大。虽然你不应该仓促,但要在推理深度和效率之间寻求平衡。优先提供一个深思熟虑的答案,但如果通过合理的分析就能提供答案,就不要过度思考。明智地利用你的推理时间,专注于提供准确答案所必需的东西,避免不必要的拖延和过度思考 + + # 工具使用规则 + 1. 每条消息可以使用一个工具 + 2. 在每次使用工具后,切勿假设工具使用成功,禁止猜测工具结果。 + 3. 根据工具返回的内容组装逻辑清晰的回答。 + 4. 在任何情况下,都不要修改或扩展提供的工具参数 + 5. 所有工具参数禁止使用unicode编码 + """ } } diff --git a/llmagent/assistant_graph.py b/src/llmagent/assistant_graph.py similarity index 93% rename from llmagent/assistant_graph.py rename to src/llmagent/assistant_graph.py index ea3c753..d2298c9 100644 --- a/llmagent/assistant_graph.py +++ b/src/llmagent/assistant_graph.py @@ -5,12 +5,13 @@ # @File : llm_agent # @Project : reActLLMDemo # @Desc : 用图构建ReAct +import os from typing import Annotated from langgraph.checkpoint.memory import MemorySaver -from llmagent import llm_with_tools, PROMPT_TEMPLATE -from llmtools import tool_node +from src.llmagent import llm_with_tools, PROMPT_TEMPLATE +from src.llmtools import tool_node from langchain_core.messages import AnyMessage, SystemMessage from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END @@ -35,7 +36,7 @@ memory = MemorySaver() class AgentState(TypedDict): """ 状态机 - add_messages 函数会自动合并message到一个list中,例如HumanMessage\AIMessage + add_messages 函数会自动合并message到一个list中,例如HumanMessage或AIMessage """ messages: Annotated[list[AnyMessage], add_messages] @@ -67,4 +68,4 @@ graph_builder.add_edge("chat_llm", END) graph_builder.add_conditional_edges("chat_llm", tools_condition) graph_builder.add_edge("tools", "chat_llm") # checkpointer 是检查点设置 -graph = graph_builder.compile(name='smart_assistant', checkpointer=memory) +graph = graph_builder.compile(name='smart_assistant', checkpointer=memory) \ No newline at end of file diff --git a/llmagent/llm_config.py b/src/llmagent/llm_config.py similarity index 98% rename from llmagent/llm_config.py rename to src/llmagent/llm_config.py index 273953d..d2f8efe 100644 --- a/llmagent/llm_config.py +++ b/src/llmagent/llm_config.py @@ -58,6 +58,7 @@ class LLMConfigLoader(object): class BaseConf(BaseModel): similarity_threshold: float model_form: str + prompt_type: str base_conf = BaseConf(**conf['base']) diff --git a/llmtools/__init__.py b/src/llmtools/__init__.py similarity index 77% rename from llmtools/__init__.py rename to src/llmtools/__init__.py index 960b74a..f3b2407 100644 --- a/llmtools/__init__.py +++ b/src/llmtools/__init__.py @@ -5,7 +5,7 @@ # @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 src.llmtools.tool_impl import play_video, split_screen, play_video_record, switch_page, zoom_in, view_flight_details from langgraph.prebuilt import ToolNode # 工具列表 diff --git a/llmtools/tool_impl.py b/src/llmtools/tool_impl.py similarity index 88% rename from llmtools/tool_impl.py rename to src/llmtools/tool_impl.py index dfcd09e..91ab311 100644 --- a/llmtools/tool_impl.py +++ b/src/llmtools/tool_impl.py @@ -8,9 +8,9 @@ from typing import Annotated 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 src.vector_db import query_vector_db +from src.log_conf import log +from src.llmagent.llm_config import base_conf @tool("play_video", description="播放、查看、打开实时视频") @@ -29,12 +29,14 @@ def play_video(camera_name: Annotated[str, "相机名称,例如:南卡口1号 @tool("split_screen", description="切换分屏") -def split_screen(split_n: Annotated[int, "要切换的分屏数量,整数并且大于0,例如:1分屏、2分屏。如果是中文,例如:壹、贰、参需要转为数字形式"]) -> str: +def split_screen(split_n: Annotated[ + int, "要切换的分屏数量,整数并且大于0,例如:1分屏、2分屏。如果是中文,例如:壹、贰、参需要转为数字形式"]) -> str: return f"【tool_back】正在切换到{split_n}分屏,请等待操作完成" @tool("play_video_record", description="播放、打开录像") -def play_video_record(camera_name: Annotated[str, "相机名称,例如:南卡口1号相机,如果没有提供时间,结束时间为当前时间,开始时间为当前时间往前5分钟"], +def play_video_record(camera_name: Annotated[ + str, "相机名称,例如:南卡口1号相机,如果没有提供时间,结束时间为当前时间,开始时间为当前时间往前5分钟"], 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) diff --git a/local_test.py b/src/local_test.py similarity index 100% rename from local_test.py rename to src/local_test.py diff --git a/log_conf.py b/src/log_conf.py similarity index 94% rename from log_conf.py rename to src/log_conf.py index 26abb9b..d595b15 100644 --- a/log_conf.py +++ b/src/log_conf.py @@ -10,7 +10,8 @@ import sys import os from loguru import logger -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +# 当前目录上一层 +BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 日志输出路径 LOG_PATH = os.path.join(BASE_DIR, r'logout/logout.log') diff --git a/server.py b/src/server.py similarity index 100% rename from server.py rename to src/server.py diff --git a/vector_db.py b/src/vector_db.py similarity index 100% rename from vector_db.py rename to src/vector_db.py