обновленный README

This commit is contained in:
Егор Кандрушин 2026-04-02 00:59:41 +03:00
parent 1e256a545b
commit f9289b92fa

125
README.md
View file

@ -1,11 +1,13 @@
from lambda_agent_api import AgentApi
# Lambda Agent API # Lambda Agent API
WebSocket API SDK для взаимодействия с AI-агентом. WebSocket API SDK для взаимодействия с AI-агентом.
## Установка ## Установка
В `master` всегда будет актуальная рабочая версия.
```bash ```bash
pip install . pip install git+https://git.lambda.coredump.ru/platform/agent_api.git
``` ```
Требуется Python 3.14+. Требуется Python 3.14+.
@ -14,32 +16,22 @@ pip install .
```python ```python
import asyncio import asyncio
from lambda_agent_api.agent_api import AgentApi, OM
from lambda_agent_api.agent_api import AgentApi
def my_callback(message): from lambda_agent_api.server import MsgEventTextChunk
if isinstance(message, OM.MsgError):
print(f"\n[Ошибка: {message.code}] {message.details}")
elif isinstance(message, OM.MsgStatus):
print("✓ Agent status update")
elif isinstance(message, OM.MsgGracefulDisconnect):
print("✓ Agent gracefully requested disconnect")
async def main(): async def main():
api = AgentApi("agent-1", "ws://localhost:8000/ws", callback=my_callback) api = AgentApi("agent-1", "ws://localhost:8000/ws")
await api.connect() await api.connect()
try: try:
response = await api.send_message("Привет, агент!") response = await api.send_message("Привет, агент!")
async for chunk in response: async for chunk in response:
if isinstance(chunk, OM.MsgEventTextChunk): if isinstance(chunk, MsgEventTextChunk):
print(chunk.text, end="", flush=True) print(chunk.text, end="", flush=True)
# После окончания Generation возможно получить EventEnd в очереди и сохранить tokens
# (в current implementation: `response` - генератор, для токенов смотрите `EventEnd` в callback)
finally: finally:
await api.close() await api.close()
@ -47,40 +39,31 @@ async def main():
asyncio.run(main()) asyncio.run(main())
``` ```
## AgentApi - Асинхронный Python клиент ## Предполагаемое использование
Новая библиотека `AgentApi` предоставляет типизированный асинхронный клиент для WebSocket взаимодействия с агентом.
### Характеристики
- ✅ **Асинхронный клиент** на основе `aiohttp`
- ✅ **Явное подключение/закрытие** через `connect()`/`close()`
- ✅ **Защита от параллельных запросов** через `AgentBusyException`
- ✅ **ResponseIterator** для асинхронной итерации по чанкам ответа
- ✅ **Callback** для обработки событий вне генерации ответа (`Status`, `Error`, `GracefulDisconnect`)
- ✅ **Типизированные сообщения** через Pydantic с дискриминированными объединениями
- ✅ **Обработка ошибок** с кастомным исключением `AgentException`
- ✅ **Логирование** на всех уровнях операций
- ✅ **Полная документация** всех методов
### Использование
```python ```python
from lambda_agent_api.agent_api import AgentApi, OM from lambda_agent_api.agent_api import AgentApi
api = AgentApi("agent-1", "ws://localhost:8000/ws", callback=my_callback) connected_agents: dict[str, AgentApi] = {}
await api.connect()
try:
response = await api.send_message("Your question here")
async for chunk in response: # агент автоматически выключится после нескольких минут бездействия
if isinstance(chunk, OM.MsgEventTextChunk): # этот колбек вызовется при разрыве соединения
print(chunk.text, end="", flush=True) def on_agent_disconnect(agent: AgentApi):
del connected_agents[agent.id]
print("\nDone!")
finally: async def on_telegram_message(from_user: int, text: str):
await api.close() agent_id = get_agent_id_by_user(user_id)
agent = connected_agents.get(agent_id, None)
if not agent:
agent = AgentApi(agent_id, get_agent_url(agent_id), on_disconnect=on_agent_disconnect)
await agent.connect()
connected_agents[agent_id] = agent
async for event in agent.send_message(text):
...
``` ```
# Обработка ошибок # Обработка ошибок
@ -89,55 +72,6 @@ finally:
- `AgentException` возникает, если агент возвращает `ERROR` или есть проблемы с подключением. - `AgentException` возникает, если агент возвращает `ERROR` или есть проблемы с подключением.
- `on_disconnect` callback вызывается один раз при закрытии/разрыве соединения. - `on_disconnect` callback вызывается один раз при закрытии/разрыве соединения.
Callback функция для обработки событий вне генерации:
```python
def my_callback(message):
if isinstance(message, OM.MsgStatus):
print("Agent status update")
elif isinstance(message, OM.MsgError):
print(f"Agent error: {message.code} - {message.details}")
elif isinstance(message, OM.MsgGracefulDisconnect):
print("Agent disconnecting gracefully")
```
## Классический подход (низкоуровневый)
```python
import asyncio
import websockets
from lambda_agent_api.server import ServerMessage, OM
async def main():
uri = "ws://localhost:8000/ws"
async with websockets.connect(uri) as ws:
# 1. Ждём STATUS - подтверждение готовности
status = await ws.recv()
print(f"Connected: {status}")
# 2. Отправляем сообщение
await ws.send('{"type": "USER_MESSAGE", "text": "Привет!"}')
# 3. Читаем ответ в виде потока событий
while True:
msg = await ws.recv()
data = ServerMessage.model_validate_json(msg)
match data:
case OM.AgentEvent(subtype=OM.AgentEventType.TEXT_CHUNK):
print(data.text, end="", flush=True)
case OM.MsgEventEnd():
print(f"\n[Завершено, использовано токенов: {data.tokens_used}]")
break
case OM.MsgError():
print(f"\n[Ошибка: {data.code}] {data.details}")
break
asyncio.run(main())
```
## Протокол ## Протокол
@ -231,8 +165,3 @@ asyncio.run(main())
``` ```
![Схема взаимодействия](docs/schema.png) ![Схема взаимодействия](docs/schema.png)
## Зависимости
- Python 3.14+
- pydantic >= 2.12.5