@xenterprises/fastify-x-ai
v1.1.2
Published
Fastify plugin for Vercel AI SDK - unified AI provider access with text generation, streaming, embeddings, and structured output
Readme
xAI
A Fastify plugin for the Vercel AI SDK providing unified access to AI providers (OpenAI, Anthropic, Google) with text generation, streaming, embeddings, and structured output.
Features
- Unified Provider Access - Single API for OpenAI, Anthropic, Google, and more
- Text Generation - Generate text with
generate()andcomplete() - Streaming - Real-time streaming with
stream() - Chat - Conversation handling with
chat() - Embeddings - Create embeddings for semantic search and RAG
- Structured Output - Generate typed objects with schemas
- Tool Calling - Function/tool execution support
Installation
npm install xai ai
# Install provider SDKs as needed
npm install @ai-sdk/openai # For OpenAI/GPT models
npm install @ai-sdk/anthropic # For Anthropic/Claude models
npm install @ai-sdk/google # For Google/Gemini modelsQuick Start
import Fastify from "fastify";
import xAI from "xai";
const fastify = Fastify();
await fastify.register(xAI, {
defaultProvider: "openai",
providers: {
openai: { apiKey: process.env.OPENAI_API_KEY },
},
});
// Simple text completion
const text = await fastify.xai.complete("Write a haiku about coding");
console.log(text);
// Chat with conversation history
const result = await fastify.xai.chat({
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What is the capital of France?" },
],
});
console.log(result.text);Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| active | boolean | true | Enable/disable the plugin |
| defaultProvider | string | "openai" | Default AI provider |
| defaultModel | string | Provider default | Default model to use |
| defaultMaxTokens | number | 4096 | Default max tokens |
| defaultTemperature | number | 0.7 | Default temperature (0-1) |
| providers | object | {} | Provider configurations |
Provider Configuration
await fastify.register(xAI, {
providers: {
openai: {
apiKey: process.env.OPENAI_API_KEY,
baseURL: "https://custom-endpoint.com", // Optional
},
anthropic: {
apiKey: process.env.ANTHROPIC_API_KEY,
},
google: {
apiKey: process.env.GOOGLE_API_KEY,
},
},
});Environment Variables
You can also configure providers via environment variables:
OPENAI_API_KEYANTHROPIC_API_KEYGOOGLE_API_KEY
API Reference
Decorators
| Method | Description |
|--------|-------------|
| fastify.xai.generate(params) | Generate text with full control |
| fastify.xai.stream(params) | Stream text generation |
| fastify.xai.chat(params) | Chat with conversation history |
| fastify.xai.complete(prompt, options) | Simple text completion |
| fastify.xai.createEmbedding(params) | Create embeddings |
| fastify.xai.similarity(a, b) | Calculate cosine similarity |
| fastify.xai.generateStructured(params) | Generate structured output |
| fastify.xai.getModel(provider, model) | Get model instance |
| fastify.xai.raw | Raw AI SDK functions |
generate(params)
Generate text with full control over parameters.
const result = await fastify.xai.generate({
prompt: "Explain quantum computing",
// Or use messages for chat-style
messages: [
{ role: "user", content: "Hello!" },
],
system: "You are a physics professor.",
provider: "openai", // Optional: override default
model: "gpt-4o", // Optional: specific model
maxTokens: 1000, // Optional: max tokens
temperature: 0.7, // Optional: creativity (0-1)
tools: { ... }, // Optional: tool definitions
maxSteps: 5, // Optional: max tool execution steps
});
console.log(result.text);
console.log(result.usage); // Token usage
console.log(result.toolCalls); // Tool calls madestream(params)
Stream text generation for real-time applications.
const result = await fastify.xai.stream({
prompt: "Tell me a long story",
onChunk: ({ chunk }) => {
// Handle each chunk
console.log(chunk);
},
onFinish: ({ text, usage }) => {
console.log("Done:", text);
},
onError: ({ error }) => {
console.error(error);
},
});
// Iterate over the stream
for await (const text of result.textStream) {
process.stdout.write(text);
}chat(params)
Handle conversations with message history.
// Non-streaming chat
const result = await fastify.xai.chat({
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What is 2+2?" },
{ role: "assistant", content: "2+2 equals 4." },
{ role: "user", content: "What about 3+3?" },
],
});
// Streaming chat
const streamResult = await fastify.xai.chat({
messages: [...],
stream: true,
});complete(prompt, options)
Simple text completion helper.
const text = await fastify.xai.complete("Write a poem about the sea");
// With options
const text = await fastify.xai.complete("Summarize this article", {
provider: "anthropic",
model: "claude-sonnet-4-20250514",
maxTokens: 500,
});createEmbedding(params)
Create embeddings for semantic search and RAG.
// Single embedding
const { embedding } = await fastify.xai.createEmbedding({
text: "Hello world",
});
// Multiple embeddings
const { embeddings } = await fastify.xai.createEmbedding({
texts: ["Hello", "World", "Foo", "Bar"],
});
// Calculate similarity
const similarity = fastify.xai.similarity(embedding1, embedding2);
console.log(`Similarity: ${similarity}`); // -1 to 1generateStructured(params)
Generate structured output with a Zod schema.
import { z } from "zod";
const result = await fastify.xai.generateStructured({
prompt: "Generate a recipe for chocolate cake",
schema: z.object({
name: z.string(),
ingredients: z.array(z.object({
item: z.string(),
amount: z.string(),
})),
instructions: z.array(z.string()),
prepTime: z.number(),
cookTime: z.number(),
}),
schemaName: "Recipe",
schemaDescription: "A cooking recipe",
});
console.log(result.output); // Typed recipe objectTool Calling
Use tools/functions with AI models.
const result = await fastify.xai.generate({
prompt: "What's the weather in San Francisco?",
tools: {
getWeather: {
description: "Get weather for a location",
parameters: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
// Call weather API
return { temperature: 72, condition: "sunny" };
},
},
},
maxSteps: 3, // Allow up to 3 tool execution steps
});
console.log(result.text);
console.log(result.toolCalls);
console.log(result.toolResults);Raw SDK Access
Access the underlying Vercel AI SDK functions directly.
const { generateText, streamText, embed } = fastify.xai.raw;
// Use raw functions for advanced scenarios
const result = await generateText({
model: fastify.xai.getModel("openai", "gpt-4o"),
prompt: "Hello",
});Default Models
| Provider | Default Model |
|----------|---------------|
| OpenAI | gpt-4o |
| Anthropic | claude-sonnet-4-20250514 |
| Google | gemini-2.0-flash |
Usage in Routes
fastify.post("/chat", async (request, reply) => {
const { messages } = request.body;
const result = await fastify.xai.chat({
messages,
system: "You are a helpful assistant.",
});
return { response: result.text };
});
fastify.post("/stream", async (request, reply) => {
const { prompt } = request.body;
const result = await fastify.xai.stream({ prompt });
reply.header("Content-Type", "text/event-stream");
reply.header("Cache-Control", "no-cache");
for await (const chunk of result.textStream) {
reply.raw.write(`data: ${JSON.stringify({ text: chunk })}\n\n`);
}
reply.raw.end();
});
fastify.post("/search", async (request, reply) => {
const { query, documents } = request.body;
// Create embeddings
const { embedding: queryEmbed } = await fastify.xai.createEmbedding({
text: query,
});
const { embeddings: docEmbeds } = await fastify.xai.createEmbedding({
texts: documents,
});
// Find most similar
const similarities = docEmbeds.map((embed, i) => ({
document: documents[i],
score: fastify.xai.similarity(queryEmbed, embed),
}));
similarities.sort((a, b) => b.score - a.score);
return { results: similarities.slice(0, 5) };
});Testing
npm testResources
License
MIT
