Extend LLM and embedding adapters in unstract/sdk1. Use when adding new adapters (LLM or embedding), removing adapters, adding/removing models to existing adapters, or editing adapter configurations. Supports OpenAI-compatible providers, cloud providers (AWS Bedrock, VertexAI, Azure), and self-hosted models (Ollama).
This skill provides workflows and automation for extending LLM and embedding adapters in the unstract/sdk1 module.
| Operation | Command | Description |
|---|---|---|
| Add LLM Adapter | scripts/init_llm_adapter.py | Create new LLM provider adapter |
| Add Embedding Adapter | scripts/init_embedding_adapter.py | Create new embedding provider adapter |
| Remove Adapter | Manual deletion | Remove adapter files and parameter class |
| Add/Remove Models | scripts/manage_models.py | Modify available models in JSON schema |
| Edit Adapter | Manual edit | Modify existing adapter behavior |
| Check for Updates |
scripts/check_adapter_updates.py| Compare adapters against LiteLLM features |
unstract/sdk1/src/unstract/sdk1/adapters/
├── base1.py # Parameter classes (add new ones here)
├── llm1/ # LLM adapters
│ ├── {provider}.py # Adapter implementation
│ └── static/{provider}.json # UI schema
└── embedding1/ # Embedding adapters
├── {provider}.py # Adapter implementation
└── static/{provider}.json # UI schema
Adapter IDs follow the pattern: {provider}|{uuid4}
openai|502ecf49-e47c-445c-9907-6d4b90c5cd17python -c "import uuid; print(uuid.uuid4())"LiteLLM requires provider prefixes on model names:
| Provider | Prefix | Example |
|---|---|---|
| OpenAI | openai/ | openai/gpt-4 |
| Azure | azure/ | azure/gpt-4-deployment |
| Anthropic | anthropic/ | anthropic/claude-3-opus |
| Bedrock | bedrock/ | bedrock/anthropic.claude-v2 |
| VertexAI | vertex_ai/ | vertex_ai/gemini-pro |
| Ollama | ollama_chat/ | ollama_chat/llama2 |
| Mistral | mistral/ | mistral/mistral-large |
| Anyscale | anyscale/ | anyscale/meta-llama/Llama-2-70b |
Run initialization script:
python .claude/skills/unstract-adapter-extension/scripts/init_llm_adapter.py \
--provider newprovider \
--name "New Provider" \
--description "New Provider LLM adapter" \
--auto-logo
Logo options:
--auto-logo: Search for potential logo sources (Clearbit, GitHub) and display suggestions. Does NOT auto-download - you must verify and use --logo-url to download.--logo-url URL: Download logo from a verified URL (supports SVG and raster images)--logo-file PATH: Copy logo from local file (supports SVG and raster images)Logo image settings (optimized for sharp rendering):
sudo pacman -S imagemagick)GitHub logo URL tip: When downloading logos from GitHub, always use the raw URL:
https://github.com/user/repo/blob/main/logo.svghttps://raw.githubusercontent.com/user/repo/main/logo.svgLogos are saved to: frontend/public/icons/adapter-icons/{ProviderName}.png
Add parameter class to base1.py (if provider has unique parameters):
class NewProviderLLMParameters(BaseChatCompletionParameters):
"""See https://docs.litellm.ai/docs/providers/newprovider."""
api_key: str
# Add provider-specific fields
@staticmethod
def validate(adapter_metadata: dict[str, "Any"]) -> dict[str, "Any"]:
adapter_metadata["model"] = NewProviderLLMParameters.validate_model(adapter_metadata)
return NewProviderLLMParameters(**adapter_metadata).model_dump()
@staticmethod
def validate_model(adapter_metadata: dict[str, "Any"]) -> str:
model = adapter_metadata.get("model", "")
if model.startswith("newprovider/"):
return model
return f"newprovider/{model}"
Update adapter class to inherit from new parameter class:
Run initialization script:
python .claude/skills/unstract-adapter-extension/scripts/init_embedding_adapter.py \
--provider newprovider \
--name "New Provider" \
--description "New Provider embedding adapter" \
--auto-logo
Same logo options as LLM adapter: --auto-logo (search only), --logo-url, --logo-file
Add parameter class to base1.py (if needed):
class NewProviderEmbeddingParameters(BaseEmbeddingParameters):
"""See https://docs.litellm.ai/docs/providers/newprovider."""
api_key: str
embed_batch_size: int | None = 10
@staticmethod
def validate(adapter_metadata: dict[str, "Any"]) -> dict[str, "Any"]:
adapter_metadata["model"] = NewProviderEmbeddingParameters.validate_model(adapter_metadata)
return NewProviderEmbeddingParameters(**adapter_metadata).model_dump()
@staticmethod
def validate_model(adapter_metadata: dict[str, "Any"]) -> str:
return adapter_metadata.get("model", "")
Update adapter class and JSON schema
llm1/{provider}.py or embedding1/{provider}.pyllm1/static/{provider}.json or embedding1/static/{provider}.jsonbase1.py (if dedicated class exists)Adapterkit().get_adapters_list() to confirmEdit JSON schema (static/{provider}.json):
{
"properties": {
"model": {
"type": "string",
"title": "Model",
"default": "new-default-model",
"description": "Available models: model-1, model-2, model-3"
}
}
}
For dropdown selection, use enum:
{
"properties": {
"model": {
"type": "string",
"title": "Model",
"enum": ["model-1", "model-2", "model-3"],
"default": "model-1"
}
}
}
Run management script for automated updates:
python .claude/skills/unstract-adapter-extension/scripts/manage_models.py \
--adapter llm \
--provider openai \
--action add \
--models "gpt-4-turbo,gpt-4o-mini"
Common modifications:
Add reasoning/thinking support:
enable_thinking boolean field to JSON schemathinking config in validate() methodAnthropicLLMParameters in base1.py for referenceAdd custom field mapping:
@staticmethod
def validate(adapter_metadata: dict[str, "Any"]) -> dict[str, "Any"]:
# Map custom field names to expected names
if "custom_field" in adapter_metadata:
adapter_metadata["expected_field"] = adapter_metadata["custom_field"]
# Continue validation...
Add conditional fields in JSON schema:
{
"allOf": [
{
"if": { "properties": { "feature_enabled": { "const": true } } },
"then": {
"properties": { "feature_config": { "type": "string" } },
"required": ["feature_config"]
}
}
]
}
Compare existing adapter schemas against known LiteLLM features to identify potential updates:
Run the update checker:
# Check all adapters
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py
# Check specific adapter type
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py --adapter llm
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py --adapter embedding
# Check specific provider
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py --provider openai
# Output as JSON
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py --json
Review the report:
Common update types identified:
dimensions for embeddings)After identifying updates:
static/{provider}.jsonbase1.py if validation logic changesUpdate the feature database (check_adapter_updates.py):
LITELLM_FEATURES dict to add new providers or parametersknown_params, reasoning_models, thinking_models, latest_models currentBefore submitting adapter changes:
BaseAdapterget_id() returns unique {provider}|{uuid} formatget_metadata() returns dict with name, version, adapter, description, is_activeget_provider() returns value matching litellm_provider in LiteLLM pricing data (see below)get_adapter_type() returns correct AdapterTypes.LLM or AdapterTypes.EMBEDDINGadapter_name as required fieldvalidate() method adds correct model prefixvalidate_model() method handles prefix idempotently (doesn't double-prefix)@staticmethod/icons/adapter-icons/{Name}.pngThe get_provider() return value is used for cost calculation. It MUST match the litellm_provider field in LiteLLM's pricing data, otherwise costs will show as $0.
Before implementing any adapter, verify the provider name:
# Fetch LiteLLM pricing data and check provider name
curl -s https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json | \
jq 'to_entries | map(select(.value.litellm_provider != null)) |
map({key: .key, provider: .value.litellm_provider}) |
unique_by(.provider) |
sort_by(.provider) |
.[].provider' | sort -u
Common provider name mappings:
| Display Name | get_provider() Value | LiteLLM Provider |
|---|---|---|
| OpenAI | openai | openai |
| Anthropic | anthropic | anthropic |
| Azure OpenAI | azure | azure |
| Azure AI Foundry | azure_ai | azure_ai |
| AWS Bedrock | bedrock | bedrock |
| Google VertexAI | vertex_ai | vertex_ai |
| Mistral | mistral | mistral |
| Ollama | ollama | ollama |
Example verification for Azure AI Foundry:
curl -s https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json | \
jq 'to_entries | map(select(.key | startswith("azure_ai"))) | .[0].value.litellm_provider'
# Output: "azure_ai" (NOT "azure_ai_foundry")
Why this matters:
The cost calculation in platform-service/src/unstract/platform_service/helper/cost_calculation.py filters models by checking if the provider string is contained in litellm_provider. A mismatch (e.g., returning "azure_ai_foundry" when LiteLLM uses "azure_ai") causes the cost lookup to fail silently, returning $0.
Periodic maintenance to keep adapters current with LiteLLM features:
Run the update checker:
python .claude/skills/unstract-adapter-extension/scripts/check_adapter_updates.py
Review LiteLLM changelog for new provider features:
Update feature database in check_adapter_updates.py:
known_params for each providerreasoning_models and thinking_models listslatest_models with current defaultsApply updates following priority:
When upgrading LiteLLM dependency:
When LiteLLM adds a new provider:
https://docs.litellm.ai/docs/providers/{provider}check_adapter_updates.pyFor detailed patterns and examples, see:
references/adapter_patterns.md - Complete code patternsreferences/json_schema_guide.md - JSON schema patterns for UIreferences/provider_capabilities.md - Provider feature matrixassets/templates/ - Ready-to-use templatesLLMAdapter or EmbeddingAdapteris_active: True in metadatallm1/ or embedding1/)validate() returns properly validated dictbase1.pyTYPE_CHECKING guard)from unstract.sdk1.adapters.base1 import BaseAdapter, NewProviderLLMParameters
class NewProviderLLMAdapter(NewProviderLLMParameters, BaseAdapter):
# ... implementation
Customize JSON schema in llm1/static/newprovider.json for UI configuration
Test the adapter:
from unstract.sdk1.adapters.adapterkit import Adapterkit
kit = Adapterkit()
adapters = kit.get_adapters_list()
# Verify new adapter appears
PyTorch深度学习模式与最佳实践,用于构建稳健、高效且可复现的训练流程、模型架构和数据加载。