Skip to content

Fix: Create OpenAI model instance in build_native_gemini_model#3

Open
railway-app[bot] wants to merge 1 commit into
mainfrom
railway/code-change-jd5-Sm
Open

Fix: Create OpenAI model instance in build_native_gemini_model#3
railway-app[bot] wants to merge 1 commit into
mainfrom
railway/code-change-jd5-Sm

Conversation

@railway-app
Copy link
Copy Markdown

@railway-app railway-app Bot commented May 12, 2026

Problem

When build_native_gemini_model() receives an openai:-prefixed spec (e.g. openai:gpt-4o-mini), it falls through all branches and returns the raw string. PydanticAI requires a Model object, so passing a plain string causes 404 errors at inference time. The existing test also asserted the broken string-return behaviour, causing it to fail once the fix is applied.

Solution

Added from pydantic_ai.models.openai import OpenAIModel and a new openai: branch in build_native_gemini_model() that extracts the model ID and constructs an OpenAIModel instance using OPENAI_API_KEY. The return type annotation was updated to str | GoogleModel | OpenAIModel. The corresponding test was updated to assert an OpenAIModel instance is returned and that its model_name matches the spec, replacing the now-incorrect string-equality assertion.

Changes

  • Modified backend/src/services/llm.py
  • Modified backend/tests/test_llm.py

Generated by Railway

Summary by Sourcery

Ensure build_native_gemini_model returns proper model instances for OpenAI-prefixed specs instead of raw strings.

Bug Fixes:

  • Fix handling of openai:-prefixed specs so build_native_gemini_model returns an OpenAIModel instance rather than a plain string.

Tests:

  • Update OpenAI model construction test to assert an OpenAIModel instance with the expected model name and API key usage.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
news-foundry-nvpt Ready Ready Preview, Comment May 12, 2026 10:07pm

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 12, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds proper OpenAIModel construction in build_native_gemini_model for openai:-prefixed specs and updates tests accordingly.

Flow diagram for build_native_gemini_model OpenAIModel branch

flowchart TD
    A[normalized_spec] --> B[normalize_provider_model_spec]
    B --> C[spec.lower]
    C --> D{prefix}
    D --> E[return GoogleModel
GeminiModel]:::nodeGoogleGla
    D --> F[return GoogleModel
GeminiModel vertexai]:::nodeGoogleVertex
    D --> G[return OpenAIModel
api_key OPENAI_API_KEY]:::nodeOpenAI
    D --> H[return spec string]

    classDef nodeGoogleGla fill:#e0f7fa,stroke:#006064
    classDef nodeGoogleVertex fill:#e8f5e9,stroke:#1b5e20
    classDef nodeOpenAI fill:#f3e5f5,stroke:#4a148c
Loading

File-Level Changes

Change Details Files
Ensure openai:-prefixed specs return an OpenAIModel instance instead of a raw string.
  • Extend build_native_gemini_model return type to include OpenAIModel
  • Normalize and detect openai:-prefixed specs via a new branch
  • Extract model_id from spec and build OpenAIModel with OPENAI_API_KEY environment variable
  • Fall back to returning the spec string only for unknown prefixes
backend/src/services/llm.py
Update tests to validate OpenAIModel construction for openai:-prefixed specs.
  • Add monkeypatching of OPENAI_API_KEY for deterministic OpenAIModel creation
  • Change assertion to check instance type OpenAIModel
  • Assert OpenAIModel.model_name matches the model id extracted from spec
backend/tests/test_llm.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • Consider centralizing OpenAI API key retrieval (similar to _google_api_key) instead of calling os.getenv inline, so missing or misconfigured keys can be handled consistently and with clearer error messages.
  • The build_native_gemini_model docstring and naming still suggest it only returns a Google/Gemini model or OpenAI string; updating them to reflect the new OpenAIModel return path would make the behavior clearer to callers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider centralizing OpenAI API key retrieval (similar to `_google_api_key`) instead of calling `os.getenv` inline, so missing or misconfigured keys can be handled consistently and with clearer error messages.
- The `build_native_gemini_model` docstring and naming still suggest it only returns a Google/Gemini model or OpenAI string; updating them to reflect the new `OpenAIModel` return path would make the behavior clearer to callers.

## Individual Comments

### Comment 1
<location path="backend/src/services/llm.py" line_range="38-40" />
<code_context>
     if low.startswith("google-vertex:"):
         model_id = spec.split(":", 1)[1].strip()
         return GeminiModel(model_id, provider=GoogleProvider(vertexai=True))
+    if low.startswith("openai:"):
+        model_id = spec.split(":", 1)[1].strip()
+        return OpenAIModel(model_id, api_key=os.getenv("OPENAI_API_KEY"))
     return spec
</code_context>
<issue_to_address>
**issue:** Guard against empty or missing model id in the `openai:` spec

When `normalized_spec` is just `"openai:"` (or otherwise has nothing after the colon), `model_id` becomes an empty string and you end up constructing `OpenAIModel("")`, which may fail in a confusing way. Consider validating that `model_id` is non-empty and either returning `spec` unchanged or raising a clearer error for malformed specs.
</issue_to_address>

### Comment 2
<location path="backend/tests/test_llm.py" line_range="14-18" />
<code_context>

-def test_build_native_openai_returns_string() -> None:
-    assert build_native_gemini_model("openai:gpt-4o-mini") == "openai:gpt-4o-mini"
+def test_build_native_openai_returns_openai_model(monkeypatch: pytest.MonkeyPatch) -> None:
+    monkeypatch.setenv("OPENAI_API_KEY", "test-openai-key")
+    m = build_native_gemini_model("openai:gpt-4o-mini")
+    assert isinstance(m, OpenAIModel)
+    assert m.model_name == "gpt-4o-mini"


</code_context>
<issue_to_address>
**suggestion (testing):** Also assert the OpenAIModel api_key to verify that OPENAI_API_KEY wiring works as expected.

The current test only checks that we build an OpenAIModel with the expected model_name. Please also assert that `m.api_key == "test-openai-key"` (or equivalent) so the test verifies the OPENAI_API_KEY env var is correctly wired into the model.

```suggestion
def test_build_native_openai_returns_openai_model(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setenv("OPENAI_API_KEY", "test-openai-key")
    m = build_native_gemini_model("openai:gpt-4o-mini")
    assert isinstance(m, OpenAIModel)
    assert m.model_name == "gpt-4o-mini"
    assert m.api_key == "test-openai-key"
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +38 to +40
if low.startswith("openai:"):
model_id = spec.split(":", 1)[1].strip()
return OpenAIModel(model_id, api_key=os.getenv("OPENAI_API_KEY"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue: Guard against empty or missing model id in the openai: spec

When normalized_spec is just "openai:" (or otherwise has nothing after the colon), model_id becomes an empty string and you end up constructing OpenAIModel(""), which may fail in a confusing way. Consider validating that model_id is non-empty and either returning spec unchanged or raising a clearer error for malformed specs.

Comment thread backend/tests/test_llm.py
Comment on lines +14 to +18
def test_build_native_openai_returns_openai_model(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("OPENAI_API_KEY", "test-openai-key")
m = build_native_gemini_model("openai:gpt-4o-mini")
assert isinstance(m, OpenAIModel)
assert m.model_name == "gpt-4o-mini"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Also assert the OpenAIModel api_key to verify that OPENAI_API_KEY wiring works as expected.

The current test only checks that we build an OpenAIModel with the expected model_name. Please also assert that m.api_key == "test-openai-key" (or equivalent) so the test verifies the OPENAI_API_KEY env var is correctly wired into the model.

Suggested change
def test_build_native_openai_returns_openai_model(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("OPENAI_API_KEY", "test-openai-key")
m = build_native_gemini_model("openai:gpt-4o-mini")
assert isinstance(m, OpenAIModel)
assert m.model_name == "gpt-4o-mini"
def test_build_native_openai_returns_openai_model(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("OPENAI_API_KEY", "test-openai-key")
m = build_native_gemini_model("openai:gpt-4o-mini")
assert isinstance(m, OpenAIModel)
assert m.model_name == "gpt-4o-mini"
assert m.api_key == "test-openai-key"

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.

0 participants