""" LLM客户端 - 调用大模型API """ import requests import json import time from typing import Dict, List, Optional class LLMClient: """大模型客户端""" def __init__( self, base_url: str = "http://192.168.2.17:19007/v1", api_key: str = "xxxx", model: str = "auto", timeout: int = 120 ): self.base_url = base_url.rstrip('/') self.api_key = api_key self.model = model self.timeout = timeout def chat( self, messages: List[Dict], temperature: float = 0.7, max_tokens: int = 4096, stream: bool = False ) -> Dict: """ 发送聊天请求 Args: messages: [{"role": "user/assistant/system", "content": "..."}] temperature: 温度参数 max_tokens: 最大token数 stream: 是否流式输出 Returns: {"content": "...", "usage": {...}} """ url = f"{self.base_url}/chat/completions" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}" } payload = { "model": self.model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens, "stream": stream } try: response = requests.post( url, headers=headers, json=payload, timeout=self.timeout, stream=stream ) if response.status_code != 200: return { "content": "", "error": f"API错误: {response.status_code} - {response.text}" } if stream: # 流式处理 content = "" for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('data: '): data = line[6:] if data == '[DONE]': break try: chunk = json.loads(data) if 'choices' in chunk and len(chunk['choices']) > 0: delta = chunk['choices'][0].get('delta', {}) if 'content' in delta: content += delta['content'] except json.JSONDecodeError: continue return {"content": content} else: data = response.json() content = data['choices'][0]['message']['content'] usage = data.get('usage', {}) return { "content": content, "usage": usage } except requests.Timeout: return {"content": "", "error": "请求超时"} except requests.RequestException as e: return {"content": "", "error": f"请求异常: {str(e)}"} def simple_chat(self, prompt: str, system_prompt: str = "") -> str: """ 简单聊天接口 Args: prompt: 用户输入 system_prompt: 系统提示 Returns: 模型回复文本 """ messages = [] if system_prompt: messages.append({"role": "system", "content": system_prompt}) messages.append({"role": "user", "content": prompt}) result = self.chat(messages) if "error" in result and result["error"]: raise Exception(result["error"]) return result["content"] def structured_output( self, prompt: str, schema: Dict, system_prompt: str = "" ) -> Dict: """ 结构化输出 Args: prompt: 用户输入 schema: 输出格式描述 system_prompt: 系统提示 Returns: 解析后的JSON对象 """ schema_text = json.dumps(schema, indent=2, ensure_ascii=False) full_system = system_prompt + "\n\n请按照以下JSON格式输出,不要输出其他内容:\n" + schema_text messages = [ {"role": "system", "content": full_system}, {"role": "user", "content": prompt} ] result = self.chat(messages, temperature=0.3) if "error" in result and result["error"]: raise Exception(result["error"]) content = result["content"].strip() # 尝试解析JSON try: # 去除可能的markdown代码块标记 if content.startswith('```'): lines = content.split('\n') content = '\n'.join(lines[1:-1] if lines[-1] == '```' else lines[1:]) return json.loads(content) except json.JSONDecodeError: # 尝试提取JSON部分 import re json_match = re.search(r'\{.*\}', content, re.DOTALL) if json_match: try: return json.loads(json_match.group()) except json.JSONDecodeError: pass return {"raw_content": content, "parse_error": "无法解析为JSON"} def analyze_intent(self, user_request: str) -> Dict: """ 分析用户意图 Args: user_request: 用户原始请求 Returns: {"intent": "...", "keywords": [...], "need_clarification": bool, "questions": [...]} """ system_prompt = """你是一个意图分析专家。分析用户的请求,判断: 1. 用户的核心意图是什么 2. 提取关键信息 3. 信息是否足够完整(不需要额外澄清) 4. 如果不完整,需要澄清的问题 请以JSON格式输出。""" schema = { "intent": "用户核心意图的简洁描述", "keywords": ["关键信息列表"], "need_clarification": "是否需要澄清 (true/false)", "questions": ["需要澄清的问题列表(如果need_clarification为true)"] } return self.structured_output( f"分析以下用户请求:\n\n{user_request}", schema, system_prompt ) def split_tasks(self, intent: Dict, user_request: str) -> List[Dict]: """ 任务拆分 Args: intent: 意图分析结果 user_request: 用户原始请求 Returns: [{"id": "...", "type": "serial/parallel", "description": "...", "dependencies": [...]}] """ system_prompt = """你是一个任务规划专家。根据用户意图,将请求拆分为多个子任务。 规则: 1. 识别任务之间的依赖关系 2. 无依赖的任务标记为parallel(可并行) 3. 有依赖的任务标记为serial(串行) 4. 每个任务有明确的描述 5. 每个任务有明确的输入输出要求 请以JSON格式输出任务列表。""" schema = { "tasks": [ { "id": "任务唯一标识(如task_1, task_2)", "type": "serial 或 parallel", "description": "任务描述", "input_schema": {"输入要求"}, "output_schema": {"输出要求"}, "dependencies": ["依赖的任务ID列表"] } ], "execution_order": ["任务执行顺序说明"] } result = self.structured_output( f"""用户原始请求: {user_request} 意图分析结果: {json.dumps(intent, indent=2, ensure_ascii=False)} 请拆分为子任务列表。""", schema, system_prompt ) return result.get("tasks", []) def generate_bid( self, task: Dict, agent_profile: Dict ) -> Dict: """ Agent生成竞标 Args: task: 任务定义 agent_profile: Agent档案 Returns: 竞标书内容 """ system_prompt = """你是一个执行Agent,需要为任务竞标。 评估你的能力和任务的匹配度,给出: 1. 能力匹配度(0-1) 2. 预估完成时间(秒) 3. 自信度(0-1) 4. 执行方案描述 5. 前置条件(如果有) 6. 备选方案(如果有) 请以JSON格式输出。""" schema = { "capability_match": "能力匹配度 0-1", "estimated_time": "预估完成时间(秒)", "confidence": "自信度 0-1", "approach": "执行方案描述", "prerequisites": ["前置条件列表"], "alternative_approaches": ["备选方案列表"] } result = self.structured_output( f"""任务: {json.dumps(task, indent=2, ensure_ascii=False)} 你的档案: {json.dumps(agent_profile, indent=2, ensure_ascii=False)} 请生成竞标书。""", schema, system_prompt ) return result def execute_task( self, task: Dict, approach: str = "" ) -> Dict: """ 执行任务 Args: task: 任务定义 approach: 执行方案 Returns: 执行结果 """ system_prompt = """你是一个任务执行者。根据任务描述和执行方案,完成任务并输出结果。 输出应该符合任务的output_schema要求。""" messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": f"""任务: {json.dumps(task, indent=2, ensure_ascii=False)} 执行方案: {approach} 请执行任务并输出结果。"""} ] result = self.chat(messages, temperature=0.5, max_tokens=8192) if "error" in result and result["error"]: return {"error": result["error"]} return {"result": result["content"]} def validate_result( self, task: Dict, result: Any ) -> Dict: """ 验证结果 Args: task: 任务定义 result: 执行结果 Returns: {"passed": bool, "issues": [...], "score": 0-1} """ system_prompt = """你是一个结果验证专家。评估执行结果是否符合任务要求。 判断: 1. 结果完整性(是否包含所有必要部分) 2. 结果正确性(是否符合预期) 3. 结果质量评分(0-1) 请以JSON格式输出。""" schema = { "passed": "是否通过验证 (true/false)", "completeness": "完整性检查结果", "correctness": "正确性检查结果", "issues": ["问题列表(如果未通过)"], "score": "质量评分 0-1", "suggestions": ["改进建议"] } return self.structured_output( f"""任务: {json.dumps(task, indent=2, ensure_ascii=False)} 执行结果: {json.dumps(result, indent=2, ensure_ascii=False) if isinstance(result, dict) else str(result)} 请验证结果。""", schema, system_prompt ) # 默认客户端实例 default_client = LLMClient()