Repository navigation
Add SDK-free custom provider example - #59
Conversation
Summary of ChangesHello @zby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the flexibility of Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request adds a valuable example of an SDK-free custom provider, complete with comprehensive documentation in a new guide. The implementation is clear and serves as an excellent template for users. My review includes two suggestions for the providers.py file. First, a high-severity fix for a potential IndexError in the response parsing logic that could occur with valid API responses. Second, a medium-severity improvement to the model factory to reuse the HTTP client for better performance, which aligns with best practices mentioned in the new guide.
| response.raise_for_status() | ||
| data = response.json() | ||
| content = ( | ||
| data.get("choices", [{}])[0] |
There was a problem hiding this comment.
The current logic for extracting the response content is not robust. If the API returns a response with an empty choices list (e.g., {"choices": []}), which is a valid scenario, your code will raise an IndexError. This can happen, for example, if content filtering is triggered by the model provider.
| data.get("choices", [{}])[0] | |
| (data.get("choices") or [{}])[0] |
| def build_http_json_model(model_name: str) -> SimpleHTTPChatModel: | ||
| return SimpleHTTPChatModel( | ||
| model_name, | ||
| provider=SimpleHTTPProvider( | ||
| base_url="http://127.0.0.1:8000/v1", | ||
| api_key=None, | ||
| ), | ||
| ) |
There was a problem hiding this comment.
The current implementation of build_http_json_model creates a new SimpleHTTPProvider instance on every call. Since SimpleHTTPProvider instantiates an httpx.AsyncClient, this leads to creating a new HTTP client and connection pool for each model resolution, which is inefficient. It's better to create a single provider instance at the module level and reuse it. This also aligns with the GUIDE.md's mention of a 'reusable async HTTP client'.
| def build_http_json_model(model_name: str) -> SimpleHTTPChatModel: | |
| return SimpleHTTPChatModel( | |
| model_name, | |
| provider=SimpleHTTPProvider( | |
| base_url="http://127.0.0.1:8000/v1", | |
| api_key=None, | |
| ), | |
| ) | |
| _http_json_provider = SimpleHTTPProvider( | |
| base_url="http://127.0.0.1:8000/v1", | |
| api_key=None, | |
| ) | |
| def build_http_json_model(model_name: str) -> SimpleHTTPChatModel: | |
| return SimpleHTTPChatModel( | |
| model_name, | |
| provider=_http_json_provider, | |
| ) |
Motivation
llm-doand PydanticAI.Description
SimpleHTTPProviderandSimpleHTTPChatModeltoexamples/custom_provider/providers.pythat send/receive OpenAI-style chat payloads via raw HTTP usinghttpx.http-jsonviaregister_model_factory("http-json", build_http_json_model).examples/custom_provider/README.mdto document the new provider usage.examples/custom_provider/GUIDE.md, a detailed guide describing required responsibilities (provider, model, message mapping, request/response mapping, limitations, and extension points) for SDK-free custom providers.Testing
uv run ruff check .(auto-fix applied where needed) and the command completed successfully.uv run mypy llm_doand it reported no issues.uv run pytestand all tests passed (315 passed).Codex Task