A lightweight library for making AI API calls with streaming support.
npm install call-ai
# or
yarn add call-ai
# or
pnpm add call-ai
import { callAI } from 'call-ai';
// Basic usage with string prompt (non-streaming by default)
const response = await callAI('Explain quantum computing in simple terms', {
apiKey: 'your-api-key',
model: 'gpt-4'
});
// The response is the complete text
console.log(response);
// With streaming enabled (returns an AsyncGenerator)
const generator = callAI('Tell me a story', {
apiKey: 'your-api-key',
model: 'gpt-4',
stream: true
});
// Process streaming updates
for await (const chunk of generator) {
console.log(chunk); // Streaming updates as they arrive
}
// Using message array for more control
const messages = [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain quantum computing in simple terms' }
];
const response = await callAI(messages, {
apiKey: 'your-api-key',
model: 'gpt-4'
});
console.log(response);
// Using schema for structured output
const schema = {
name: "exercise_summary",
properties: {
title: { type: 'string' },
summary: { type: 'string' },
points: { type: 'array', items: { type: 'string' } }
},
required: ['title', 'summary']
};
const response = await callAI('Summarize the benefits of exercise', {
apiKey: 'your-api-key',
schema: schema
});
const structuredOutput = JSON.parse(response);
console.log(structuredOutput.title);
// Streaming with schema for OpenRouter structured JSON output
const schema = {
properties: {
title: { type: 'string' },
items: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
description: { type: 'string' }
}
}
}
}
};
const generator = callAI('Create a list of sci-fi books', {
apiKey: 'your-api-key',
stream: true,
schema: schema
});
for await (const chunk of generator) {
console.log(chunk); // Shows the partial JSON as it's being generated
}
- π Streaming responses via AsyncGenerator when
stream: true
- π§© Structured JSON outputs with schema validation
- π Full compatibility with OpenRouter's JSON schema format for structured outputs
- π Support for message arrays with system, user, and assistant roles
- π§ TypeScript support with full type definitions
- β Works in Node.js and browser environments
Call-AI supports all models available through OpenRouter, including:
- OpenAI models (GPT-4, GPT-3.5, etc.)
- Anthropic Claude
- Gemini
- Llama 3
- Mistral
- And many more
Different LLMs have different strengths when working with structured data. Based on our testing, here's a guide to help you choose the right model for your schema needs:
Model Family | Grade | Simple Flat Schema | Complex Flat Schema | Nested Schema | Best For |
---|---|---|---|---|---|
OpenAI | A | β Excellent | β Excellent | β Excellent | Most reliable for all schema types |
Gemini | A | β Excellent | β Excellent | β Good | Good all-around performance, especially with flat schemas |
Claude | B | β Excellent | β Good | Simple schemas, robust handling of complex prompts | |
Llama 3 | C | β Good | β Good | β Poor | Simpler flat schemas, may struggle with nested structures |
Deepseek | C | β Good | β Good | β Poor | Basic flat schemas only |
-
Flat schemas perform better across all models. If you need maximum compatibility, avoid deeply nested structures.
-
Field names matter. Some models have preferences for certain property naming patterns:
- Use simple, common naming patterns like
name
,type
,items
,price
- Avoid deeply nested object hierarchies (more than 2 levels deep)
- Keep array items simple (strings or flat objects)
- Use simple, common naming patterns like
-
Model-specific considerations:
- OpenAI models: Best overall schema adherence and handle complex nesting well
- Claude models: Great for simple schemas, occasional JSON formatting issues with complex structures
- Gemini models: Good general performance, handles array properties well
- Llama/Mistral/Deepseek: Strong with flat schemas, but often ignore nesting structure and provide their own organization
-
For mission-critical applications requiring schema adherence, use OpenAI models or implement fallback mechanisms.
You can provide your API key in three ways:
- Directly in the options:
const response = await callAI('Hello', { apiKey: 'your-api-key' });
- Set globally in the browser:
window.CALLAI_API_KEY = 'your-api-key';
const response = await callAI('Hello');
- Use environment variables in Node.js (with a custom implementation):
// Example of environment variable integration
import { callAI } from 'call-ai';
const apiKey = process.env.OPENAI_API_KEY || process.env.OPENROUTER_API_KEY;
const response = await callAI('Hello', { apiKey });
// Main function
function callAI(
prompt: string | Message[],
options?: CallAIOptions
): Promise<string> | AsyncGenerator<string, string, unknown>
// Types
type Message = {
role: 'user' | 'system' | 'assistant';
content: string;
};
interface Schema {
/**
* Optional schema name that will be sent to the model provider if supported
*/
name?: string;
properties: Record<string, any>;
required?: string[];
additionalProperties?: boolean;
}
interface CallAIOptions {
apiKey?: string;
model?: string;
endpoint?: string;
stream?: boolean;
schema?: Schema | null;
[key: string]: any;
}
apiKey
: Your API key (can also be set via window.CALLAI_API_KEY)model
: Model identifier (default: 'openrouter/auto')endpoint
: API endpoint (default: 'https://openrouter.ai/api/v1/chat/completions')stream
: Enable streaming responses (default: false)schema
: Optional JSON schema for structured output- Any other options are passed directly to the API (temperature, max_tokens, etc.)
MIT or Apache-2.0, at your option
- Fork the repository
- Make your changes
- Add tests for new functionality
- Run tests:
npm test
- Run type checking:
npm run typecheck
- Create a pull request
The project includes integration tests that make real API calls to verify functionality with actual LLM models:
- Copy
.env.example
to.env
and add your OpenRouter API key - Run integration tests:
npm run test:integration
Note: Integration tests are excluded from the normal test suite to avoid making API calls during CI/CD. They require a valid API key to execute and will be skipped if no key is provided.
This library uses GitHub Actions to automate the release process:
- Update the version in
package.json
(follow semver) - Update
CHANGELOG.md
with details of changes - Commit changes:
git commit -am "Release vX.Y.Z"
- Create a git tag:
git tag -a vX.Y.Z -m "Version X.Y.Z"
- Push changes and tag:
git push origin main vX.Y.Z
The GitHub workflow in .github/workflows/publish.yml
will:
- Automatically trigger when a new tag is pushed
- Run tests and type checking
- Verify the tag signature
- Publish the package to npm
When making significant changes, remember to:
- Document breaking changes in the changelog
- Update documentation to reflect API changes
- Update TypeScript types