LLM Bridge: A Unified API Schema for OpenAI, Claude, and Gemini

7月8日 Published inLLM Tooling

LLM Bridge is a TypeScript library designed to resolve the inconsistencies of fragmented LLM APIs. It provides a unified conversion layer for OpenAI, Anthropic Claude, and Google Gemini, ensuring that requests and responses transition between providers without omitting fields or losing data.

The library functions by utilizing a universal schema. It maps provider-specific structures into a common format, ensuring that multimodal content—such as images and documents—is translated accurately. Furthermore, tool calls and function definitions remain intact during the conversion process, and errors are standardized into a predictable structure. With full TypeScript support, the library maintains strict type integrity throughout your workflow.

Key Capabilities

  • Reliable Conversion: Seamlessly switch between OpenAI, Anthropic, and Google formats.
  • Zero Data Loss: The _original field preserves the source data for exact reconstruction.
  • Multimodal Support: Transfer images and rich media across different provider ecosystems.
  • Tool Call Mapping: Automatically converts function-calling schemas between disparate provider requirements.
  • Unified Error Handling: Standardizes error shapes while retaining specific provider details internally.
  • Type Safety: Built with strict TypeScript definitions to catch errors during development.

Installation

npm install llm-bridge
# or
yarn add llm-bridge
# or
pnpm add llm-bridge

Quick Start

import { toUniversal, fromUniversal, translateBetweenProviders } from 'llm-bridge'

// Convert an OpenAI request to the universal format
const openaiRequest = {
  model: "gpt-4",
  messages: [
    { role: "system", content: "You are a helpful assistant" },
    { role: "user", content: "Hello!" }
  ],
  temperature: 0.7,
  max_tokens: 1000
}

const universal = toUniversal("openai", openaiRequest)

console.log(universal.provider) // "openai"
console.log(universal.model)    // "gpt-4"
console.log(universal.system)   // "You are a helpful assistant"

// Revert the universal format back to a specific provider
const anthropicRequest = fromUniversal("anthropic", universal)
const googleRequest = fromUniversal("google", universal)

// Alternatively, translate directly between providers
const anthropicRequest2 = translateBetweenProviders("openai", "anthropic", openaiRequest)

Data Integrity and Reconstruction

Round-trip conversions ensure that no information is lost during the process.

const original = { /* your OpenAI request */ }
const universal = toUniversal("openai", original)
const reconstructed = fromUniversal("openai", universal)

// The reconstructed object matches the original structure
console.log(reconstructed === original) // true

Core Features

1. Universal Format Translation

The library acts as a central hub for all major LLM providers:

OpenAI ←→ Universal ←→ Anthropic
  ↕                    ↕
Google ←→ Universal ←→ Custom

2. Multimodal Content

LLM Bridge facilitates the movement of images and documents between providers.

// OpenAI format containing a base64 image
const openaiMultimodal = {
  model: "gpt-4-vision-preview",
  messages: [{
    role: "user",
    content: [
      { type: "text", text: "What's in this image?" },
      {
        type: "image_url",
        image_url: {
          url: "data:image/jpeg;base64,iVBORw0KGgoAAAA...",
          detail: "high"
        }
      }
    ]
  }]
}

// Convert directly to Anthropic
const anthropicMultimodal = translateBetweenProviders("openai", "anthropic", openaiMultimodal)
// Result: An Anthropic-compatible format with the correct base64 source structure

3. Tool and Function Calls

Manage complex tool interactions across different platforms.

// OpenAI tool call configuration
const openaiWithTools = {
  model: "gpt-4",
  messages: [
    {
      role: "assistant",
      tool_calls: [{
        id: "call_123",
        type: "function",
        function: {
          name: "get_weather",
          arguments: '{"location": "San Francisco"}'
        }
      }]
    },
    {
      role: "tool",
      content: '{"temperature": 72, "condition": "sunny"}',
      tool_call_id: "call_123"
    }
  ],
  tools: [{
    type: "function",
    function: {
      name: "get_weather",
      description: "Get weather info",
      parameters: {
        type: "object",
        properties: {
          location: { type: "string" }
        }
      }
    }
  }]
}

// Convert the OpenAI schema to Google Gemini
const geminiWithTools = translateBetweenProviders("openai", "google", openaiWithTools)

4. Error Handling

import { buildUniversalError, translateError } from 'llm-bridge'

// Define a universal error object
const error = buildUniversalError(
  "rate_limit_error",
  "Rate limit exceeded",
  "openai",
  { retryAfter: 60 }
)

// Translate the error for different provider contexts
const anthropicError = translateError(error.universal, "anthropic")
const googleError = translateError(error.universal, "google")

5. Automated Provider Detection

Identify the source provider based on the request structure.

import { detectProvider } from 'llm-bridge'

detectProvider({ model: "gpt-4", messages: [...] })        // "openai"
detectProvider({ model: "claude-3-opus", max_tokens: 100 }) // "anthropic"
detectProvider({ contents: [...] })                        // "google"

Advanced Patterns

Universal Middleware

import { toUniversal, fromUniversal } from 'llm-bridge'

async function universalLLMMiddleware(request: any, targetProvider: string) {
  const sourceProvider = detectProvider(request)
  const universal = toUniversal(sourceProvider, request)

  // Enforce universal parameter constraints
  universal.temperature = Math.min(universal.temperature || 0, 1)
  universal.max_tokens = Math.min(universal.max_tokens || 1000, 4000)

  const targetRequest = fromUniversal(targetProvider, universal)
  return await callProvider(targetProvider, targetRequest)
}

Load Balancing with Automated Fallback

async function robustLLMCall(request: any) {
  const providers = ["openai", "anthropic", "google"]

  for (const provider of providers) {
    try {
      const universal = toUniversal(detectProvider(request), request)
      const providerRequest = fromUniversal(provider, universal)
      return await callProvider(provider, providerRequest)
    } catch (error) {
      console.log(`${provider} failed, attempting next available provider...`)
      continue
    }
  }
  throw new Error("All providers failed to respond")
}

Cost Optimization

import { getModelCosts, countUniversalTokens } from 'llm-bridge'

function optimizeModelChoice(request: any) {
  const universal = toUniversal(detectProvider(request), request)
  const tokens = countUniversalTokens(universal)

  const models = [
    { provider: "openai", model: "gpt-4o-mini" },
    { provider: "anthropic", model: "claude-3-haiku" },
    { provider: "google", model: "gemini-1.5-flash" }
  ]

  const costs = models.map(({ provider, model }) => {
    const modelCosts = getModelCosts(model)
    const inputCost = (tokens.inputTokens / 1000) * modelCosts.inputCostPer1K
    const outputCost = (tokens.outputTokens / 1000) * modelCosts.outputCostPer1K
    return { provider, model, totalCost: inputCost + outputCost }
  })

  // Select the most cost-effective option
  return costs.sort((a, b) => a.totalCost - b.totalCost)[0]
}

API Reference

Core Translation Functions

  • toUniversal(provider, body): Converts provider-specific data to the universal format.
  • fromUniversal(provider, universal): Converts the universal format back to a specific provider.
  • translateBetweenProviders(from, to, body): Performs a direct conversion between two providers.
  • detectProvider(body): Automatically identifies the provider based on request properties.

Utility Functions

  • getModelDetails(model): Retrieves specific model capabilities.
  • getModelCosts(model): Accesses current pricing information.
  • countUniversalTokens(universal): Provides a token count estimate.
  • createObservabilityData(universal): Generates data for telemetry and logging.

Error Management

  • buildUniversalError(type, message, provider, options)
  • translateError(error, targetProvider)
  • parseProviderError(error, provider)

Example: Multi-Provider Chat Implementation

import { translateBetweenProviders, detectProvider } from 'llm-bridge'

class UniversalChatBot {
  async chat(message: string, preferredProvider = "openai") {
    const request = {
      model: this.getPreferredModel(preferredProvider),
      messages: [
        { role: "system", content: "You are a helpful assistant" },
        { role: "user", content: message }
      ],
      temperature: 0.7
    }

    try {
      return await this.callProvider(preferredProvider, request)
    } catch (error) {
      const fallbacks = ["anthropic", "google", "openai"]
        .filter(p => p !== preferredProvider)

      for (const provider of fallbacks) {
        try {
          const translated = translateBetweenProviders(
            preferredProvider,
            provider,
            request
          )
          return await this.callProvider(provider, translated)
        } catch (fallbackError) {
          continue
        }
      }
      throw new Error("Unable to complete request: All providers failed")
    }
  }

  private getPreferredModel(provider: string) {
    const models = {
      openai: "gpt-4",
      anthropic: "claude-3-opus-20240229",
      google: "gemini-1.5-pro"
    }
    return models[provider] || "gpt-4"
  }
}

Cross-Provider Image Analysis

async function analyzeImage(imageUrl: string, provider: string) {
  const request = {
    model: "gpt-4-vision-preview",
    messages: [{
      role: "user",
      content: [
        { type: "text", text: "Provide a detailed analysis of this image." },
        { type: "image_url", image_url: { url: imageUrl } }
      ]
    }]
  }

  const translated = translateBetweenProviders("openai", provider, request)
  return await callProvider(provider, translated)
}