отправка END в API слое вместо service
This commit is contained in:
parent
3118e576da
commit
74e884179a
2 changed files with 9 additions and 18 deletions
|
|
@ -8,7 +8,6 @@ from lambda_agent_api.server import (
|
||||||
MsgEventToolCallChunk,
|
MsgEventToolCallChunk,
|
||||||
MsgEventToolResult,
|
MsgEventToolResult,
|
||||||
MsgEventSendFile,
|
MsgEventSendFile,
|
||||||
MsgEventEnd,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,23 +98,23 @@ class AgentService:
|
||||||
attachments_description = await self.__describe_attachments(attachments)
|
attachments_description = await self.__describe_attachments(attachments)
|
||||||
new_message += "\n" + attachments_description
|
new_message += "\n" + attachments_description
|
||||||
|
|
||||||
# Используем astream_events для перехвата детальных событий (инструменты, чанки и т.д.)
|
# astream_events, чтобы выходили промежуточные ивенты по мере их генерации
|
||||||
async for event in self._agent.astream_events(
|
async for event in self._agent.astream_events(
|
||||||
{"messages": [{"role": "user", "content": new_message}]},
|
{"messages": [{"role": "user", "content": new_message}]},
|
||||||
config=config,
|
config=config,
|
||||||
version="v2", # Обязательно v2 для современных версий LangChain
|
version="v2",
|
||||||
):
|
):
|
||||||
kind = event["event"]
|
kind = event["event"]
|
||||||
|
|
||||||
# 1. Агент генерирует токены (текст или аргументы для инструмента)
|
# пришли чанки от LLM
|
||||||
if kind == "on_chat_model_stream":
|
if kind == "on_chat_model_stream":
|
||||||
chunk = event["data"]["chunk"]
|
chunk = event["data"]["chunk"]
|
||||||
|
|
||||||
# Если генерируется обычный текст
|
# обычный текст
|
||||||
if chunk.content:
|
if chunk.content:
|
||||||
yield MsgEventTextChunk(text=chunk.content)
|
yield MsgEventTextChunk(text=chunk.content)
|
||||||
|
|
||||||
# Если агент решил использовать инструмент (Langchain выдает tool_call_chunks)
|
# если вернулся tool_call
|
||||||
if hasattr(chunk, "tool_call_chunks") and chunk.tool_call_chunks:
|
if hasattr(chunk, "tool_call_chunks") and chunk.tool_call_chunks:
|
||||||
for tool_chunk in chunk.tool_call_chunks:
|
for tool_chunk in chunk.tool_call_chunks:
|
||||||
yield MsgEventToolCallChunk(
|
yield MsgEventToolCallChunk(
|
||||||
|
|
@ -123,28 +122,20 @@ class AgentService:
|
||||||
args_chunk=tool_chunk.get("args"),
|
args_chunk=tool_chunk.get("args"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2. Инструмент завершил работу и вернул результат
|
# завершилось выполнение тула
|
||||||
elif kind == "on_tool_end":
|
elif kind == "on_tool_end":
|
||||||
result = event["data"].get("output")
|
result = event["data"].get("output")
|
||||||
|
|
||||||
"""# Перехватываем ссылку на авторизацию Composio v3
|
|
||||||
if result and "connect.composio.dev" in str(result):
|
|
||||||
yield MsgEventTextChunk(
|
|
||||||
text=f"\n⚠️ Для выполнения действия требуется авторизация. Перейдите по ссылке: {result}\n")
|
|
||||||
else:"""
|
|
||||||
yield MsgEventToolResult(
|
yield MsgEventToolResult(
|
||||||
tool_name=event["name"],
|
tool_name=event["name"],
|
||||||
result=str(result) # Страховка от ошибки сериализации JSON
|
result=str(result) # переводим в строку, потому что иногда приходит кривой json
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3. Кастомные события (send_file и др.)
|
# события, которые мы вызвали (например внутри тулов) через adispatch_custom_event
|
||||||
elif kind == "on_custom_event":
|
elif kind == "on_custom_event":
|
||||||
if event["name"] == "send_file":
|
if event["name"] == "send_file":
|
||||||
yield MsgEventSendFile(path=event["data"]["path"])
|
yield MsgEventSendFile(path=event["data"]["path"])
|
||||||
|
|
||||||
# 3. В конце генерации отправляем событие завершения
|
|
||||||
yield MsgEventEnd(tokens_used=0) # потом заменить на метадату
|
|
||||||
|
|
||||||
async def __describe_attachments(self, raw_paths: list[str]) -> str:
|
async def __describe_attachments(self, raw_paths: list[str]) -> str:
|
||||||
lines = []
|
lines = []
|
||||||
for raw_path in raw_paths:
|
for raw_path in raw_paths:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends
|
||||||
|
|
||||||
from lambda_agent_api.server import (
|
from lambda_agent_api.server import (
|
||||||
MsgStatus,
|
MsgStatus,
|
||||||
MsgEventTextChunk,
|
|
||||||
MsgEventEnd,
|
MsgEventEnd,
|
||||||
MsgError,
|
MsgError,
|
||||||
)
|
)
|
||||||
|
|
@ -45,3 +44,4 @@ async def process_message(ws: WebSocket, chat: AgentChat, msg):
|
||||||
case MsgUserMessage():
|
case MsgUserMessage():
|
||||||
async for chunk in chat.astream(msg.text, msg.attachments):
|
async for chunk in chat.astream(msg.text, msg.attachments):
|
||||||
await ws.send_text(chunk.model_dump_json())
|
await ws.send_text(chunk.model_dump_json())
|
||||||
|
await ws.send_text(MsgEventEnd(tokens_used=0).model_dump_json()) # TODO: подставить реальное потребление токенов
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue