main.py 6.4 KB

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