Skip to content

Feat/add litellm provider#338

Open
RheagalFire wants to merge 2 commits into
microsoft:mainfrom
RheagalFire:feat/add-litellm-provider
Open

Feat/add litellm provider#338
RheagalFire wants to merge 2 commits into
microsoft:mainfrom
RheagalFire:feat/add-litellm-provider

Conversation

@RheagalFire

Copy link
Copy Markdown

Summary

  • Add LiteLLM as a new AI provider, giving UFO users access to 100+ LLM providers (OpenAI, Anthropic, Google, Azure, Bedrock, Cohere, Mistral, and more) through a single unified interface.
  • Implements LiteLLMService extending BaseService, following the Claude provider pattern.

Motivation

UFO currently supports 6 individual LLM providers (OpenAI, Claude, Gemini, DeepSeek, Qwen, Ollama), each requiring separate configuration. Users who want providers not directly supported (Bedrock, Mistral, Cohere, Together AI, etc.) have no straightforward path.

LiteLLM routes to 100+ providers through provider-prefixed model names. Users switch providers by changing one config line - no additional SDKs needed.

Changes

  • ufo/llm/litellm.py - new LiteLLMService implementing BaseService
  • ufo/llm/base.py - added "litellm": "LiteLLMService" to service_map and cost estimator
  • requirements.txt - added litellm>=1.80,<1.87

Implementation details

  • Directly implements BaseService (not BaseOpenAIService) since LiteLLM handles all provider routing internally.
  • Uses litellm.completion() with drop_params=True to silently drop provider-unsupported kwargs for cross-provider compatibility.
  • Retry with exponential backoff on transient errors (rate limits, timeouts, 5xx), matching the existing Claude provider pattern.
  • Lazy import litellm inside method bodies so the import only fails when litellm is actually used, not at module load.
  • Messages are forwarded as-is (OpenAI format with multimodal content parts) since litellm accepts them natively.
  • Returns (responses, cost) tuple matching the BaseService.chat_completion contract.

Tests

1. Live E2E against Anthropic (via Azure Foundry):

$ ANTHROPIC_API_KEY=<key> ANTHROPIC_API_BASE=<url> python3 test_litellm.py

Model: anthropic/claude-sonnet-4-6
Response: 4
Cost: 0.0

Full chain verified: LiteLLMService.chat_completion() -> litellm.completion() -> Anthropic API -> response parsed with cost tracking.

Risk / Compatibility

  • Additive only. Existing providers (OpenAI, Claude, Gemini, DeepSeek, Qwen, Ollama) untouched.
  • LiteLLM is a new requirements.txt entry. Compatible with existing openai==1.66.2 pin.

Example usage

# config/ufo/agents.yaml
HOST_AGENT:
  API_TYPE: "litellm"
  API_MODEL: "anthropic/claude-sonnet-4-6"
  API_KEY: ""  # Or set provider-specific env vars (ANTHROPIC_API_KEY, etc.)
  API_BASE: ""  # Optional: LiteLLM proxy URL

APP_AGENT:
  API_TYPE: "litellm"
  API_MODEL: "openai/gpt-4o"

Python:

from ufo.llm.litellm import LiteLLMService

# No provider-specific config needed - just set API_TYPE and API_MODEL.
# LiteLLM routes automatically based on the model prefix.
# Provider API keys are read from env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)

service = LiteLLMService(config, agent_type="host_agent")
messages = [
    {"role": "system", "content": "You are a Windows UI automation agent."},
    {"role": "user", "content": [{"type": "text", "text": "Open Notepad and type hello"}]},
]

# Switch providers by changing the model string - no config changes needed:
#   "anthropic/claude-sonnet-4-6"  -> routes to Anthropic
#   "openai/gpt-4o"               -> routes to OpenAI
#   "gemini/gemini-2.5-pro"       -> routes to Google
#   "bedrock/anthropic.claude-v2" -> routes to AWS Bedrock
responses, cost = service.chat_completion(messages)
print(responses[0])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant