ForcePilot/src/agents/chatbot/graph.py

87 lines
3.2 KiB
Python
Raw Normal View History

2025-03-24 23:00:14 +08:00
import asyncio
import uuid
from typing import Any
2025-04-02 13:00:25 +08:00
from datetime import datetime, timezone
2025-03-24 19:07:51 +08:00
from langchain_core.runnables import RunnableConfig
2025-03-24 23:00:14 +08:00
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
2025-04-02 00:00:04 +08:00
from langgraph.checkpoint.memory import MemorySaver # 实际上没有起作用
2025-03-29 17:33:09 +08:00
2025-03-24 19:07:51 +08:00
2025-04-02 13:00:25 +08:00
from src.utils import logger
2025-03-24 19:07:51 +08:00
from src.agents.registry import State, BaseAgent
2025-04-02 13:00:25 +08:00
from src.agents.utils import load_chat_model, get_cur_time_with_utc
from src.agents.chatbot.configuration import ChatbotConfiguration
2025-04-02 00:00:04 +08:00
from src.agents.tools_factory import _TOOLS_REGISTRY
2025-03-24 19:07:51 +08:00
class ChatbotAgent(BaseAgent):
2025-03-25 05:40:07 +08:00
name = "chatbot"
description = "A chatbot that can answer questions and help with tasks."
requirements = ["TAVILY_API_KEY", "ZHIPUAI_API_KEY"]
2025-04-02 13:00:25 +08:00
all_tools = ["TavilySearchResults", "multiply", "add", "subtract", "divide"]
config_schema = ChatbotConfiguration
2025-03-24 23:00:14 +08:00
2025-03-28 11:40:46 +08:00
def __init__(self, **kwargs):
super().__init__(**kwargs)
2025-03-25 05:40:07 +08:00
2025-03-28 11:40:46 +08:00
def _get_tools(self, config_schema: RunnableConfig):
2025-04-02 13:00:25 +08:00
"""根据配置获取工具,如果配置为空,则使用所有工具,如果配置为列表,则使用列表中的工具,
如果配置为其他类型则抛出错误"""
conf_tools = config_schema.get("tools")
if conf_tools == None:
tool_names = self.all_tools
elif isinstance(conf_tools, list):
tool_names = [tool for tool in self.all_tools if tool in conf_tools]
else:
raise ValueError(f"tools 配置错误: {conf_tools}")
logger.info(f"Tools: {tool_names}")
return [_TOOLS_REGISTRY[tool] for tool in tool_names]
2025-03-25 05:40:07 +08:00
2025-03-29 17:33:09 +08:00
def llm_call(self, state: State, config: RunnableConfig = None) -> dict[str, Any]:
"""调用 llm 模型"""
config_schema = config or {}
conf = self.config_schema.from_runnable_config(config_schema)
2025-04-02 13:00:25 +08:00
system_prompt = f"{conf.system_prompt} Now is {get_cur_time_with_utc()}"
model = load_chat_model(conf.model)
2025-03-29 17:33:09 +08:00
model_with_tools = model.bind_tools(self._get_tools(config_schema))
2025-04-02 13:00:25 +08:00
logger.info(f"llm_call with config: {conf}, {conf.model}")
2025-03-25 05:40:07 +08:00
2025-03-29 17:33:09 +08:00
res = model_with_tools.invoke(
2025-04-02 13:00:25 +08:00
[{"role": "system", "content": system_prompt}, *state["messages"]]
2025-03-29 17:33:09 +08:00
)
2025-03-24 23:00:14 +08:00
return {"messages": [res]}
def get_graph(self, config_schema: RunnableConfig = None, **kwargs):
2025-03-24 23:00:14 +08:00
"""构建图"""
workflow = StateGraph(State, config_schema=self.config_schema)
2025-03-25 05:40:07 +08:00
workflow.add_node("chatbot", self.llm_call)
2025-03-28 11:40:46 +08:00
workflow.add_node("tools", ToolNode(tools=self._get_tools(config_schema)))
2025-03-25 05:40:07 +08:00
workflow.add_edge(START, "chatbot")
workflow.add_conditional_edges(
"chatbot",
tools_condition,
)
workflow.add_edge("tools", "chatbot")
workflow.add_edge("chatbot", END)
graph = workflow.compile(checkpointer=MemorySaver())
return graph
2025-03-24 23:00:14 +08:00
def main():
agent = ChatbotAgent(ChatbotConfiguration())
2025-03-24 19:07:51 +08:00
2025-03-24 23:00:14 +08:00
thread_id = str(uuid.uuid4())
config = {"configurable": {"thread_id": thread_id}}
2025-03-24 19:07:51 +08:00
2025-03-25 05:40:07 +08:00
from src.agents.utils import agent_cli
2025-03-24 23:00:14 +08:00
agent_cli(agent, config)
2025-03-24 19:07:51 +08:00
2025-03-24 23:00:14 +08:00
if __name__ == "__main__":
main()
# asyncio.run(main())