feat:lpmm可选接入memory agent,将memory agent改为标准工具格式,修改llm_utils以兼容
This commit is contained in:
@@ -77,6 +77,23 @@ def _convert_messages(messages: list[Message]) -> list[ChatCompletionMessagePara
|
||||
"content": content,
|
||||
}
|
||||
|
||||
if message.role == RoleType.Assistant and getattr(message, "tool_calls", None):
|
||||
tool_calls_payload: list[dict[str, Any]] = []
|
||||
for call in message.tool_calls or []:
|
||||
tool_calls_payload.append(
|
||||
{
|
||||
"id": call.call_id,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": call.func_name,
|
||||
"arguments": json.dumps(call.args or {}, ensure_ascii=False),
|
||||
},
|
||||
}
|
||||
)
|
||||
ret["tool_calls"] = tool_calls_payload
|
||||
if ret["content"] == []:
|
||||
ret["content"] = ""
|
||||
|
||||
# 添加工具调用ID
|
||||
if message.role == RoleType.Tool:
|
||||
if not message.tool_call_id:
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
from .tool_option import ToolCall
|
||||
|
||||
|
||||
# 设计这系列类的目的是为未来可能的扩展做准备
|
||||
@@ -20,6 +23,7 @@ class Message:
|
||||
role: RoleType,
|
||||
content: str | list[tuple[str, str] | str],
|
||||
tool_call_id: str | None = None,
|
||||
tool_calls: Optional[List[ToolCall]] = None,
|
||||
):
|
||||
"""
|
||||
初始化消息对象
|
||||
@@ -28,6 +32,13 @@ class Message:
|
||||
self.role: RoleType = role
|
||||
self.content: str | list[tuple[str, str] | str] = content
|
||||
self.tool_call_id: str | None = tool_call_id
|
||||
self.tool_calls: Optional[List[ToolCall]] = tool_calls
|
||||
|
||||
def __str__(self) -> str:
|
||||
return (
|
||||
f"Role: {self.role}, Content: {self.content}, "
|
||||
f"Tool Call ID: {self.tool_call_id}, Tool Calls: {self.tool_calls}"
|
||||
)
|
||||
|
||||
|
||||
class MessageBuilder:
|
||||
@@ -35,6 +46,7 @@ class MessageBuilder:
|
||||
self.__role: RoleType = RoleType.User
|
||||
self.__content: list[tuple[str, str] | str] = []
|
||||
self.__tool_call_id: str | None = None
|
||||
self.__tool_calls: Optional[List[ToolCall]] = None
|
||||
|
||||
def set_role(self, role: RoleType = RoleType.User) -> "MessageBuilder":
|
||||
"""
|
||||
@@ -86,12 +98,27 @@ class MessageBuilder:
|
||||
self.__tool_call_id = tool_call_id
|
||||
return self
|
||||
|
||||
def set_tool_calls(self, tool_calls: List[ToolCall]) -> "MessageBuilder":
|
||||
"""
|
||||
设置助手消息的工具调用列表
|
||||
:param tool_calls: 工具调用列表
|
||||
:return: MessageBuilder对象
|
||||
"""
|
||||
if self.__role != RoleType.Assistant:
|
||||
raise ValueError("仅当角色为Assistant时才能设置工具调用列表")
|
||||
if not tool_calls:
|
||||
raise ValueError("工具调用列表不能为空")
|
||||
self.__tool_calls = tool_calls
|
||||
return self
|
||||
|
||||
def build(self) -> Message:
|
||||
"""
|
||||
构建消息对象
|
||||
:return: Message对象
|
||||
"""
|
||||
if len(self.__content) == 0:
|
||||
if len(self.__content) == 0 and not (
|
||||
self.__role == RoleType.Assistant and self.__tool_calls
|
||||
):
|
||||
raise ValueError("内容不能为空")
|
||||
if self.__role == RoleType.Tool and self.__tool_call_id is None:
|
||||
raise ValueError("Tool角色的工具调用ID不能为空")
|
||||
@@ -104,4 +131,5 @@ class MessageBuilder:
|
||||
else self.__content
|
||||
),
|
||||
tool_call_id=self.__tool_call_id,
|
||||
tool_calls=self.__tool_calls,
|
||||
)
|
||||
|
||||
@@ -166,6 +166,57 @@ class LLMRequest:
|
||||
time_cost=time.time() - start_time,
|
||||
)
|
||||
return content or "", (reasoning_content, model_info.name, tool_calls)
|
||||
|
||||
async def generate_response_with_message_async(
|
||||
self,
|
||||
message_factory: Callable[[BaseClient], List[Message]],
|
||||
temperature: Optional[float] = None,
|
||||
max_tokens: Optional[int] = None,
|
||||
tools: Optional[List[Dict[str, Any]]] = None,
|
||||
raise_when_empty: bool = True,
|
||||
) -> Tuple[str, Tuple[str, str, Optional[List[ToolCall]]]]:
|
||||
"""
|
||||
异步生成响应
|
||||
Args:
|
||||
message_factory (Callable[[BaseClient], List[Message]]): 已构建好的消息工厂
|
||||
temperature (float, optional): 温度参数
|
||||
max_tokens (int, optional): 最大token数
|
||||
tools (Optional[List[Dict[str, Any]]]): 工具列表
|
||||
raise_when_empty (bool): 当响应为空时是否抛出异常
|
||||
Returns:
|
||||
(Tuple[str, str, str, Optional[List[ToolCall]]]): 响应内容、推理内容、模型名称、工具调用列表
|
||||
"""
|
||||
start_time = time.time()
|
||||
|
||||
tool_built = self._build_tool_options(tools)
|
||||
|
||||
response, model_info = await self._execute_request(
|
||||
request_type=RequestType.RESPONSE,
|
||||
message_factory=message_factory,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
tool_options=tool_built,
|
||||
)
|
||||
|
||||
logger.debug(f"LLM请求总耗时: {time.time() - start_time}")
|
||||
logger.debug(f"LLM生成内容: {response}")
|
||||
|
||||
content = response.content
|
||||
reasoning_content = response.reasoning_content or ""
|
||||
tool_calls = response.tool_calls
|
||||
if not reasoning_content and content:
|
||||
content, extracted_reasoning = self._extract_reasoning(content)
|
||||
reasoning_content = extracted_reasoning
|
||||
if usage := response.usage:
|
||||
llm_usage_recorder.record_usage_to_database(
|
||||
model_info=model_info,
|
||||
model_usage=usage,
|
||||
user_id="system",
|
||||
request_type=self.request_type,
|
||||
endpoint="/chat/completions",
|
||||
time_cost=time.time() - start_time,
|
||||
)
|
||||
return content or "", (reasoning_content, model_info.name, tool_calls)
|
||||
|
||||
async def get_embedding(self, embedding_input: str) -> Tuple[List[float], str]:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user