agent-lab-sdk 0.1.42__tar.gz → 0.1.43__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of agent-lab-sdk might be problematic. Click here for more details.
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/PKG-INFO +26 -2
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/README.md +25 -1
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/agw_saver.py +58 -17
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/PKG-INFO +26 -2
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/pyproject.toml +1 -1
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/LICENSE +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/serde.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/agw_token_manager.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/gigachat_token_manager.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/llm.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/throttled.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/metrics.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/input_types.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/log_message.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/__init__.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage_v2.py +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/SOURCES.txt +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/dependency_links.txt +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/requires.txt +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/top_level.txt +0 -0
- {agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-lab-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.43
|
|
4
4
|
Summary: SDK для работы с Agent Lab
|
|
5
5
|
Author-email: Andrew Ohurtsov <andermirik@yandex.com>
|
|
6
6
|
License: Proprietary and Confidential — All Rights Reserved
|
|
@@ -373,7 +373,31 @@ class TaskConfig(BaseModel):
|
|
|
373
373
|
|
|
374
374
|
### 5.2. LogMessage
|
|
375
375
|
|
|
376
|
-
|
|
376
|
+
`LogMessage` — вспомогательное сообщение для потоковой передачи логов из узлов LangGraph / LangChain. Экземпляры создаются как обычные сообщения чата, но получают тип `log`, поэтому фронтенд может отображать их отдельно от ответов модели.
|
|
377
|
+
|
|
378
|
+
- Импортируется из `agent_lab_sdk.schema`.
|
|
379
|
+
- По умолчанию наследуется от `langchain.schema.AIMessage` и устанавливает `additional_kwargs={"type": "log"}`.
|
|
380
|
+
- Если установить переменную окружения `IS_LOG_MESSAGE_CUSTOM=true`, будет использоваться наследник `BaseMessage` с явным типом `log`.
|
|
381
|
+
|
|
382
|
+
Переменная окружения `IS_LOG_MESSAGE_CUSTOM` на текущий момент установлена для всех агентов в значение `true`
|
|
383
|
+
|
|
384
|
+
#### Пример использования со `StreamWriter`
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from langgraph.graph import MessagesState
|
|
388
|
+
from langgraph.types import StreamWriter
|
|
389
|
+
from agent_lab_sdk.schema import LogMessage
|
|
390
|
+
|
|
391
|
+
async def run(state: MessagesState, writer: StreamWriter) -> MessagesState:
|
|
392
|
+
writer(LogMessage("Запускаю обработку запроса"))
|
|
393
|
+
|
|
394
|
+
# ... полезная работа здесь ...
|
|
395
|
+
|
|
396
|
+
writer(LogMessage("Обработка завершена"))
|
|
397
|
+
return state
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Вызов `writer(LogMessage(...))` отправляет лог во время выполнения шага графа, позволяя клиенту сразу видеть прогресс.
|
|
377
401
|
|
|
378
402
|
## 6. Сборка и публикация
|
|
379
403
|
|
|
@@ -343,7 +343,31 @@ class TaskConfig(BaseModel):
|
|
|
343
343
|
|
|
344
344
|
### 5.2. LogMessage
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
`LogMessage` — вспомогательное сообщение для потоковой передачи логов из узлов LangGraph / LangChain. Экземпляры создаются как обычные сообщения чата, но получают тип `log`, поэтому фронтенд может отображать их отдельно от ответов модели.
|
|
347
|
+
|
|
348
|
+
- Импортируется из `agent_lab_sdk.schema`.
|
|
349
|
+
- По умолчанию наследуется от `langchain.schema.AIMessage` и устанавливает `additional_kwargs={"type": "log"}`.
|
|
350
|
+
- Если установить переменную окружения `IS_LOG_MESSAGE_CUSTOM=true`, будет использоваться наследник `BaseMessage` с явным типом `log`.
|
|
351
|
+
|
|
352
|
+
Переменная окружения `IS_LOG_MESSAGE_CUSTOM` на текущий момент установлена для всех агентов в значение `true`
|
|
353
|
+
|
|
354
|
+
#### Пример использования со `StreamWriter`
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
from langgraph.graph import MessagesState
|
|
358
|
+
from langgraph.types import StreamWriter
|
|
359
|
+
from agent_lab_sdk.schema import LogMessage
|
|
360
|
+
|
|
361
|
+
async def run(state: MessagesState, writer: StreamWriter) -> MessagesState:
|
|
362
|
+
writer(LogMessage("Запускаю обработку запроса"))
|
|
363
|
+
|
|
364
|
+
# ... полезная работа здесь ...
|
|
365
|
+
|
|
366
|
+
writer(LogMessage("Обработка завершена"))
|
|
367
|
+
return state
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Вызов `writer(LogMessage(...))` отправляет лог во время выполнения шага графа, позволяя клиенту сразу видеть прогресс.
|
|
347
371
|
|
|
348
372
|
## 6. Сборка и публикация
|
|
349
373
|
|
{agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/agw_saver.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import threading
|
|
4
5
|
import base64
|
|
5
6
|
import logging
|
|
6
7
|
import os
|
|
@@ -102,7 +103,10 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
102
103
|
super().__init__(serde=serde)
|
|
103
104
|
self.base_url = base_url.rstrip("/")
|
|
104
105
|
self.timeout = timeout
|
|
105
|
-
|
|
106
|
+
# Фоновый loop для sync-обёрток
|
|
107
|
+
self._bg_loop: asyncio.AbstractEventLoop | None = None
|
|
108
|
+
self._bg_thread: threading.Thread | None = None
|
|
109
|
+
self._loop_lock = threading.Lock()
|
|
106
110
|
|
|
107
111
|
raw_attempts = os.getenv("AGW_HTTP_MAX_RETRIES")
|
|
108
112
|
if raw_attempts is None:
|
|
@@ -175,6 +179,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
175
179
|
|
|
176
180
|
self._verify = verify
|
|
177
181
|
self._client: httpx.AsyncClient | None = None
|
|
182
|
+
self._client_loop: asyncio.AbstractEventLoop | None = None
|
|
178
183
|
|
|
179
184
|
def _create_client(self) -> httpx.AsyncClient:
|
|
180
185
|
return httpx.AsyncClient(
|
|
@@ -185,14 +190,23 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
185
190
|
trust_env=True,
|
|
186
191
|
)
|
|
187
192
|
|
|
188
|
-
def
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
def _ensure_bg_loop(self) -> asyncio.AbstractEventLoop:
|
|
194
|
+
with self._loop_lock:
|
|
195
|
+
if self._bg_loop and self._bg_loop.is_running():
|
|
196
|
+
return self._bg_loop
|
|
197
|
+
|
|
198
|
+
loop = asyncio.new_event_loop()
|
|
199
|
+
|
|
200
|
+
def runner():
|
|
201
|
+
asyncio.set_event_loop(loop)
|
|
202
|
+
loop.run_forever()
|
|
203
|
+
|
|
204
|
+
t = threading.Thread(target=runner, name="agw-checkpoint-loop", daemon=True)
|
|
205
|
+
t.start()
|
|
206
|
+
|
|
207
|
+
self._bg_loop = loop
|
|
208
|
+
self._bg_thread = t
|
|
209
|
+
return loop
|
|
196
210
|
|
|
197
211
|
def _compute_retry_delay(self, attempt: int) -> float:
|
|
198
212
|
if attempt <= 0:
|
|
@@ -218,6 +232,14 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
218
232
|
logger.debug("Failed to close AGW httpx.AsyncClient: %s", close_exc)
|
|
219
233
|
finally:
|
|
220
234
|
self._client = None
|
|
235
|
+
self._client_loop = None
|
|
236
|
+
# останавливаем фоновый loop, если поднимали
|
|
237
|
+
if self._bg_loop is not None:
|
|
238
|
+
try:
|
|
239
|
+
self._bg_loop.call_soon_threadsafe(self._bg_loop.stop)
|
|
240
|
+
finally:
|
|
241
|
+
self._bg_loop = None
|
|
242
|
+
self._bg_thread = None
|
|
221
243
|
|
|
222
244
|
# ----------------------- universal dump/load ---------------------
|
|
223
245
|
def _safe_dump(self, obj: Any) -> Any:
|
|
@@ -539,7 +561,18 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
539
561
|
|
|
540
562
|
attempt = 1
|
|
541
563
|
while True:
|
|
542
|
-
|
|
564
|
+
# клиент должен принадлежать текущему loop
|
|
565
|
+
current_loop = asyncio.get_running_loop()
|
|
566
|
+
client = self._client
|
|
567
|
+
if client is None or client.is_closed or self._client_loop is not current_loop:
|
|
568
|
+
if client is not None:
|
|
569
|
+
try:
|
|
570
|
+
await client.aclose()
|
|
571
|
+
except Exception as e:
|
|
572
|
+
logger.exception("ошибка при закрытии клиента", e)
|
|
573
|
+
client = self._create_client()
|
|
574
|
+
self._client = client
|
|
575
|
+
self._client_loop = current_loop
|
|
543
576
|
try:
|
|
544
577
|
resp = await client.request(method, path, **kw)
|
|
545
578
|
except httpx.RequestError as exc:
|
|
@@ -564,6 +597,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
564
597
|
)
|
|
565
598
|
finally:
|
|
566
599
|
self._client = None
|
|
600
|
+
self._client_loop = None
|
|
567
601
|
raise
|
|
568
602
|
|
|
569
603
|
if self._client is not None:
|
|
@@ -576,6 +610,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
576
610
|
)
|
|
577
611
|
finally:
|
|
578
612
|
self._client = None
|
|
613
|
+
self._client_loop = None
|
|
579
614
|
delay = self._compute_retry_delay(attempt)
|
|
580
615
|
if delay > 0:
|
|
581
616
|
await asyncio.sleep(delay)
|
|
@@ -611,6 +646,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
611
646
|
)
|
|
612
647
|
finally:
|
|
613
648
|
self._client = None
|
|
649
|
+
self._client_loop = None
|
|
614
650
|
delay = self._compute_retry_delay(attempt)
|
|
615
651
|
if delay > 0:
|
|
616
652
|
await asyncio.sleep(delay)
|
|
@@ -737,7 +773,10 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
737
773
|
# sync-обёртки
|
|
738
774
|
# =================================================================
|
|
739
775
|
def _run(self, coro):
|
|
740
|
-
|
|
776
|
+
# sync-обёртки всегда выполняем в собственном loop в отдельном потоке
|
|
777
|
+
loop = self._ensure_bg_loop()
|
|
778
|
+
fut = asyncio.run_coroutine_threadsafe(coro, loop)
|
|
779
|
+
return fut.result()
|
|
741
780
|
|
|
742
781
|
def list(
|
|
743
782
|
self,
|
|
@@ -747,12 +786,14 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
747
786
|
before: RunnableConfig | None = None,
|
|
748
787
|
limit: int | None = None,
|
|
749
788
|
) -> Iterator[CheckpointTuple]:
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
789
|
+
async def _collect():
|
|
790
|
+
out = []
|
|
791
|
+
async for item in self.alist(cfg, filter=filter, before=before, limit=limit):
|
|
792
|
+
out.append(item)
|
|
793
|
+
return out
|
|
794
|
+
|
|
795
|
+
for item in self._run(_collect()):
|
|
796
|
+
yield item
|
|
756
797
|
|
|
757
798
|
def get_tuple(self, cfg: RunnableConfig) -> CheckpointTuple | None:
|
|
758
799
|
return self._run(self.aget_tuple(cfg))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-lab-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.43
|
|
4
4
|
Summary: SDK для работы с Agent Lab
|
|
5
5
|
Author-email: Andrew Ohurtsov <andermirik@yandex.com>
|
|
6
6
|
License: Proprietary and Confidential — All Rights Reserved
|
|
@@ -373,7 +373,31 @@ class TaskConfig(BaseModel):
|
|
|
373
373
|
|
|
374
374
|
### 5.2. LogMessage
|
|
375
375
|
|
|
376
|
-
|
|
376
|
+
`LogMessage` — вспомогательное сообщение для потоковой передачи логов из узлов LangGraph / LangChain. Экземпляры создаются как обычные сообщения чата, но получают тип `log`, поэтому фронтенд может отображать их отдельно от ответов модели.
|
|
377
|
+
|
|
378
|
+
- Импортируется из `agent_lab_sdk.schema`.
|
|
379
|
+
- По умолчанию наследуется от `langchain.schema.AIMessage` и устанавливает `additional_kwargs={"type": "log"}`.
|
|
380
|
+
- Если установить переменную окружения `IS_LOG_MESSAGE_CUSTOM=true`, будет использоваться наследник `BaseMessage` с явным типом `log`.
|
|
381
|
+
|
|
382
|
+
Переменная окружения `IS_LOG_MESSAGE_CUSTOM` на текущий момент установлена для всех агентов в значение `true`
|
|
383
|
+
|
|
384
|
+
#### Пример использования со `StreamWriter`
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from langgraph.graph import MessagesState
|
|
388
|
+
from langgraph.types import StreamWriter
|
|
389
|
+
from agent_lab_sdk.schema import LogMessage
|
|
390
|
+
|
|
391
|
+
async def run(state: MessagesState, writer: StreamWriter) -> MessagesState:
|
|
392
|
+
writer(LogMessage("Запускаю обработку запроса"))
|
|
393
|
+
|
|
394
|
+
# ... полезная работа здесь ...
|
|
395
|
+
|
|
396
|
+
writer(LogMessage("Обработка завершена"))
|
|
397
|
+
return state
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Вызов `writer(LogMessage(...))` отправляет лог во время выполнения шага графа, позволяя клиенту сразу видеть прогресс.
|
|
377
401
|
|
|
378
402
|
## 6. Сборка и публикация
|
|
379
403
|
|
|
File without changes
|
|
File without changes
|
{agent_lab_sdk-0.1.42 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|