"""Agent 基类 — 100% 真实 LLM 调用 + 真实工具执行""" import json, time from openai import OpenAI from config import LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, MAX_TOOL_ROUNDS from tools import TOOL_SCHEMAS, execute_tool class Agent: def __init__(self, name: str, icon: str, system_prompt: str, tool_names: list, model: str = None): self.name = name self.icon = icon self.system_prompt = system_prompt self.model = model or LLM_MODEL self.tools = [TOOL_SCHEMAS[n] for n in tool_names if n in TOOL_SCHEMAS] self.tool_names = tool_names self.client = OpenAI(api_key=LLM_API_KEY, base_url=LLM_BASE_URL) def chat(self, messages: list, emit=None) -> str: """带工具循环的真实 LLM 调用""" full_messages = [{"role": "system", "content": self.system_prompt}] + messages for round_i in range(MAX_TOOL_ROUNDS): t0 = time.time() kwargs = {"model": self.model, "messages": full_messages, "temperature": 0.3, "max_tokens": 4000} if self.tools: kwargs["tools"] = self.tools kwargs["tool_choice"] = "auto" resp = self.client.chat.completions.create(**kwargs) msg = resp.choices[0].message latency = int((time.time() - t0) * 1000) tokens = resp.usage.total_tokens if resp.usage else 0 if emit: emit("llm_call", {"agent": self.name, "model": self.model, "latency_ms": latency, "tokens": tokens, "round": round_i + 1}) # 无工具调用 → 最终文本 if not msg.tool_calls: final = msg.content or "" if emit: emit("final_answer", {"agent": self.name, "answer": final, "rounds": round_i + 1}) return final # 有工具调用 → 逐个执行 full_messages.append(msg) for tc in msg.tool_calls: fn_name = tc.function.name try: fn_args = json.loads(tc.function.arguments) except json.JSONDecodeError: fn_args = {} t1 = time.time() result = execute_tool(fn_name, fn_args) tool_ms = int((time.time() - t1) * 1000) if emit: emit("tool_call", { "agent": self.name, "tool": fn_name, "args": fn_args, "result": result, "latency_ms": tool_ms, }) full_messages.append({"role": "tool", "tool_call_id": tc.id, "content": result}) return "[达到最大工具调用轮次限制]"