main.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import openai
  2. import json
  3. from tools import Tools
  4. with open('key.json', 'r', encoding='utf-8') as f:
  5. config = json.load(f)
  6. openai_url = config.get("openai_url")
  7. api_key = config.get("api_key")
  8. model = config.get("model")
  9. client = openai.OpenAI(
  10. base_url=openai_url,
  11. api_key=api_key,
  12. )
  13. tool = Tools()
  14. # 流式输出处理函数
  15. def stream_response(messages, tools=None):
  16. full_response = ""
  17. tool_calls = []
  18. # 使用client对象调用API
  19. response = client.chat.completions.create(
  20. model=model,
  21. messages=messages,
  22. tools=tools,
  23. tool_choice="auto",
  24. stream=True
  25. )
  26. # 处理流式响应
  27. for chunk in response:
  28. # 提取delta内容
  29. delta = chunk.choices[0].delta
  30. # 处理文本内容(最终回答)
  31. if hasattr(delta, 'content') and delta.content:
  32. content = delta.content
  33. full_response += content
  34. print(content, end="", flush=True) # 实时输出到控制台
  35. # 处理工具调用(tool_calls)
  36. if hasattr(delta, 'tool_calls') and delta.tool_calls:
  37. for tool_call in delta.tool_calls:
  38. # 初始化tool_calls数组(如果需要)
  39. while len(tool_calls) <= tool_call.index:
  40. tool_calls.append({
  41. "id": "",
  42. "type": "function",
  43. "function": {
  44. "name": "",
  45. "arguments": ""
  46. }
  47. })
  48. # 更新工具调用信息
  49. if tool_call.id:
  50. tool_calls[tool_call.index]["id"] = tool_call.id
  51. if tool_call.function:
  52. if tool_call.function.name:
  53. tool_calls[tool_call.index]["function"]["name"] = tool_call.function.name
  54. if tool_call.function.arguments:
  55. tool_calls[tool_call.index]["function"]["arguments"] += tool_call.function.arguments
  56. # 如果有工具调用,处理并返回
  57. if tool_calls:
  58. # 解析工具调用参数并执行
  59. executed_tools = []
  60. for tool_call in tool_calls:
  61. try:
  62. arguments = json.loads(tool_call["function"]["arguments"])
  63. except json.JSONDecodeError:
  64. arguments = {}
  65. tool_name = tool_call["function"]["name"]
  66. tool_id = tool_call["id"]
  67. # 执行工具
  68. tool_result = tool.call_tool(tool_name, arguments)
  69. executed_tools.append({
  70. "name": tool_name,
  71. "arguments": arguments,
  72. "result": tool_result,
  73. "id": tool_id
  74. })
  75. return {
  76. "content": full_response,
  77. "tool_calls": executed_tools
  78. }
  79. # 返回完整响应和工具调用信息
  80. return {
  81. "content": full_response,
  82. "tool_calls": None
  83. }
  84. # 主函数:处理多轮工具调用的流式输出
  85. def run_conversation(messages):
  86. # 系统提示
  87. system_prompt = """
  88. 你是一个可以调用工具的AI助手。请根据用户需求,判断是否需要调用工具:
  89. 1. 若需要,可调用工具列表中的工具(可多次调用,直到获取足够信息);
  90. 2. 调用工具后,需等待工具返回结果,再决定是否继续调用或整理结果回答用户;
  91. 3. 工具返回结果会以函数消息的形式提供给你,请基于所有信息生成最终回答。
  92. 你的回答需要保持严谨和专业,假如你无法从工具调用结果和系统提示中获取足够的信息,请不要随意回答,请直接告诉用户暂无详情
  93. """
  94. # 添加系统提示到消息历史(如果还没有)
  95. if not any(msg.get("role") == "system" for msg in messages):
  96. messages.insert(0, {"role": "system", "content": system_prompt})
  97. print("\n🤖 助手: ", end="", flush=True)
  98. # 多轮工具调用循环
  99. while True:
  100. # 流式获取模型响应
  101. response = stream_response(messages, tool.get_tool_list())
  102. # 检查是否需要调用工具
  103. if response["tool_calls"]:
  104. tool_calls = response["tool_calls"]
  105. # 添加助手的工具调用到消息历史
  106. tool_call_list = []
  107. for tool_call in tool_calls:
  108. tool_call_list.append({
  109. "id": tool_call["id"],
  110. "type": "function",
  111. "function": {
  112. "name": tool_call["name"],
  113. "arguments": json.dumps(tool_call["arguments"])
  114. }
  115. })
  116. messages.append({
  117. "role": "assistant",
  118. "tool_calls": tool_call_list
  119. })
  120. # 执行所有工具并将结果添加到对话历史
  121. for tool_call in tool_calls:
  122. tool_name = tool_call["name"]
  123. tool_result = tool_call["result"]
  124. tool_id = tool_call["id"]
  125. messages.append({
  126. "role": "tool",
  127. "tool_call_id": tool_id,
  128. "name": tool_name,
  129. "content": tool_result
  130. })
  131. print(f"\n\n🔍 工具结果 ({tool_name}): {tool_result}")
  132. print("\n🤖 助手: ", end="", flush=True)
  133. else:
  134. # 没有工具调用,对话结束
  135. messages.append({
  136. "role": "assistant",
  137. "content": response["content"]
  138. })
  139. break
  140. return response["content"]
  141. # 多轮对话主循环
  142. def main():
  143. # 初始化对话历史
  144. messages = []
  145. print("开始多轮对话(输入'exit'结束对话)")
  146. while True:
  147. user_input = input("\n👨‍💻 用户: ").strip()
  148. if user_input.lower() in ['退出', 'quit', 'exit']:
  149. print("对话结束")
  150. break
  151. if user_input:
  152. messages.append({"role": "user", "content": user_input})
  153. run_conversation(messages)
  154. else:
  155. print("请输入有效内容")
  156. # 示例:运行对话
  157. if __name__ == "__main__":
  158. main()