import json import httpx import openai import time base_url= "https://api.moonshot.cn/v1" api_key= "sk-xW0xjfQM6Mp9ZCWMLlnHiRJcpEOIZPTkXcN0dQ15xpZSuw2y" # 如有需要可放置独立密钥 class FormulaChatClient: def __init__(self, base_url: str, api_key: str): """初始化 Formula 客户端""" self.base_url = base_url self.api_key = api_key self.openai = openai.Client( base_url=base_url, api_key=api_key, ) self.httpx = httpx.Client( base_url=base_url, headers={"Authorization": f"Bearer {api_key}"}, timeout=30.0, ) self.model = "kimi-k2-thinking" def get_tools(self, formula_uri: str): """从 Formula API 获取工具定义""" response = self.httpx.get(f"/formulas/{formula_uri}/tools") response.raise_for_status() # 检查 HTTP 状态码 try: return response.json().get("tools", []) except json.JSONDecodeError as e: print(f"错误: 无法解析响应为 JSON (状态码: {response.status_code})") print(f"响应内容: {response.text[:500]}") raise def call_tool(self, formula_uri: str, function: str, args: dict): """调用官方工具""" response = self.httpx.post( f"/formulas/{formula_uri}/fibers", json={"name": function, "arguments": json.dumps(args)}, ) response.raise_for_status() # 检查 HTTP 状态码 fiber = response.json() if fiber.get("status", "") == "succeeded": return fiber["context"].get("output") or fiber["context"].get("encrypted_output") if "error" in fiber: return f"Error: {fiber['error']}" if "error" in fiber.get("context", {}): return f"Error: {fiber['context']['error']}" return "Error: Unknown error" def close(self): """关闭客户端连接""" self.httpx.close() # 初始化客户端 - 使用硬编码配置 base_url = "https://api.moonshot.cn/v1" api_key = "sk-xW0xjfQM6Mp9ZCWMLlnHiRJcpEOIZPTkXcN0dQ15xpZSuw2y" print(f"Base URL: {base_url}") print(f"API Key: {api_key[:10]}...{api_key[-10:] if len(api_key) > 20 else api_key}\n") # 等待一段时间避免并发限制 print("等待5秒避免组织并发限制...") time.sleep(5) client = FormulaChatClient(base_url, api_key) # 定义要使用的官方工具 Formula URI formula_uris = [ "moonshot/date:latest", "moonshot/web-search:latest" ] # 加载所有工具定义并建立映射 print("正在加载官方工具...") all_tools = [] tool_to_uri = {} # function.name -> formula_uri 的映射 for uri in formula_uris: try: tools = client.get_tools(uri) for tool in tools: func = tool.get("function") if func: func_name = func.get("name") if func_name: tool_to_uri[func_name] = uri all_tools.append(tool) print(f" 已加载工具: {func_name} from {uri}") except Exception as e: print(f" 警告: 加载工具 {uri} 失败: {e}") continue print(f"总共加载 {len(all_tools)} 个工具\n") if not all_tools: raise ValueError("未能加载任何工具,请检查 API 密钥和网络连接") # 初始化消息列表 messages = [ { "role": "system", "content": "你是 Kimi,一个专业的新闻分析师。你擅长收集、分析和整理信息,生成高质量的新闻报告。", }, ] # 用户请求生成今日新闻报告 user_request = "请帮我生成一份今日新闻报告,包含重要的科技、经济和社会新闻。" messages.append({ "role": "user", "content": user_request }) print(f"用户请求: {user_request}\n") max_iterations = 5 # 防止无限循环,减少API调用次数 for iteration in range(max_iterations): # 添加延迟避免速率限制 print(f"等待3秒避免速率限制...\n") time.sleep(3) # 调用模型 try: completion = client.openai.chat.completions.create( model=client.model, messages=messages, max_tokens=1024 * 32, tools=all_tools, temperature=1.0, ) except openai.AuthenticationError as e: print(f"认证错误: {e}") print("请检查 API key 是否正确,以及 API key 是否有权限访问该端点") raise except Exception as e: print(f"调用模型时发生错误: {e}") raise # 获取响应 message = completion.choices[0].message # 打印思考过程 if hasattr(message, "reasoning_content"): print(f"=============第 {iteration + 1} 轮思考开始=============") reasoning = getattr(message, "reasoning_content") if reasoning: print(reasoning[:500] + "..." if len(reasoning) > 500 else reasoning) print(f"=============第 {iteration + 1} 轮思考结束=============\n") # 添加 assistant 消息到上下文(保留 reasoning_content) messages.append(message) # 如果模型没有调用工具,说明对话结束 if not message.tool_calls: print("=============最终回答=============") print(message.content) break # 处理工具调用 print(f"模型决定调用 {len(message.tool_calls)} 个工具:\n") for tool_call in message.tool_calls: func_name = tool_call.function.name args = json.loads(tool_call.function.arguments) print(f"调用工具: {func_name}") print(f"参数: {json.dumps(args, ensure_ascii=False, indent=2)}") # 获取对应的 formula_uri formula_uri = tool_to_uri.get(func_name) if not formula_uri: print(f"错误: 找不到工具 {func_name} 对应的 Formula URI") continue # 调用工具 result = client.call_tool(formula_uri, func_name, args) # 打印结果(截断过长内容) if len(str(result)) > 200: print(f"工具结果: {str(result)[:200]}...\n") else: print(f"工具结果: {result}\n") # 添加工具结果到消息列表 tool_message = { "role": "tool", "tool_call_id": tool_call.id, "name": func_name, "content": result } messages.append(tool_message) print("\n对话完成!") # 清理资源 client.close()