ai.matey.frontend
Frontend adapters define the input format for your AI requests. Write code in any API format you prefer - OpenAI, Anthropic, Google Gemini, or others.
Installation
Section titled “Installation”npm install ai.matey.frontendOverview
Section titled “Overview”Frontend adapters translate your chosen API format into ai.matey’s Intermediate Representation (IR). This allows you to write code in whatever format you’re most comfortable with.
Available Adapters:
- OpenAI
- Anthropic
- Google Gemini
- Ollama
- Cohere
- Mistral
- Groq
OpenAI Frontend Adapter
Section titled “OpenAI Frontend Adapter”Use OpenAI’s API format as input.
Installation
Section titled “Installation”import { OpenAIFrontendAdapter } from 'ai.matey.frontend/openai';import { Bridge } from 'ai.matey.core';import { OpenAIFrontendAdapter } from 'ai.matey.frontend/openai';import { AnthropicBackendAdapter } from 'ai.matey.backend/anthropic';
const bridge = new Bridge( new OpenAIFrontendAdapter(), new AnthropicBackendAdapter({ apiKey: 'your-key' }));
// Write in OpenAI formatconst response = await bridge.chat({ model: 'gpt-4', messages: [ { role: 'system', content: 'You are helpful.' }, { role: 'user', content: 'Hello!' } ], temperature: 0.7, max_tokens: 100});Supported Features
Section titled “Supported Features”- ✅ Chat completions
- ✅ Streaming
- ✅ Function calling/tools
- ✅ Vision (image inputs)
- ✅ System messages
- ✅ Temperature, top_p, max_tokens
- ✅ Stop sequences
- ✅ Presence/frequency penalties
Request Format
Section titled “Request Format”interface OpenAIChatRequest { model: string; messages: OpenAIMessage[]; temperature?: number; max_tokens?: number; top_p?: number; n?: number; stream?: boolean; stop?: string | string[]; presence_penalty?: number; frequency_penalty?: number; logit_bias?: Record<string, number>; user?: string; tools?: OpenAITool[]; tool_choice?: 'none' | 'auto' | { type: 'function'; function: { name: string } };}Anthropic Frontend Adapter
Section titled “Anthropic Frontend Adapter”Use Anthropic’s API format as input.
Installation
Section titled “Installation”import { AnthropicFrontendAdapter } from 'ai.matey.frontend/anthropic';import { Bridge } from 'ai.matey.core';import { AnthropicFrontendAdapter } from 'ai.matey.frontend/anthropic';import { OpenAIBackendAdapter } from 'ai.matey.backend/openai';
const bridge = new Bridge( new AnthropicFrontendAdapter(), new OpenAIBackendAdapter({ apiKey: 'your-key' }));
// Write in Anthropic formatconst response = await bridge.chat({ model: 'claude-3-5-sonnet-20241022', max_tokens: 100, messages: [ { role: 'user', content: 'Hello!' } ], system: 'You are helpful.', // System message separate temperature: 0.7});Key Differences from OpenAI
Section titled “Key Differences from OpenAI”- System messages are a separate
systemparameter (not in messages array) max_tokensis required- No
presence_penaltyorfrequency_penalty - Different tool/function calling format
Supported Features
Section titled “Supported Features”- ✅ Chat completions
- ✅ Streaming
- ✅ Tool use
- ✅ Vision (image inputs)
- ✅ System messages (as parameter)
- ✅ Temperature, top_p, top_k
- ✅ Stop sequences
Google Gemini Frontend Adapter
Section titled “Google Gemini Frontend Adapter”Use Google’s Gemini API format as input.
Installation
Section titled “Installation”import { GeminiFrontendAdapter } from 'ai.matey.frontend/gemini';import { Bridge } from 'ai.matey.core';import { GeminiFrontendAdapter } from 'ai.matey.frontend/gemini';import { OpenAIBackendAdapter } from 'ai.matey.backend/openai';
const bridge = new Bridge( new GeminiFrontendAdapter(), new OpenAIBackendAdapter({ apiKey: 'your-key' }));
// Write in Gemini formatconst response = await bridge.chat({ model: 'gemini-1.5-pro', contents: [ { role: 'user', parts: [{ text: 'Hello!' }] } ], generationConfig: { temperature: 0.7, maxOutputTokens: 100 }});Key Differences
Section titled “Key Differences”- Uses
contentsinstead ofmessages - Uses
partsfor multi-modal content - Role is
modelinstead ofassistant - Configuration in
generationConfigobject - System instructions separate parameter
Supported Features
Section titled “Supported Features”- ✅ Chat completions
- ✅ Streaming
- ✅ Function calling
- ✅ Vision (native multi-modal support)
- ✅ System instructions
- ✅ Temperature, topP, topK
- ✅ Stop sequences
- ✅ Safety settings
Ollama Frontend Adapter
Section titled “Ollama Frontend Adapter”Use Ollama’s API format (compatible with local models).
Installation
Section titled “Installation”import { OllamaFrontendAdapter } from 'ai.matey.frontend/ollama';import { Bridge } from 'ai.matey.core';import { OllamaFrontendAdapter } from 'ai.matey.frontend/ollama';import { OpenAIBackendAdapter } from 'ai.matey.backend/openai';
const bridge = new Bridge( new OllamaFrontendAdapter(), new OpenAIBackendAdapter({ apiKey: 'your-key' }));
// Write in Ollama formatconst response = await bridge.chat({ model: 'llama3.2', messages: [ { role: 'user', content: 'Hello!' } ], stream: false});Supported Features
Section titled “Supported Features”- ✅ Chat completions
- ✅ Streaming
- ✅ System messages
- ✅ Temperature, top_p, top_k
- ⚠️ Limited tool support (model-dependent)
Cohere Frontend Adapter
Section titled “Cohere Frontend Adapter”Use Cohere’s API format as input.
Installation
Section titled “Installation”import { CohereFrontendAdapter } from 'ai.matey.frontend/cohere';import { Bridge } from 'ai.matey.core';import { CohereFrontendAdapter } from 'ai.matey.frontend/cohere';import { OpenAIBackendAdapter } from 'ai.matey.backend/openai';
const bridge = new Bridge( new CohereFrontendAdapter(), new OpenAIBackendAdapter({ apiKey: 'your-key' }));
// Write in Cohere formatconst response = await bridge.chat({ model: 'command-r-plus', message: 'Hello!', chat_history: [ { role: 'USER', message: 'Hi' }, { role: 'CHATBOT', message: 'Hello!' } ], temperature: 0.7});Key Differences
Section titled “Key Differences”- Uses
messagefor current user message - Chat history separate from current message
- Roles are
USERandCHATBOT(uppercase) - Different parameter names
Mistral Frontend Adapter
Section titled “Mistral Frontend Adapter”Use Mistral’s API format (very similar to OpenAI).
Installation
Section titled “Installation”import { MistralFrontendAdapter } from 'ai.matey.frontend/mistral';import { Bridge } from 'ai.matey.core';import { MistralFrontendAdapter } from 'ai.matey.frontend/mistral';import { OpenAIBackendAdapter } from 'ai.matey.backend/openai';
const bridge = new Bridge( new MistralFrontendAdapter(), new OpenAIBackendAdapter({ apiKey: 'your-key' }));
// Mistral format is very similar to OpenAIconst response = await bridge.chat({ model: 'mistral-large-latest', messages: [ { role: 'user', content: 'Hello!' } ], temperature: 0.7});Groq Frontend Adapter
Section titled “Groq Frontend Adapter”Use Groq’s API format (OpenAI-compatible).
Installation
Section titled “Installation”import { GroqFrontendAdapter } from 'ai.matey.frontend/groq';import { Bridge } from 'ai.matey.core';import { GroqFrontendAdapter } from 'ai.matey.frontend/groq';import { AnthropicBackendAdapter } from 'ai.matey.backend/anthropic';
const bridge = new Bridge( new GroqFrontendAdapter(), new AnthropicBackendAdapter({ apiKey: 'your-key' }));
// Groq uses OpenAI-compatible formatconst response = await bridge.chat({ model: 'llama3-8b-8192', messages: [ { role: 'user', content: 'Hello!' } ]});Choosing a Frontend Adapter
Section titled “Choosing a Frontend Adapter”Use OpenAI Frontend Adapter if:
Section titled “Use OpenAI Frontend Adapter if:”- You’re familiar with OpenAI’s API
- You want the most widely-used format
- Your codebase already uses OpenAI
- You need maximum compatibility
Use Anthropic Frontend Adapter if:
Section titled “Use Anthropic Frontend Adapter if:”- You prefer Anthropic’s API design
- You want explicit system message separation
- Your codebase uses Claude
Use Gemini Frontend Adapter if:
Section titled “Use Gemini Frontend Adapter if:”- You’re working with Google AI Platform
- You need native multi-modal support
- You use Vertex AI
Use Ollama Frontend Adapter if:
Section titled “Use Ollama Frontend Adapter if:”- You’re working with local models
- You want a simple format
- You’re developing locally
Feature Compatibility Matrix
Section titled “Feature Compatibility Matrix”| Feature | OpenAI | Anthropic | Gemini | Ollama | Cohere | Mistral | Groq |
|---|---|---|---|---|---|---|---|
| Chat | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Streaming | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Tools/Functions | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ⚠️ |
| Vision | ✅ | ✅ | ✅ | ⚠️ | ❌ | ⚠️ | ⚠️ |
| System Messages | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
✅ Fully supported | ⚠️ Partially supported | ❌ Not supported
Creating Custom Frontend Adapters
Section titled “Creating Custom Frontend Adapters”You can create your own frontend adapter:
import { FrontendAdapter } from 'ai.matey.core';import type { IRChatCompletionRequest, IRChatCompletionResponse } from 'ai.matey.types';
export class CustomFrontendAdapter implements FrontendAdapter { name = 'custom';
// Convert custom format to IR toIR(request: CustomRequest): IRChatCompletionRequest { return { model: request.modelName, messages: request.conversation.map(msg => ({ role: msg.sender === 'human' ? 'user' : 'assistant', content: msg.text })), temperature: request.temp, max_tokens: request.maxLength }; }
// Convert IR back to custom format fromIR(response: IRChatCompletionResponse): CustomResponse { return { reply: response.choices[0].message.content, tokens: response.usage?.total_tokens || 0 }; }
// Stream support (optional) async *fromIRStream(stream: AsyncIterable<IRChatCompletionChunk>) { for await (const chunk of stream) { yield { text: chunk.choices?.[0]?.delta?.content || '', done: chunk.choices?.[0]?.finish_reason !== null }; } }}Best Practices
Section titled “Best Practices”1. Choose Based on Your Codebase
Section titled “1. Choose Based on Your Codebase”If your codebase already uses a specific API format, use that frontend adapter:
// Existing OpenAI codeconst openaiResponse = await openai.chat.completions.create({ model: 'gpt-4', messages: [{ role: 'user', content: 'Hello' }]});
// Easy migration - use OpenAI frontend adapterconst bridge = new Bridge( new OpenAIFrontendAdapter(), // Same format! new AnthropicBackendAdapter({ apiKey }));2. Frontend is Independent of Backend
Section titled “2. Frontend is Independent of Backend”Mix and match any frontend with any backend:
// OpenAI format → Anthropic backendnew Bridge(new OpenAIFrontendAdapter(), new AnthropicBackendAdapter({ apiKey }));
// Anthropic format → OpenAI backendnew Bridge(new AnthropicFrontendAdapter(), new OpenAIBackendAdapter({ apiKey }));
// Gemini format → Groq backendnew Bridge(new GeminiFrontendAdapter(), new GroqBackendAdapter({ apiKey }));3. Type Safety
Section titled “3. Type Safety”Use TypeScript for frontend-specific request types:
import type { OpenAIChatRequest, OpenAIChatResponse } from 'ai.matey.frontend/openai';
const bridge = new Bridge( new OpenAIFrontendAdapter(), new AnthropicBackendAdapter({ apiKey }));
const request: OpenAIChatRequest = { model: 'gpt-4', messages: [{ role: 'user', content: 'Hello' }]};
const response: OpenAIChatResponse = await bridge.chat(request);Semantic Drift
Section titled “Semantic Drift”When converting between formats, some features may not map perfectly. This is called “semantic drift.”
Example: System Messages
Section titled “Example: System Messages”// OpenAI: system messages in array{ messages: [ { role: 'system', content: 'You are helpful.' }, { role: 'user', content: 'Hello' } ]}
// Anthropic: system separate{ system: 'You are helpful.', messages: [ { role: 'user', content: 'Hello' } ]}The adapter handles this automatically, but be aware of potential drift.
Handling Drift
Section titled “Handling Drift”Frontend adapters track and warn about semantic drift:
const response = await bridge.chat(request);
if (response.warnings) { console.warn('Semantic drift detected:', response.warnings);}See Also
Section titled “See Also”- Backend Adapters - Available backend providers
- IR Format - Intermediate representation details
- Core Package - Bridge and Router documentation
- Tutorial: Simple Bridge - Step-by-step guide