Skip to content

refactor(llm): extract shared http_client sync/async split helper - #567

Merged
matteomedioli merged 5 commits into
mainfrom
matteo/split-http-client-helper
Jul 22, 2026
Merged

refactor(llm): extract shared http_client sync/async split helper#567
matteomedioli merged 5 commits into
mainfrom
matteo/split-http-client-helper

Conversation

@matteomedioli

@matteomedioli matteomedioli commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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_client belongs to the sync or the async SDK client — existed as three identical copies: in AnthropicLLM, OpenAILLM, and AzureOpenAILLM. 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 — with http_client placed 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

  • New feature
  • Bug fix
  • Breaking change
  • Documentation update
  • Project configuration change

Complexity

Complexity: Low

How Has This Been Tested?

  • Unit tests
  • E2E tests
  • Manual tests

Checklist

  • Documentation has been updated
  • Unit tests have been updated
  • Examples have been updated
  • CLA (https://neo4j.com/developer/cla/) has been signed
  • CHANGELOG.md updated

@stellasia stellasia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Left some minor comments but can be merged as it is.

Comment thread tests/unit/llm/test_llm_utils.py Outdated


def test_split_http_client_kwargs_routes_sync_client() -> None:
client = httpx.Client()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()

Comment thread tests/unit/llm/test_llm_utils.py Outdated


def test_split_http_client_kwargs_routes_async_client() -> None:
client = httpx.AsyncClient()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can maybe make httpx a required dependency, wdyt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@matteomedioli
matteomedioli force-pushed the matteo/anthropic-kwargs-bugfix branch from 4300d09 to cedb488 Compare July 21, 2026 12:40
Base automatically changed from matteo/anthropic-kwargs-bugfix to main July 21, 2026 12:49
…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.
@matteomedioli
matteomedioli force-pushed the matteo/split-http-client-helper branch from 5a6541c to a819760 Compare July 22, 2026 11:42
@matteomedioli
matteomedioli merged commit 96247ff into main Jul 22, 2026
16 checks passed
@matteomedioli
matteomedioli deleted the matteo/split-http-client-helper branch July 22, 2026 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants