Skip to content

feat(embedder): OpenAI-compatible embedding provider - #803

Merged
vitali87 merged 4 commits into
mainfrom
feat/openai-compatible-embeddings
Jul 19, 2026
Merged

feat(embedder): OpenAI-compatible embedding provider#803
vitali87 merged 4 commits into
mainfrom
feat/openai-compatible-embeddings

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Closes #267.

Adds an OpenAI-compatible embedding provider so embeddings can be computed by any server implementing the OpenAI embeddings API (OpenAI, Ollama, vLLM, LM Studio), removing the local torch/transformers requirement for semantic search.

Configuration

  • CGR_EMBEDDING_PROVIDER=openai selects the provider (unixcoder remains the default; fully backward compatible).
  • OPENAI_EMBEDDING_BASE_URL (default https://api.openai.com/v1), OPENAI_EMBEDDING_MODEL (default text-embedding-3-small).
  • OPENAI_EMBEDDING_API_KEY sent as a bearer token when set, falling back to the OPENAI_API_KEY env var; local servers needing no key work without one.
  • OPENAI_EMBEDDING_DIMENSIONS forwarded as the dimensions request parameter, OPENAI_EMBEDDING_BATCH_SIZE (default 128), OPENAI_EMBEDDING_TIMEOUT (default 60s).

Implementation

  • Provider dispatch in embedder.py; the UniXcoder torch path is unchanged and stays behind the existing dependency gate. The HTTP client is httpx, already a guaranteed transitive dependency, so no new packages.
  • Batch requests chunk by the configured batch size, validate the returned count, and sort rows by index so out-of-order responses cannot scramble embeddings. Non-200 responses raise with status and body excerpt.
  • The embedding cache is now namespaced by provider and model, so switching models never replays cached vectors from a different embedding space.
  • has_semantic_dependencies() requires only the vector store dependency under the openai provider since embeddings are computed server-side.

Tests

Strict RED then GREEN: commit one adds 17 failing specs (request shape, batching, ordering, caching, namespacing, auth header, base URL, error paths, dependency gating) driven through httpx.MockTransport; commit two implements. Full suite: 5182 passed, 5 skipped.

Docs

README, PYPI_README, docs/sdk/semantic-search.md (full configuration table plus vector-dimension guidance), and docs/guide/interactive-querying.md.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces support for OpenAI-compatible embedding providers (such as OpenAI, Ollama, vLLM, and LM Studio) as an alternative to local UniXcoder embeddings, allowing users to run without local torch and transformers dependencies. The feedback highlights critical issues with URL resolution in httpx due to a leading slash in the embeddings path and a missing trailing slash in the base URL. Additionally, the feedback suggests including configured embedding dimensions in the cache namespace to prevent retrieving stale cached vectors of incorrect dimensions, and recommends hardening the response parsing logic against malformed or buggy API responses.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread codebase_rag/constants/providers.py
Comment thread codebase_rag/embedder.py
Comment thread codebase_rag/embedder.py Outdated
Comment thread codebase_rag/embedder.py Outdated
@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds OpenAI-compatible embedding support while keeping UniXcoder as the default. The main changes are:

  • Environment-driven configuration for selecting the embedding provider and OpenAI-compatible endpoint.
  • HTTP embedding requests with batching, auth header handling, timeout settings, and response validation.
  • Provider, model, and dimension-aware embedding cache keys.
  • Dependency gating that skips local torch/transformers requirements for server-side embeddings.
  • Tests and documentation for request shape, batching, ordering, cache namespacing, auth, errors, and setup.

Confidence Score: 5/5

Safe to merge with minimal risk.

The new provider is opt-in, the default UniXcoder path remains intact, and the changed code validates response counts and indices before caching or returning embeddings. Cache keys include provider, model, and configured dimensions, so switching embedding spaces does not replay stale vectors. Tests cover the main OpenAI-compatible request, batching, auth, cache, URL, dependency, and error paths.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • The initial Pytest run after recreating the virtual environment failed due to a missing loguru dependency.
  • Subsequent setup artifacts show pytest collection blockers appearing in sequence (codebase_rag, then prompt_toolkit, then rich) with no edits to tracked files.
  • A passing runtime proof was recorded in the harness after dependencies were installed, with the executed command, working directory, exit code 0, and request/response summaries.
  • The artifacts include multiple logs and a Python artifact that support inspection of the commands, environment, and results used to validate the workflow.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
codebase_rag/embedder.py Refactors embedding dispatch to support UniXcoder and OpenAI-compatible HTTP embeddings with namespaced caching and response validation.
codebase_rag/config.py Adds validated settings for embedding provider selection and OpenAI-compatible endpoint behavior.
codebase_rag/utils/dependencies.py Adjusts semantic dependency gating so OpenAI-compatible embeddings require only the configured vector-store dependency.
codebase_rag/tests/test_embedder_openai.py Adds focused tests for OpenAI-compatible request shape, batching, cache namespacing, auth, URL joining, and malformed responses.
docs/sdk/semantic-search.md Expands semantic-search documentation with OpenAI-compatible provider setup, optional settings, and vector dimension guidance.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Caller as Graph updater / semantic search
participant Embedder as embedder.py
participant Cache as EmbeddingCache
participant Provider as OpenAI-compatible / UniXcoder
participant Store as Vector store

Caller->>Embedder: embed_code_batch(snippets)
Embedder->>Cache: get_many(snippets)
Cache-->>Embedder: cached vectors by index
alt OpenAI provider for uncached snippets
    Embedder->>Provider: "POST /embeddings {model,input,dimensions?}"
    Provider-->>Embedder: "data[{index, embedding}]"
    Embedder->>Embedder: validate count and indices
else UniXcoder provider for uncached snippets
    Embedder->>Provider: tokenize and run local model
    Provider-->>Embedder: embeddings
end
Embedder->>Cache: put_many(uncached snippets, embeddings)
Embedder-->>Caller: vectors in request order
Caller->>Store: store/search embeddings
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Caller as Graph updater / semantic search
participant Embedder as embedder.py
participant Cache as EmbeddingCache
participant Provider as OpenAI-compatible / UniXcoder
participant Store as Vector store

Caller->>Embedder: embed_code_batch(snippets)
Embedder->>Cache: get_many(snippets)
Cache-->>Embedder: cached vectors by index
alt OpenAI provider for uncached snippets
    Embedder->>Provider: "POST /embeddings {model,input,dimensions?}"
    Provider-->>Embedder: "data[{index, embedding}]"
    Embedder->>Embedder: validate count and indices
else UniXcoder provider for uncached snippets
    Embedder->>Provider: tokenize and run local model
    Provider-->>Embedder: embeddings
end
Embedder->>Cache: put_many(uncached snippets, embeddings)
Embedder-->>Caller: vectors in request order
Caller->>Store: store/search embeddings
Loading

Reviews (2): Last reviewed commit: "fix(embedder): dimension-aware cache nam..." | Re-trigger Greptile

Comment thread codebase_rag/embedder.py
@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

@sonarqubecloud

Copy link
Copy Markdown

@vitali87
vitali87 merged commit 168b888 into main Jul 19, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Openai-compatible embeddings

1 participant