feat: add OpenAI-compatible embedding backend#12
Conversation
Add a third embedding backend ("openai") alongside the existing
"dashscope" and "local" options. It talks to any OpenAI-compatible
/embeddings endpoint (OpenAI, Zhipu/GLM, vLLM/TEI, ...) via
base_url + api_key + model.
- EmbeddingService: new _init_openai_client / _embed_openai with
robust handling for call failures, empty data/rows, and count
mismatches; openai branch wired into embed_text/embed_texts/
is_available/get_model_info.
- Config: new embedding_base_url / embedding_api_key fields that fall
back to the LLM endpoint/key (ULTRON_BASE_URL, ULTRON_API_KEY /
OPENAI_API_KEY) so no duplicate setup is needed.
- SDK: pass the new config through to EmbeddingService.
- Tests: cover the openai backend success and error paths.
- Docs/.env.example: document the new backend and env vars (EN/ZH).
Default behavior is unchanged (still dashscope).
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Code Review
This pull request introduces support for an OpenAI-compatible embedding backend (openai) alongside the existing dashscope and local backends, updating the configuration, documentation, and SDK implementation, and adding corresponding unit tests. Feedback on these changes suggests ensuring that EmbeddingService falls back to environment variables for base_url and api_key when instantiated directly, sorting the returned embedding data by index to handle potential out-of-order responses from some providers, and isolating configuration tests from host environment variables to prevent flakiness.
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.
Summary
Adds a third embedding backend
openaialongside the existingdashscope(default) andlocalbackends. It works with any OpenAI-compatible/embeddingsendpoint — OpenAI, Zhipu/GLM (embedding-3), self-hosted vLLM/TEI, etc. — configured viabase_url+api_key+model.Default behavior is unchanged: existing users stay on
dashscopewith no action required.Changes
ultron/core/embeddings.py:EmbeddingServicenow supportsopenai. New_init_openai_client()(lazy-importsopenai, validatesbase_url/api_key) and_embed_openai()with robust error handling for call failures, emptydata, empty rows, and input/output count mismatches. Theopenaibranch is wired intoembed_text/embed_texts/is_available/get_model_info.ultron/config.py: newembedding_base_urlandembedding_api_keyfields. They fall back to the LLM endpoint/key (ULTRON_BASE_URL,ULTRON_API_KEY/OPENAI_API_KEY), so most users need no extra setup.ultron/api/sdk/ultron.py: passes the new config through toEmbeddingService..env.example: document the new backend and env vars (ULTRON_EMBEDDING_BASE_URL,ULTRON_EMBEDDING_API_KEY) in both EN and ZH.tests/core/test_embeddings.pycovers theopenaibackend success and error paths (skipped whenopenaiis not installed).New environment variables
ULTRON_EMBEDDING_BACKEND=openaiembedding_backenddashscopeULTRON_EMBEDDING_BASE_URLembedding_base_urlULTRON_BASE_URLULTRON_EMBEDDING_API_KEYembedding_api_keyULTRON_API_KEY/OPENAI_API_KEYNotes
ULTRON_DATA_DIRcan only use a single embedding backend/model/dimension; switching requiresreset_all()(existing constraint, unchanged).openaipackage only when this backend is selected.Test plan
python -m pytest tests/core/test_embeddings.pyembedding-3/ OpenAI endpoint