fix: tolerate raw api_key string in AzureEmbed and AzureGptV4 __init__ (#15877)

Fixes #15587

## Problem

`AzureEmbed.__init__` in `rag/llm/embedding_model.py` and
`AzureGptV4.__init__` in `rag/llm/cv_model.py` both call
`json.loads(key)` unconditionally:

```python
api_key = json.loads(key).get("api_key", "")
api_version = json.loads(key).get("api_version", "2024-02-01")
```

When a user stores a plain API key string (not a JSON object) in the
model configuration — which is a valid and common way to configure Azure
OpenAI — `json.loads` raises `JSONDecodeError`. This makes the model
fail to initialize and causes document parsing/embedding to return a 500
error.

## Fix

Wrap `json.loads` in `try/except (json.JSONDecodeError, TypeError)` and
fall back to using the raw string as the `api_key` with the default
`api_version`. This is the same pattern already applied to the Azure
chat model in PR #15604.

## Files changed

- `rag/llm/embedding_model.py` — `AzureEmbed.__init__`
- `rag/llm/cv_model.py` — `AzureGptV4.__init__`

Fixes #15857

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Wang Qi <wangq8@outlook.com>
This commit is contained in:
jaso0n0818
2026-06-11 18:28:29 +10:00
committed by GitHub
parent 381091df71
commit d4fbc013b9
2 changed files with 28 additions and 4 deletions

View File

@@ -298,12 +298,24 @@ class GptV4(Base):
return res.choices[0].message.content.strip(), total_token_count_from_response(res)
def _resolve_azure_credentials(key):
try:
key_obj = json.loads(key)
if isinstance(key_obj, dict):
return key_obj.get("api_key", ""), key_obj.get("api_version", "2024-02-01")
logging.warning(
"Azure credential payload parsed as JSON but is not an object; using raw api_key string"
)
except (json.JSONDecodeError, TypeError):
logging.warning("Azure credential payload is not valid JSON; using raw api_key string")
return key, "2024-02-01"
class AzureGptV4(GptV4):
_FACTORY_NAME = "Azure-OpenAI"
def __init__(self, key, model_name, lang="Chinese", **kwargs):
api_key = json.loads(key).get("api_key", "")
api_version = json.loads(key).get("api_version", "2024-02-01")
api_key, api_version = _resolve_azure_credentials(key)
self.client = AzureOpenAI(api_key=api_key, azure_endpoint=kwargs["base_url"], api_version=api_version)
self.async_client = AsyncAzureOpenAI(api_key=api_key, azure_endpoint=kwargs["base_url"], api_version=api_version)
self.model_name = model_name

View File

@@ -235,14 +235,26 @@ class LocalAIEmbed(Base):
return np.array(embds[0]), cnt
def _resolve_azure_credentials(key):
try:
key_obj = json.loads(key)
if isinstance(key_obj, dict):
return key_obj.get("api_key", ""), key_obj.get("api_version", "2024-02-01")
logging.warning(
"Azure credential payload parsed as JSON but is not an object; using raw api_key string"
)
except (json.JSONDecodeError, TypeError):
logging.warning("Azure credential payload is not valid JSON; using raw api_key string")
return key, "2024-02-01"
class AzureEmbed(OpenAIEmbed):
_FACTORY_NAME = "Azure-OpenAI"
def __init__(self, key, model_name, **kwargs):
from openai.lib.azure import AzureOpenAI
api_key = json.loads(key).get("api_key", "")
api_version = json.loads(key).get("api_version", "2024-02-01")
api_key, api_version = _resolve_azure_credentials(key)
self.client = AzureOpenAI(api_key=api_key, azure_endpoint=kwargs["base_url"], api_version=api_version)
self.model_name = model_name