Learn how to integrate and optimize AI development frameworks for efficient model management. This guide covers LangChain, OpenRouter, Together AI, and custom provider solutions with practical implementation examples.
Framework Comparison Overview
Framework Capabilities
Framework | Type | Strengths | Best For | Cost Model |
---|---|---|---|---|
LangChain | Orchestration | Comprehensive ecosystem, chains | Complex workflows, RAG | Free (OSS) + provider costs |
OpenRouter | API Gateway | Model routing, unified API | Model experimentation | Pay-per-token + markup |
Together AI | Hosting Platform | Open source models, fine-tuning | Custom models, inference | Pay-per-token |
Custom Solutions | DIY | Full control, optimization | Specific requirements | Development time + hosting |
:::tip Framework Selection Strategy Use LangChain for complex AI workflows, OpenRouter for model experimentation and unified access, Together AI for open-source model hosting, and custom solutions for specific optimization needs. :::
LangChain Integration
Setup and Basic Configuration
// LangChain setup with multiple providers
import { ChatOpenAI } from '@langchain/openai';
import { ChatAnthropic } from '@langchain/anthropic';
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { RunnableSequence } from '@langchain/core/runnables';
// Provider configuration
const providers = {
openai: new ChatOpenAI({
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4',
temperature: 0.7,
maxTokens: 1000,
}),
anthropic: new ChatAnthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-5-sonnet-20241022',
temperature: 0.7,
maxTokens: 1000,
}),
google: new ChatGoogleGenerativeAI({
apiKey: process.env.GOOGLE_AI_API_KEY,
model: 'gemini-pro',
temperature: 0.7,
maxOutputTokens: 1000,
})
};
// Basic chain creation
async function createBasicChain(providerName = 'openai') {
const model = providers[providerName];
const prompt = PromptTemplate.fromTemplate(
"Answer the following question: {question}"
);
const chain = RunnableSequence.from([
prompt,
model,
new StringOutputParser()
]);
return chain;
}
// Usage example
async function basicLangChainExample() {
const chain = await createBasicChain('anthropic');
const result = await chain.invoke({
question: "What are the benefits of renewable energy?"
});
console.log(result);
}
Advanced LangChain Patterns
// Multi-provider routing with LangChain
import { RouterChain } from '@langchain/core/chains';
import { LLMRouterChain, MultiPromptChain } from 'langchain/chains';
import { ConversationChain } from 'langchain/chains';
class LangChainProviderRouter {
constructor() {
this.providers = providers;
this.setupRouterChains();
}
setupRouterChains() {
// Define different chain types for different tasks
this.chainConfigs = {
reasoning: {
provider: 'anthropic',
prompt: PromptTemplate.fromTemplate(
"Think step by step to answer: {input}"
)
},
creative: {
provider: 'openai',
prompt: PromptTemplate.fromTemplate(
"Be creative and engaging when answering: {input}"
)
},
factual: {
provider: 'google',
prompt: PromptTemplate.fromTemplate(
"Provide accurate, factual information about: {input}"
)
}
};
}
async routeToOptimalChain(input, taskType = 'auto') {
// Auto-detect task type if not specified
if (taskType === 'auto') {
taskType = await this.detectTaskType(input);
}
const config = this.chainConfigs[taskType] || this.chainConfigs['factual'];
const model = this.providers[config.provider];
const chain = RunnableSequence.from([
config.prompt,
model,
new StringOutputParser()
]);
return await chain.invoke({ input });
}
async detectTaskType(input) {
// Simple keyword-based detection (could be enhanced with ML)
const keywords = {
reasoning: ['analyze', 'explain', 'why', 'how', 'because', 'logic'],
creative: ['create', 'write', 'story', 'poem', 'creative', 'imagine'],
factual: ['what', 'when', 'where', 'who', 'fact', 'data', 'statistics']
};
const inputLower = input.toLowerCase();
const scores = {};
for (const [type, words] of Object.entries(keywords)) {
scores[type] = words.filter(word => inputLower.includes(word)).length;
}
return Object.entries(scores).reduce((a, b) => scores[a[0]] > scores[b[0]] ? a : b)[0];
}
}
LangChain RAG Implementation
// RAG (Retrieval Augmented Generation) with LangChain
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { HNSWLib } from '@langchain/community/vectorstores/hnswlib';
import { OpenAIEmbeddings } from '@langchain/openai';
import { RetrievalQAChain } from 'langchain/chains';
class LangChainRAGSystem {
constructor() {
this.embeddings = new OpenAIEmbeddings({
apiKey: process.env.OPENAI_API_KEY,
});
this.vectorStore = null;
this.qaChain = null;
}
async setupRAG(documents) {
// Split documents into chunks
const textSplitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
const splitDocs = await textSplitter.splitDocuments(documents);
// Create vector store
this.vectorStore = await HNSWLib.fromDocuments(
splitDocs,
this.embeddings
);
// Create QA chain with provider selection
this.qaChain = RetrievalQAChain.fromLLM(
providers.anthropic, // Use Claude for reasoning tasks
this.vectorStore.asRetriever(3) // Retrieve top 3 relevant chunks
);
}
async query(question, options = {}) {
if (!this.qaChain) {
throw new Error('RAG system not initialized. Call setupRAG first.');
}
const { provider = 'anthropic', includeSourceDocuments = true } = options;
// Switch provider if requested
if (provider !== 'anthropic') {
this.qaChain = RetrievalQAChain.fromLLM(
providers[provider],
this.vectorStore.asRetriever(3)
);
}
const result = await this.qaChain.call({
query: question,
return_source_documents: includeSourceDocuments
});
return {
answer: result.text,
sources: includeSourceDocuments ? result.sourceDocuments : []
};
}
async addDocuments(newDocuments) {
const textSplitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
const splitDocs = await textSplitter.splitDocuments(newDocuments);
await this.vectorStore.addDocuments(splitDocs);
}
}
OpenRouter Integration
Setup and Configuration
// OpenRouter SDK setup and configuration
import OpenAI from 'openai';
class OpenRouterClient {
constructor() {
this.client = new OpenAI({
baseURL: 'https://openrouter.ai/api/v1',
apiKey: process.env.OPENROUTER_API_KEY,
defaultHeaders: {
'HTTP-Referer': process.env.YOUR_SITE_URL || 'http://localhost:3000',
'X-Title': process.env.YOUR_APP_NAME || 'AI App',
}
});
this.modelPricing = new Map();
this.loadModelPricing();
}
async loadModelPricing() {
try {
// Fetch current model pricing from OpenRouter
const response = await fetch('https://openrouter.ai/api/v1/models', {
headers: {
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`
}
});
const models = await response.json();
models.data.forEach(model => {
this.modelPricing.set(model.id, {
prompt: parseFloat(model.pricing.prompt),
completion: parseFloat(model.pricing.completion)
});
});
} catch (error) {
console.error('Failed to load OpenRouter pricing:', error);
}
}
async complete(prompt, options = {}) {
const {
model = 'anthropic/claude-3.5-sonnet',
maxTokens = 1000,
temperature = 0.7,
stream = false
} = options;
try {
const response = await this.client.chat.completions.create({
model: model,
messages: [{ role: 'user', content: prompt }],
max_tokens: maxTokens,
temperature: temperature,
stream: stream
});
return {
text: response.choices[0].message.content,
usage: response.usage,
cost: this.calculateCost(response.usage, model),
model: model
};
} catch (error) {
console.error('OpenRouter API error:', error);
throw error;
}
}
calculateCost(usage, model) {
const pricing = this.modelPricing.get(model);
if (!pricing) return null;
return (usage.prompt_tokens * pricing.prompt +
usage.completion_tokens * pricing.completion) / 1000000;
}
}
OpenRouter Model Selection and Optimization
// Advanced OpenRouter features
class OptimizedOpenRouter extends OpenRouterClient {
constructor() {
super();
this.modelPerformance = new Map();
this.setupModelCategories();
}
setupModelCategories() {
// Categorize models by use case and performance characteristics
this.modelCategories = {
'fast-cheap': [
'meta-llama/llama-3.1-8b-instruct:free',
'microsoft/wizardlm-2-8x22b',
'google/gemma-7b-it:free'
],
'balanced': [
'anthropic/claude-3.5-sonnet',
'openai/gpt-4o-mini',
'google/gemini-pro'
],
'premium': [
'openai/gpt-4o',
'anthropic/claude-3-opus',
'google/gemini-pro-1.5'
],
'coding': [
'anthropic/claude-3.5-sonnet',
'openai/gpt-4o',
'deepseek/deepseek-coder'
],
'reasoning': [
'anthropic/claude-3.5-sonnet',
'openai/o1-preview',
'openai/gpt-4o'
]
};
}
async selectOptimalModel(prompt, requirements = {}) {
const {
budget = 'balanced',
taskType = 'general',
maxLatency = 10000,
minQuality = 0.7
} = requirements;
let candidateModels = this.modelCategories[budget] || this.modelCategories['balanced'];
// Filter by task type if specified
if (taskType !== 'general' && this.modelCategories[taskType]) {
candidateModels = this.modelCategories[taskType];
}
// Score models based on historical performance
const scoredModels = candidateModels.map(model => ({
model,
score: this.calculateModelScore(model, requirements)
}));
// Sort by score and return best model
scoredModels.sort((a, b) => b.score - a.score);
return scoredModels[0].model;
}
calculateModelScore(model, requirements) {
const performance = this.modelPerformance.get(model) || {
avgLatency: 3000,
avgQuality: 0.8,
avgCost: 0.001
};
let score = 0;
// Latency score (lower is better)
if (performance.avgLatency <= requirements.maxLatency) {
score += (requirements.maxLatency - performance.avgLatency) / requirements.maxLatency * 30;
}
// Quality score
if (performance.avgQuality >= requirements.minQuality) {
score += performance.avgQuality * 40;
}
// Cost efficiency score (lower cost is better)
score += (1 - Math.min(performance.avgCost / 0.01, 1)) * 20;
// Model availability score
score += 10; // Base availability score
return score;
}
async completeWithOptimalModel(prompt, requirements = {}) {
const selectedModel = await this.selectOptimalModel(prompt, requirements);
console.log(`Selected model: ${selectedModel}`);
const startTime = Date.now();
const result = await this.complete(prompt, {
model: selectedModel,
...requirements
});
const endTime = Date.now();
// Update performance metrics
this.updateModelPerformance(selectedModel, {
latency: endTime - startTime,
cost: result.cost
});
return {
...result,
selectedModel,
latency: endTime - startTime
};
}
updateModelPerformance(model, metrics) {
const current = this.modelPerformance.get(model) || {
avgLatency: 3000,
avgQuality: 0.8,
avgCost: 0.001,
samples: 0
};
const samples = current.samples + 1;
const alpha = 1 / Math.min(samples, 100); // Exponential moving average
this.modelPerformance.set(model, {
avgLatency: current.avgLatency * (1 - alpha) + metrics.latency * alpha,
avgCost: current.avgCost * (1 - alpha) + metrics.cost * alpha,
avgQuality: current.avgQuality, // Quality would need separate evaluation
samples
});
}
}
OpenRouter Streaming and Fallbacks
// Streaming and fallback implementation
class RobustOpenRouter extends OptimizedOpenRouter {
constructor() {
super();
this.fallbackModels = new Map();
this.setupFallbacks();
}
setupFallbacks() {
// Define fallback chains for different model categories
this.fallbackModels.set('anthropic/claude-3.5-sonnet', [
'openai/gpt-4o-mini',
'google/gemini-pro',
'meta-llama/llama-3.1-70b-instruct'
]);
this.fallbackModels.set('openai/gpt-4o', [
'anthropic/claude-3.5-sonnet',
'openai/gpt-4o-mini',
'google/gemini-pro'
]);
}
async completeWithFallback(prompt, options = {}) {
const primaryModel = await this.selectOptimalModel(prompt, options);
const fallbacks = this.fallbackModels.get(primaryModel) || [];
const modelsToTry = [primaryModel, ...fallbacks];
for (const model of modelsToTry) {
try {
return await this.complete(prompt, { ...options, model });
} catch (error) {
console.warn(`Model ${model} failed: ${error.message}`);
// If this was the last model, throw the error
if (model === modelsToTry[modelsToTry.length - 1]) {
throw new Error(`All models failed. Last error: ${error.message}`);
}
continue;
}
}
}
async streamWithFallback(prompt, options = {}) {
const primaryModel = await this.selectOptimalModel(prompt, options);
try {
const stream = await this.client.chat.completions.create({
model: primaryModel,
messages: [{ role: 'user', content: prompt }],
stream: true,
...options
});
return this.processStream(stream);
} catch (error) {
console.warn(`Streaming with ${primaryModel} failed, falling back to regular completion`);
return await this.completeWithFallback(prompt, options);
}
}
async *processStream(stream) {
try {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
yield content;
}
}
} catch (error) {
console.error('Stream processing error:', error);
throw error;
}
}
}
Together AI Integration
Setup and Model Management
// Together AI integration
import Together from 'together-ai';
class TogetherAIProvider {
constructor() {
this.client = new Together({
apiKey: process.env.TOGETHER_API_KEY,
});
this.availableModels = new Map();
this.loadAvailableModels();
}
async loadAvailableModels() {
try {
const models = await this.client.models.list();
models.forEach(model => {
this.availableModels.set(model.id, {
name: model.display_name,
type: model.type,
context_length: model.context_length,
pricing: model.pricing
});
});
console.log(`Loaded ${this.availableModels.size} Together AI models`);
} catch (error) {
console.error('Failed to load Together AI models:', error);
}
}
async complete(prompt, options = {}) {
const {
model = 'meta-llama/Llama-2-70b-chat-hf',
maxTokens = 1000,
temperature = 0.7,
systemPrompt = null
} = options;
const messages = [];
if (systemPrompt) {
messages.push({ role: 'system', content: systemPrompt });
}
messages.push({ role: 'user', content: prompt });
try {
const response = await this.client.chat.completions.create({
model: model,
messages: messages,
max_tokens: maxTokens,
temperature: temperature,
});
return {
text: response.choices[0].message.content,
usage: response.usage,
cost: this.calculateCost(response.usage, model),
model: model
};
} catch (error) {
console.error('Together AI error:', error);
throw error;
}
}
calculateCost(usage, model) {
const modelInfo = this.availableModels.get(model);
if (!modelInfo || !modelInfo.pricing) return null;
const inputCost = usage.prompt_tokens * modelInfo.pricing.input / 1000000;
const outputCost = usage.completion_tokens * modelInfo.pricing.output / 1000000;
return inputCost + outputCost;
}
getModelsByType(type = 'chat') {
return Array.from(this.availableModels.entries())
.filter(([_, info]) => info.type === type)
.map(([id, info]) => ({ id, ...info }));
}
getOpenSourceModels() {
// Together AI specializes in open source models
const openSourceKeywords = ['llama', 'mistral', 'falcon', 'vicuna', 'alpaca'];
return Array.from(this.availableModels.entries())
.filter(([id, _]) =>
openSourceKeywords.some(keyword =>
id.toLowerCase().includes(keyword)
)
)
.map(([id, info]) => ({ id, ...info }));
}
}
Together AI Fine-tuning Integration
// Fine-tuning capabilities with Together AI
class TogetherAIFineTuning extends TogetherAIProvider {
constructor() {
super();
this.finetunes = new Map();
}
async createFineTune(trainingData, options = {}) {
const {
baseModel = 'meta-llama/Llama-2-7b-chat-hf',
suffix = 'custom-model',
learningRate = 1e-5,
epochs = 3,
batchSize = 1
} = options;
try {
// Upload training data
const file = await this.client.files.upload({
file: trainingData,
purpose: 'fine-tune'
});
// Create fine-tuning job
const fineTune = await this.client.fineTuning.jobs.create({
training_file: file.id,
model: baseModel,
suffix: suffix,
hyperparameters: {
learning_rate_multiplier: learningRate,
n_epochs: epochs,
batch_size: batchSize
}
});
this.finetunes.set(fineTune.id, fineTune);
console.log(`Fine-tuning job created: ${fineTune.id}`);
return fineTune;
} catch (error) {
console.error('Fine-tuning creation failed:', error);
throw error;
}
}
async checkFineTuneStatus(fineTuneId) {
try {
const fineTune = await this.client.fineTuning.jobs.retrieve(fineTuneId);
this.finetunes.set(fineTuneId, fineTune);
return {
id: fineTune.id,
status: fineTune.status,
model: fineTune.fine_tuned_model,
progress: fineTune.progress || 0
};
} catch (error) {
console.error('Failed to check fine-tune status:', error);
throw error;
}
}
async useFineTunedModel(prompt, fineTunedModelId, options = {}) {
return await this.complete(prompt, {
model: fineTunedModelId,
...options
});
}
async listFineTunes() {
try {
const fineTunes = await this.client.fineTuning.jobs.list();
return fineTunes.data;
} catch (error) {
console.error('Failed to list fine-tunes:', error);
throw error;
}
}
}
Custom Provider Solutions
Building a Custom Provider Interface
// Custom provider abstraction layer
class CustomProviderInterface {
constructor() {
this.providers = new Map();
this.middleware = [];
this.metrics = new Map();
}
registerProvider(name, provider) {
if (!provider.complete) {
throw new Error('Provider must implement complete() method');
}
this.providers.set(name, {
instance: provider,
config: provider.config || {},
metrics: {
requests: 0,
errors: 0,
totalCost: 0,
avgLatency: 0
}
});
}
addMiddleware(middleware) {
this.middleware.push(middleware);
}
async complete(prompt, options = {}) {
const { provider = 'default', ...providerOptions } = options;
if (!this.providers.has(provider)) {
throw new Error(`Provider ${provider} not registered`);
}
const providerInfo = this.providers.get(provider);
// Apply middleware
let context = {
prompt,
options: providerOptions,
provider,
startTime: Date.now()
};
for (const mw of this.middleware) {
context = await mw.before(context);
}
try {
// Execute provider
const result = await providerInfo.instance.complete(
context.prompt,
context.options
);
context.result = result;
context.endTime = Date.now();
// Apply post-middleware
for (const mw of this.middleware.reverse()) {
if (mw.after) {
context = await mw.after(context);
}
}
// Update metrics
this.updateMetrics(provider, context);
return context.result;
} catch (error) {
// Update error metrics
providerInfo.metrics.errors++;
// Apply error middleware
for (const mw of this.middleware.reverse()) {
if (mw.error) {
await mw.error(context, error);
}
}
throw error;
}
}
updateMetrics(provider, context) {
const providerInfo = this.providers.get(provider);
const metrics = providerInfo.metrics;
metrics.requests++;
if (context.result.cost) {
metrics.totalCost += context.result.cost;
}
const latency = context.endTime - context.startTime;
metrics.avgLatency = (metrics.avgLatency * (metrics.requests - 1) + latency) / metrics.requests;
}
getMetrics(provider = null) {
if (provider) {
return this.providers.get(provider)?.metrics;
}
const allMetrics = {};
for (const [name, info] of this.providers.entries()) {
allMetrics[name] = info.metrics;
}
return allMetrics;
}
}
Middleware Examples
// Useful middleware implementations
class CachingMiddleware {
constructor(ttl = 3600000) { // 1 hour default
this.cache = new Map();
this.ttl = ttl;
}
async before(context) {
const cacheKey = this.generateCacheKey(context.prompt, context.options);
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.ttl) {
context.result = cached.result;
context.fromCache = true;
throw new CacheHitException(cached.result);
}
return context;
}
async after(context) {
if (!context.fromCache) {
const cacheKey = this.generateCacheKey(context.prompt, context.options);
this.cache.set(cacheKey, {
result: context.result,
timestamp: Date.now()
});
}
return context;
}
generateCacheKey(prompt, options) {
return `${prompt}_${JSON.stringify(options)}`;
}
}
class CostTrackingMiddleware {
constructor() {
this.dailyCosts = new Map();
this.limits = new Map();
}
setDailyLimit(provider, limit) {
this.limits.set(provider, limit);
}
async before(context) {
const today = new Date().toISOString().split('T')[0];
const key = `${context.provider}_${today}`;
const dailyCost = this.dailyCosts.get(key) || 0;
const limit = this.limits.get(context.provider);
if (limit && dailyCost >= limit) {
throw new Error(`Daily cost limit exceeded for ${context.provider}`);
}
return context;
}
async after(context) {
if (context.result.cost) {
const today = new Date().toISOString().split('T')[0];
const key = `${context.provider}_${today}`;
const currentCost = this.dailyCosts.get(key) || 0;
this.dailyCosts.set(key, currentCost + context.result.cost);
}
return context;
}
getDailyCost(provider, date = null) {
const dateStr = date || new Date().toISOString().split('T')[0];
const key = `${provider}_${dateStr}`;
return this.dailyCosts.get(key) || 0;
}
}
class RetryMiddleware {
constructor(maxRetries = 3, baseDelay = 1000) {
this.maxRetries = maxRetries;
this.baseDelay = baseDelay;
}
async error(context, error) {
const retryCount = context.retryCount || 0;
if (retryCount < this.maxRetries && this.isRetryableError(error)) {
context.retryCount = retryCount + 1;
const delay = this.baseDelay * Math.pow(2, retryCount);
await new Promise(resolve => setTimeout(resolve, delay));
// Retry the request
return await this.retry(context);
}
throw error;
}
isRetryableError(error) {
const retryableMessages = [
'rate limit',
'timeout',
'service unavailable',
'internal server error'
];
return retryableMessages.some(msg =>
error.message.toLowerCase().includes(msg)
);
}
async retry(context) {
// This would need to be handled by the main provider interface
throw new RetryException(context);
}
}
Complete Integration Example
Unified Framework Manager
// Complete integration bringing everything together
class UnifiedFrameworkManager {
constructor() {
this.customProvider = new CustomProviderInterface();
this.langchainRouter = new LangChainProviderRouter();
this.openRouter = new RobustOpenRouter();
this.togetherAI = new TogetherAIFineTuning();
this.setupMiddleware();
this.registerProviders();
}
setupMiddleware() {
// Add middleware to custom provider
this.customProvider.addMiddleware(new CachingMiddleware(3600000));
this.customProvider.addMiddleware(new CostTrackingMiddleware());
this.customProvider.addMiddleware(new RetryMiddleware(3, 1000));
}
registerProviders() {
// Register all providers with the custom interface
this.customProvider.registerProvider('langchain', {
complete: async (prompt, options) => {
return await this.langchainRouter.routeToOptimalChain(prompt, options.taskType);
},
config: { type: 'orchestration' }
});
this.customProvider.registerProvider('openrouter', {
complete: async (prompt, options) => {
return await this.openRouter.completeWithOptimalModel(prompt, options);
},
config: { type: 'gateway' }
});
this.customProvider.registerProvider('together', {
complete: async (prompt, options) => {
return await this.togetherAI.complete(prompt, options);
},
config: { type: 'hosting' }
});
}
async intelligentComplete(prompt, requirements = {}) {
const {
taskType = 'general',
budget = 'balanced',
latencyRequirement = 'medium',
qualityRequirement = 'high'
} = requirements;
// Select optimal framework based on requirements
const framework = this.selectFramework(requirements);
console.log(`Selected framework: ${framework}`);
try {
return await this.customProvider.complete(prompt, {
provider: framework,
taskType,
budget,
...requirements
});
} catch (error) {
console.error(`Framework ${framework} failed, trying fallback`);
// Try fallback framework
const fallback = this.getFallbackFramework(framework);
return await this.customProvider.complete(prompt, {
provider: fallback,
taskType,
budget,
...requirements
});
}
}
selectFramework(requirements) {
const { taskType, budget, latencyRequirement } = requirements;
// Decision matrix for framework selection
if (taskType === 'rag' || taskType === 'complex-workflow') {
return 'langchain';
}
if (budget === 'premium' && latencyRequirement === 'low') {
return 'openrouter';
}
if (budget === 'minimal' || taskType === 'open-source') {
return 'together';
}
// Default to OpenRouter for balanced needs
return 'openrouter';
}
getFallbackFramework(primary) {
const fallbacks = {
'langchain': 'openrouter',
'openrouter': 'together',
'together': 'langchain'
};
return fallbacks[primary] || 'openrouter';
}
async getFrameworkMetrics() {
return {
custom: this.customProvider.getMetrics(),
frameworks: {
langchain: 'Available',
openrouter: 'Available',
together: 'Available'
}
};
}
}
// Usage example
async function demonstrateFrameworkIntegration() {
const manager = new UnifiedFrameworkManager();
// Example 1: Complex reasoning task
const reasoningResult = await manager.intelligentComplete(
"Analyze the potential economic impacts of widespread AI adoption",
{
taskType: 'reasoning',
budget: 'premium',
qualityRequirement: 'highest'
}
);
console.log('Reasoning Result:', reasoningResult.text.substring(0, 200) + '...');
// Example 2: Cost-optimized simple task
const simpleResult = await manager.intelligentComplete(
"Summarize this text in one sentence",
{
taskType: 'general',
budget: 'minimal',
latencyRequirement: 'low'
}
);
console.log('Simple Result:', simpleResult.text);
// View metrics
const metrics = await manager.getFrameworkMetrics();
console.log('Framework Metrics:', metrics);
}
Best Practices
Framework Selection Guidelines
- LangChain: Use for complex workflows, RAG systems, and when you need extensive ecosystem integration
- OpenRouter: Use for model experimentation, unified API access, and when you need automatic model routing
- Together AI: Use for open-source models, custom fine-tuning, and cost-optimized inference
- Custom Solutions: Use when you need specific optimizations or have unique requirements
Performance Optimization
- Caching: Implement response caching to reduce API calls
- Batching: Group similar requests when possible
- Model Selection: Use appropriate models for each task type
- Monitoring: Track performance metrics across all frameworks
Cost Management
- Budget Controls: Implement spending limits per framework
- Model Optimization: Use cheaper models for simpler tasks
- Usage Tracking: Monitor usage patterns to identify optimization opportunities
- Fallback Strategies: Implement cost-aware fallback mechanisms
Conclusion
Development framework integration requires understanding each framework’s strengths and implementing intelligent routing between them. By using the patterns and implementations in this guide, you can build a robust system that leverages the best features of multiple frameworks while maintaining cost efficiency and performance.
Start with one framework that matches your primary use case, then gradually integrate others as your needs expand. Always implement proper monitoring and fallback strategies to ensure reliability across your entire AI infrastructure.