обновленный README
This commit is contained in:
parent
1e256a545b
commit
f9289b92fa
1 changed files with 27 additions and 98 deletions
125
README.md
125
README.md
|
|
@ -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())
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Зависимости
|
|
||||||
|
|
||||||
- Python 3.14+
|
|
||||||
- pydantic >= 2.12.5
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue