maiar-agents
Version:
Multi-provider AI agent library for interacting with various AI models
449 lines (448 loc) • 15.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProvider = createProvider;
const core_1 = require("@maiar-ai/core");
const openai_1 = __importDefault(require("openai"));
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
const generative_ai_1 = require("@google/generative-ai");
const axios_1 = __importDefault(require("axios"));
// Logger setup
const createProviderLogger = (provider) => (0, core_1.createLogger)(`model:${provider}`);
// Provider descriptions
const providerDescriptions = {
openai: "OpenAI API models like GPT-4 and GPT-3.5",
anthropic: "Anthropic API models like Claude 3 Opus and Sonnet",
deepseek: "DeepSeek AI language models",
mistral: "Mistral AI language models",
gemini: "Google's Gemini models",
"agent-ai": "agent.ai intelligent agents",
runway: "Runway generative AI models",
midjourney: "Midjourney image generation",
elsevier: "Elsevier scientific knowledge models",
unity: "Unity AI tools and models",
nvidia: "NVIDIA AI models and frameworks",
harmonai: "Harmonai audio generation models",
audiocraft: "AudioCraft audio generation models",
};
// Client initialization functions
const initializeClient = {
openai: (config) => new openai_1.default({ apiKey: config.apiKey }),
anthropic: (config) => new sdk_1.default({ apiKey: config.apiKey }),
deepseek: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
mistral: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
gemini: (config) => new generative_ai_1.GoogleGenerativeAI(config.apiKey),
"agent-ai": (config) => ({
apiKey: config.apiKey,
model: config.model,
agentId: config.agentId,
}),
runway: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
midjourney: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
elsevier: (config) => ({
apiKey: config.apiKey,
model: config.model,
apiEndpoint: config.apiEndpoint,
}),
unity: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
nvidia: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
harmonai: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
audiocraft: (config) => ({
apiKey: config.apiKey,
model: config.model,
}),
};
// Text generation implementations
const getTextImplementations = {
openai: async (client, model, prompt, config) => {
const completion = await client.chat.completions.create({
model,
messages: [{ role: "user", content: prompt }],
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
stop: config?.stopSequences,
});
const content = completion.choices[0]?.message?.content;
if (!content) {
throw new Error("No content in response");
}
return content;
},
anthropic: async (client, model, prompt, config) => {
const message = await client.messages.create({
model,
messages: [{ role: "user", content: prompt }],
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
stop_sequences: config?.stopSequences,
});
return message.content[0]?.text || "";
},
deepseek: async (client, model, prompt, config) => {
const response = await axios_1.default.post("https://api.deepseek.com/v1/chat/completions", {
model,
messages: [{ role: "user", content: prompt }],
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
stop: config?.stopSequences,
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.choices[0]?.message?.content || "";
},
mistral: async (client, model, prompt, config) => {
const response = await axios_1.default.post("https://api.mistral.ai/v1/chat/completions", {
model,
messages: [{ role: "user", content: prompt }],
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
stop: config?.stopSequences,
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.choices[0]?.message?.content || "";
},
gemini: async (client, model, prompt, config) => {
const geminiModel = client.getGenerativeModel({ model });
const result = await geminiModel.generateContent({
contents: [{ role: "user", parts: [{ text: prompt }] }],
generationConfig: {
temperature: config?.temperature ?? 0.7,
maxOutputTokens: config?.maxTokens,
stopSequences: config?.stopSequences,
},
});
return result.response.text();
},
"agent-ai": async (client, model, prompt, config) => {
const response = await axios_1.default.post(`https://api.agent.ai/v1/agents/${client.agentId}/run`, {
input: prompt,
config: {
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.output || "";
},
// Additional implementations for other providers
runway: async (client, model, prompt, config) => {
// Implementation for Runway
const response = await axios_1.default.post("https://api.runway.ml/v1/generate", {
model,
prompt,
parameters: {
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.output || "";
},
midjourney: async (client, model, prompt, config) => {
// Implementation for Midjourney
const response = await axios_1.default.post("https://api.midjourney.com/v1/imaginations", {
prompt,
model,
config: {
// Midjourney specific parameters
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.image_url || "";
},
elsevier: async (client, model, prompt, config) => {
// Implementation for Elsevier
const response = await axios_1.default.post(client.apiEndpoint, {
query: prompt,
model,
parameters: {
temperature: config?.temperature ?? 0.7,
},
}, {
headers: {
"Content-Type": "application/json",
"X-ELS-APIKey": client.apiKey,
},
});
return response.data.result || "";
},
unity: async (client, model, prompt, config) => {
// Implementation for Unity
const response = await axios_1.default.post("https://api.unity.ai/v1/generate", {
model,
prompt,
parameters: {
temperature: config?.temperature ?? 0.7,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.result || "";
},
nvidia: async (client, model, prompt, config) => {
// Implementation for NVIDIA
const response = await axios_1.default.post("https://api.nvidia.com/v1/generate", {
model,
input: prompt,
parameters: {
temperature: config?.temperature ?? 0.7,
max_tokens: config?.maxTokens,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.output || "";
},
harmonai: async (client, model, prompt, config) => {
// Implementation for Harmonai
const response = await axios_1.default.post("https://api.harmonai.com/v1/generate", {
model,
prompt,
parameters: {
temperature: config?.temperature ?? 0.7,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.audio_url || "";
},
audiocraft: async (client, model, prompt, config) => {
// Implementation for AudioCraft
const response = await axios_1.default.post("https://api.audiocraft.com/v1/generate", {
model,
prompt,
parameters: {
temperature: config?.temperature ?? 0.7,
},
}, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${client.apiKey}`,
},
});
return response.data.audio_url || "";
},
};
// Health check implementations
const healthCheckImplementations = {
openai: async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
anthropic: async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
// Similar implementations for other providers, potentially with provider-specific checks
deepseek: async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
mistral: async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
gemini: async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
"agent-ai": async (client, model, getText) => {
const resp = await getText("are you alive? Please respond 'yes' or 'no' only.", {
temperature: 0.7,
maxTokens: 5,
});
return resp.toLowerCase().includes("yes");
},
runway: async (client, model, getText) => {
// For image/non-text models, we might check differently
try {
await axios_1.default.get("https://api.runway.ml/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
midjourney: async (client, model, getText) => {
try {
await axios_1.default.get("https://api.midjourney.com/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
elsevier: async (client, model, getText) => {
try {
await axios_1.default.get(client.apiEndpoint + "/status", {
headers: { "X-ELS-APIKey": client.apiKey },
});
return true;
}
catch (error) {
return false;
}
},
unity: async (client, model, getText) => {
try {
await axios_1.default.get("https://api.unity.ai/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
nvidia: async (client, model, getText) => {
try {
await axios_1.default.get("https://api.nvidia.com/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
harmonai: async (client, model, getText) => {
try {
await axios_1.default.get("https://api.harmonai.com/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
audiocraft: async (client, model, getText) => {
try {
await axios_1.default.get("https://api.audiocraft.com/v1/status", {
headers: { Authorization: `Bearer ${client.apiKey}` },
});
return true;
}
catch (error) {
return false;
}
},
};
// Create provider function
function createProvider(providerConfig) {
const { type, config } = providerConfig;
const log = createProviderLogger(type);
// Type assertion to ensure TypeScript understands we're using the correct config type
const client = initializeClient[type](config);
const model = config.model;
// Create getText function for the provider
const getText = async (prompt, reqConfig) => {
try {
return await getTextImplementations[type](client, model, prompt, reqConfig);
}
catch (error) {
log.error(`Error getting text from ${type}:`, error);
throw error;
}
};
// Create checkHealth function for the provider
const checkHealth = async () => {
try {
const isHealthy = await healthCheckImplementations[type](client, model, getText);
if (isHealthy) {
log.info({ msg: `Model ${type} health check passed` });
}
else {
throw new Error(`Health check failed for ${type}`);
}
}
catch (error) {
log.error({ msg: `Model ${type} health check failed`, error });
throw new Error(`Failed to initialize Model ${type}: ${error instanceof Error ? error.message : String(error)}`);
}
};
// Initialize function
const init = async () => {
// Most providers don't need initialization
log.info(`Initialized ${type} provider with model ${model}`);
};
// Return the provider object
return {
id: type,
name: type.charAt(0).toUpperCase() + type.slice(1),
description: providerDescriptions[type],
getText,
init,
checkHealth,
};
}