отправка END в API слое вместо service

This commit is contained in:
Егор Кандрушин 2026-04-27 13:54:55 +03:00
parent 3118e576da
commit 74e884179a
2 changed files with 9 additions and 18 deletions

View file

@ -8,7 +8,6 @@ from lambda_agent_api.server import (
MsgEventToolCallChunk,
MsgEventToolResult,
MsgEventSendFile,
MsgEventEnd,
)
@ -99,23 +98,23 @@ class AgentService:
attachments_description = await self.__describe_attachments(attachments)
new_message += "\n" + attachments_description
# Используем astream_events для перехвата детальных событий (инструменты, чанки и т.д.)
# astream_events, чтобы выходили промежуточные ивенты по мере их генерации
async for event in self._agent.astream_events(
{"messages": [{"role": "user", "content": new_message}]},
config=config,
version="v2", # Обязательно v2 для современных версий LangChain
version="v2",
):
kind = event["event"]
# 1. Агент генерирует токены (текст или аргументы для инструмента)
# пришли чанки от LLM
if kind == "on_chat_model_stream":
chunk = event["data"]["chunk"]
# Если генерируется обычный текст
# обычный текст
if chunk.content:
yield MsgEventTextChunk(text=chunk.content)
# Если агент решил использовать инструмент (Langchain выдает tool_call_chunks)
# если вернулся tool_call
if hasattr(chunk, "tool_call_chunks") and chunk.tool_call_chunks:
for tool_chunk in chunk.tool_call_chunks:
yield MsgEventToolCallChunk(
@ -123,28 +122,20 @@ class AgentService:
args_chunk=tool_chunk.get("args"),
)
# 2. Инструмент завершил работу и вернул результат
# завершилось выполнение тула
elif kind == "on_tool_end":
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(
tool_name=event["name"],
result=str(result) # Страховка от ошибки сериализации JSON
result=str(result) # переводим в строку, потому что иногда приходит кривой json
)
# 3. Кастомные события (send_file и др.)
# события, которые мы вызвали (например внутри тулов) через adispatch_custom_event
elif kind == "on_custom_event":
if event["name"] == "send_file":
yield MsgEventSendFile(path=event["data"]["path"])
# 3. В конце генерации отправляем событие завершения
yield MsgEventEnd(tokens_used=0) # потом заменить на метадату
async def __describe_attachments(self, raw_paths: list[str]) -> str:
lines = []
for raw_path in raw_paths:

View file

@ -4,7 +4,6 @@ from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends
from lambda_agent_api.server import (
MsgStatus,
MsgEventTextChunk,
MsgEventEnd,
MsgError,
)
@ -45,3 +44,4 @@ async def process_message(ws: WebSocket, chat: AgentChat, msg):
case MsgUserMessage():
async for chunk in chat.astream(msg.text, msg.attachments):
await ws.send_text(chunk.model_dump_json())
await ws.send_text(MsgEventEnd(tokens_used=0).model_dump_json()) # TODO: подставить реальное потребление токенов