отправка 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,
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -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: подставить реальное потребление токенов
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue