Conversation
| @property | ||
| def langfuse_enabled(self) -> bool: | ||
| return self.langfuse.enabled |
| if getattr(config, "langfuse_enabled", False): | ||
| try: | ||
| lf_cfg = config.langfuse | ||
| if lf_cfg.public_key or lf_cfg.secret_key or lf_cfg.host: | ||
| LangfuseClient = getattr(import_module("langfuse"), "Langfuse") | ||
| kwargs = {} | ||
| if lf_cfg.public_key: | ||
| kwargs["public_key"] = lf_cfg.public_key | ||
| if lf_cfg.secret_key: | ||
| kwargs["secret_key"] = lf_cfg.secret_key | ||
| if lf_cfg.host: | ||
| kwargs["host"] = lf_cfg.host | ||
| LangfuseClient(**kwargs) | ||
| logger.info("Langfuse initialized with explicit credentials from config") | ||
| LangfuseAsyncOpenAI = getattr(import_module("langfuse.openai"), "AsyncOpenAI") | ||
| cls._patch_langfuse_stream_close() | ||
| logger.info("Creating Langfuse AsyncOpenAI client (langfuse_enabled=True)") | ||
| return LangfuseAsyncOpenAI(**client_kwargs) | ||
| except ImportError: | ||
| logger.warning( | ||
| "Langfuse is enabled but 'langfuse' package is not available. " | ||
| "Falling back to standard AsyncOpenAI client." | ||
| ) | ||
|
|
There was a problem hiding this comment.
Что-то не очень здоровое.
- Валидацию можно вынести в модельку
- Зачем-то собираются лишние kwargs с лишними if
- Если юзер не заимпортил модуль, лучше явно упасть чем неявно фолбекнуться
- Какую проблему решает патч stream close?
прогонял на этом тесте, вроде всё работает
from sgr_agent_core.agent_config import GlobalConfig
config = GlobalConfig().from_yaml("config.yaml")
from langfuse import Langfuse
Langfuse(
public_key=config.langfuse.public_key,
secret_key=config.langfuse.secret_key,
host=config.langfuse.host,
)
from langfuse.openai import AsyncOpenAI
async_client = AsyncOpenAI(
base_url=config.llm.base_url,
api_key=config.llm.api_key,
)
completion = await async_client.chat.completions.create(
name="test-chat",
model="gpt-4o",
messages=[
{"role": "system", "content": "Tell me about dirigables"},
{"role": "user", "content": "Tell me about dirigables"}],
temperature=0,
metadata={"someMetadataKey": "someValue"},
stream=True
)
async for chunk in completion:
print(chunk.choices[0].delta.content, end="")
print(Langfuse)
print(completion)
There was a problem hiding this comment.
- через kwargs собирается, потому что Langfuse с пустыми параметрами ( когда kwargs будут пустые) инициализируется с env переменными LANGFUSE_SECRET_KEY ,
LANGFUSE_PUBLIC_KEY ,
LANGFUSE_BASE_URL .
There was a problem hiding this comment.
- У нас уже есть готовая pydantic моделька, которая в себе это хранит, валидирует и всё такое. Зачем возвращаться обратно к raw словарю?
There was a problem hiding this comment.
- ЛЛМки говорят, что
Кратко: патч нужен не для того, чтобы итерация async for chunk in completion вообще заработала, а для того, чтобы корректно закрыть стрим, когда внутренний код OpenAI вызывает aclose() на обёрнутом ответе Langfuse.
Что именно ломалось
В agent_factory.py в docstring патча сказано: у обёртки Langfuse на HTTP-ответе иногда есть только синхронный close(), а класс OpenAI AsyncChatCompletionStream в методе close ожидает aclose() на _response. Тогда при закрытии стрима возникает AttributeError (в доке — про отсутствие aclose).
То есть проблема — на этапе закрытия / cleanup, а не на чтении чанков.
Почему «всё работает»
Версии пакетов — в pyproject.toml у вас langfuse>=4.0.0 и современный openai. В новых релизах Langfuse или OpenAI обёртка/стриминг могли измениться так, что либо у ответа появился aclose(), либо путь закрытия другой — и баг просто не проявляется на вашей связке.
Сценарий «дочитали до конца и вышли» — основной поток async for успевает отдать все чанки; ошибка могла бы всплыть после цикла, при закрытии контекста/деструкторе/сборке мусора — не всегда это видно как явный traceback в простом скрипте.
Другой кодовый путь — ваш ручной скрипт и путь через AgentFactory._create_client + тот же AsyncOpenAI теоретически могут отличаться окружением (версии, флаги), но чаще всего решает именно п.1–2.
There was a problem hiding this comment.
Так, и что из этого должно следовать?
There was a problem hiding this comment.
что возможно когда-то оно может сломаться, но я не уверен =/ Ок. могу убрать
Changes
Configuration: Added
langfuseflag toAgentConfigfor enabling Langfuse tracinglangfuse: true/false) or environment variable (SGR__LANGFUSE)falseAgent Factory: Updated
_create_client()to support Langfuse AsyncOpenAI clientlangfuse.openai.AsyncOpenAIwhen enabledopenai.AsyncOpenAIif Langfuse package unavailable_patch_langfuse_stream_close()to fix streaming compatibility issuesDependencies: Added
langfuse>=4.0.0to project dependenciesDocumentation: Added Langfuse configuration guide in English and Russian
Tests: Added comprehensive test coverage