refactor(llm): extract shared http_client sync/async split helper - #567
Conversation
0b4426b to
4baa924
Compare
8bf5e40 to
e487f99
Compare
4baa924 to
2b6a1f6
Compare
e487f99 to
4300d09
Compare
2b6a1f6 to
5a6541c
Compare
stellasia
left a comment
There was a problem hiding this comment.
Looks good. Left some minor comments but can be merged as it is.
|
|
||
|
|
||
| def test_split_http_client_kwargs_routes_sync_client() -> None: | ||
| client = httpx.Client() |
There was a problem hiding this comment.
Nit: I think we could also use a fixture to deal with client.close, something like:
@fixture(scope="function")
def httpx_sync_client():
client = httpx.Client()
yield client
client.close()
|
|
||
|
|
||
| def test_split_http_client_kwargs_routes_async_client() -> None: | ||
| client = httpx.AsyncClient() |
There was a problem hiding this comment.
If we also need to close the client, we could use an async test?
| from neo4j_graphrag.message_history import MessageHistory | ||
| from neo4j_graphrag.types import LLMMessage | ||
|
|
||
| try: |
There was a problem hiding this comment.
We can maybe make httpx a required dependency, wdyt?
There was a problem hiding this comment.
I'd keep it optional: the helper only needs httpx for isinstance checks, and every SDK extra that can reach this code path (anthropic/openai/cohere/mistralai/ollama) already brings httpx transitively. Making it a core dependency would add an HTTP stack to the base install without changing behavior. Happy to revisit if we ever use httpx directly in core.
4300d09 to
cedb488
Compare
…tests Add unit tests verifying httpx.Client reaches only the sync Anthropic client, httpx.AsyncClient reaches only the async client, and an invalid http_client type warns and falls back to defaults for both clients. Also note the stale-venv anthropic version gotcha in AGENTS.md.
Keep the PR scoped to the http_client routing fix.
AnthropicLLM, OpenAILLM, and AzureOpenAILLM each carried an identical ~10-line dance to route an httpx.Client/httpx.AsyncClient http_client kwarg to the matching SDK client, warning and dropping it otherwise. Factored into one split_http_client_kwargs helper in llm/utils.py, used by all three, so any future subclass needing a custom endpoint doesn't need a fourth/fifth copy of the same logic. Pure refactor, no behavior change.
… helper scope stacklevel=3 skips the LLM constructor frame that calls the helper, so the warning points at the user's constructor call site as it did when the logic was inline. Changelog no longer labels the helper 'internal': custom subclasses constructing their own SDK clients are expected to call it.
5a6541c to
a819760
Compare
Stack
Merge order: #565 → #567 → #566 → #571 / #572 (last two in either order). Each PR builds on the previous one. Until its base merges, GitHub may show parent commits in the diff — review only the commits unique to this branch.
Description
The routing logic fixed in #565 — decide whether
http_clientbelongs to the sync or the async SDK client — existed as three identical copies: inAnthropicLLM,OpenAILLM, andAzureOpenAILLM. Any new class constructing its own clients would have needed a fourth copy.This PR moves it into one shared function,
split_http_client_kwargs. It takes the constructor kwargs and returns two dicts — one for the sync client, one for the async client — withhttp_clientplaced in whichever one it matches. All three classes now call it.Pure refactor, no behavior change. The function has its own unit tests (routing in both directions, invalid type warns and drops, input dict is never modified). Custom subclasses that build their own SDK clients can call it too, so they inherit the fix instead of copying the logic — it becomes a documented public export in #566, where the extension docs live.
Type of Change
Complexity
Complexity: Low
How Has This Been Tested?
Checklist