message_util.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. """
  2. This module provides utility functions for working with messages in the OpenAI API.
  3. Functions:
  4. - new_message(role: str, content: str) -> dict: Creates a new message with the specified role and content.
  5. - system_message(content: str) -> dict: Creates a system message with the specified content.
  6. - user_message(content: str) -> dict: Creates a user message with the specified content.
  7. - assistant_message(content: str) -> dict: Creates an assistant message with the specified content.
  8. - tool_calls(tool_calls) -> dict: Creates a message with assistant tool calls.
  9. - tool_call_result(id, content) -> dict: Creates a tool call result message with the specified ID and content.
  10. - is_tool_call(message: ChatCompletionMessage) -> bool: Checks if a message is a tool call.
  11. """
  12. from openai.types.chat import ChatCompletionMessage, ChatCompletionMessageToolCall
  13. from openai.types.chat.chat_completion_message_tool_call import Function
  14. def new_message(role: str, content: str, reasoning_content=None):
  15. if role != "user" and role != "system" and role != "assistant":
  16. raise ValueError(f"Invalid role {role}")
  17. if reasoning_content is None:
  18. return {"role": role, "content": content}
  19. else:
  20. return {"role": role, "content": content, "reasoning_content": reasoning_content}
  21. def system_message(content: str):
  22. return new_message("system", content)
  23. def user_message(content: str):
  24. return new_message("user", content)
  25. def assistant_message(content: str):
  26. return new_message("assistant", content)
  27. def tool_calls(tool_calls, reasoning_content=None):
  28. if reasoning_content is None:
  29. return {"role": "assistant", "tool_calls": tool_calls}
  30. else:
  31. return {"role": "assistant", "tool_calls": tool_calls, "reasoning_content": reasoning_content}
  32. def tool_call_result(id, content):
  33. return {"role": "tool", "tool_call_id": id, "content": content}
  34. def is_tool_call(message: ChatCompletionMessage) -> bool:
  35. return bool(message.tool_calls)
  36. def merge_tool_call_delta(tool_calls, tool_call_delta):
  37. index = getattr(tool_call_delta, "index", None)
  38. if index is None:
  39. # 尝试通过 id 匹配已有工具调用
  40. if tool_call_delta.id:
  41. for i, tc in enumerate(tool_calls):
  42. if tc.id == tool_call_delta.id:
  43. index = i
  44. break
  45. # 若仍找不到,根据列表长度决定
  46. if index is None:
  47. index = 0 if len(tool_calls) == 0 else len(tool_calls) - 1
  48. if len(tool_calls) - 1 >= index:
  49. tool_call = tool_calls[index]
  50. # 确保 arguments 为字符串,避免 None 导致拼接失败
  51. tool_call.function.arguments = (tool_call.function.arguments or "") + (
  52. tool_call_delta.function.arguments or ""
  53. )
  54. else:
  55. tool_call = ChatCompletionMessageToolCall(
  56. id=tool_call_delta.id,
  57. function=Function(
  58. name=tool_call_delta.function.name,
  59. arguments=tool_call_delta.function.arguments or "",
  60. ),
  61. type=tool_call_delta.type,
  62. )
  63. tool_calls.append(tool_call)
  64. # 调试输出可保留,但建议移除或降级为 debug
  65. print("=" * 40)
  66. print(tool_calls)