Provider Configuration Persistence#
Overview#
RAGFlow stores provider instance credentials in the TenantModelInstance.api_key database column as either a plain string or a JSON-encoded object . Providers with multi-field credentials (e.g., MinerU, Azure OpenAI, BaiduYiYan, XunFei Spark) pack all credential fields into that single column, requiring symmetric transform functions on both the write (submit) and read (prefill) paths.
The api_key Column and Packing#
On save, the backend serializes a str | dict value to string :
api_key_str = api_key if isinstance(api_key, str) else json.dumps(api_key)
This happens identically in both create_provider_instance and update_provider_instance. The base_url and region are stored separately in an extra JSON blob, not in api_key .
show_provider_instance returns api_key verbatim from the DB column — it may be a raw JSON string or a bare key string.
Frontend Transform Functions#
Every entry in ProviderConfigMap defines two paired transform functions:
| Function | Direction | Purpose |
|---|---|---|
submitTransform | Form → API | Packs provider-specific form fields into { instance_name, llm_factory, api_key, base_url, model_info } |
verifyTransform | Form → verify endpoint | Shapes credentials for the connection-check endpoint (POST /providers/<name>/connection) |
The unwrapApiKey function performs the inverse of submitTransform, normalizing three possible shapes returned from the backend back into flat form fields for pre-filling:
- Raw JSON string
'{"api_key":"sk-x","group_id":"123"}'— parsed and spread into flat fields - Already-parsed object
{ api_key, ... }— spread directly - Plain bare key
"sk-x"— returned asapiKey, no nested fields
This is consumed by useProviderInitialValues, which merges the result into the form's defaultValues.
MinerU Configuration Transform#
MinerU exemplifies providers that pack all fields into api_key as a JSON object. Its submitTransform:
- Spreads all form fields (except
instance_name) into a singlecfgobject - Converts
mineru_delete_outputboolean →"1"/"0"string - Strips
mineru_server_urlwhen the backend is notvlm-http-client - Sets
api_key: cfgandbase_url: ''
The fields packed into api_key are consumed at runtime by MinerUOcrModel.__init__(), which reads them as lowercase keys.
MinerU form fields and their DB keys :
| Field | Key in api_key | Default |
|---|---|---|
| API server URL | mineru_apiserver | — |
| Output directory | mineru_output_dir | — |
| Backend | mineru_backend | "pipeline" |
| VLM server URL | mineru_server_url | (only for vlm-http-client) |
| Delete output | mineru_delete_output | "1" (boolean→string) |
Other Providers with Packed Credentials#
The same pattern applies :
- Azure OpenAI — packs
{ api_key, api_version }intoapi_keywhenapi_versionis set - BaiduYiYan — packs
{ yiyan_ak, yiyan_sk } - XunFei Spark — packs
{ spark_api_password, spark_app_id, spark_api_secret, spark_api_key } - PaddleOCR — packs
{ paddleocr_api_url, paddleocr_access_token, paddleocr_algorithm } - OpenDataLoader — packs
{ opendataloader_apiserver, opendataloader_api_key }
Providers that use a plain string key (e.g., VolcEngine, most OpenAI-compatible providers) use the generic path in buildApiKeyValue / unwrapApiKey and do not need a submitTransform.
Adding a New Provider with Packed Credentials#
- Add an entry to
ProviderConfigMapwith:fields: declare each custom fieldsubmitTransform: pack fields intoapi_keyas an object, return{ instance_name, llm_factory, api_key, base_url, model_info }verifyTransform: pack same fields into{ apiKey: cfg, baseUrl, modelInfo }
- The backend stores the dict as JSON via
json.dumps(api_key)— no backend changes needed unless the model class needs to read new keys. - Ensure
unwrapApiKeycovers the new field names, or declare them inAPI_KEY_NESTED_FIELDSfor the generic unwrap path.
Symmetry requirement:
submitTransformandunwrapApiKeymust produce byte-identical round-trips. The dirty-check baseline comparison inuseInstanceSaveStateusesJSON.stringifyon the payload; asymmetric transforms will cause phantom dirty state on every form open.
Key Source Files#
| File | Purpose |
|---|---|
provider-config-map.ts | All submitTransform / verifyTransform definitions per provider |
instance-card/hooks.tsx | buildApiKeyValue, unwrapApiKey, useProviderInitialValues, useInstanceSaveState |
provider_api_service.py | Backend packing (json.dumps) and storage in create_provider_instance / update_provider_instance |
provider_api.py | REST endpoints for create/update/show instance |
use-provider-fields.tsx | Form default value seeding from initialValues |