一键导入
mistral-proxy
Mistral AI API expert - access cutting-edge open-source models with European data residency and enterprise features.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Mistral AI API expert - access cutting-edge open-source models with European data residency and enterprise features.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
WCAG 2.2 accessibility audit and remediation guidance for frontend code, UI reviews, keyboard/focus testing, ARIA usage, contrast, forms, and regression checks.
Local-first personal AI agent gateway architecture for Windows with messaging integrations, tool execution, and real-time streaming.
Anthropic Claude API expert - master Messages API requests, responses, streaming, tool use, prompt caching, and current Claude 4-family model practices.
REST and HTTP API design with OpenAPI 3.1, resource modeling, versioning, pagination, idempotency, errors, validation, auth boundaries, and production compatibility.
Expert in converting between AI provider APIs - Anthropic, Gemini, OpenRouter, Groq, Mistral, DeepSeek, and NVIDIA NIM.
Comprehensive authentication system for AI agent gateway with JWT tokens, session management, and multi-factor authentication.
| name | mistral-proxy |
| type | skill |
| version | 1.0.0 |
| description | Mistral AI API expert - access cutting-edge open-source models with European data residency and enterprise features. |
| author | skillregistry |
| license | MIT |
| agents | ["cursor","claude-code","copilot","gemini-cli","codex"] |
| categories | ["backend","ai-ml","architecture"] |
| tags | ["ai","api","mistral","mistral-ai","open-source","llm","europe","proxy"] |
Master the Mistral AI API for accessing state-of-the-art open-source large language models. Mistral offers cutting-edge models with European data residency, fine-tuning capabilities, and enterprise-grade features.
import fetch from 'node-fetch';
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model: 'mistral-large-latest',
messages: [{ role: 'user', content: 'Hello!' }]
})
});
const data = await response.json();
console.log(data.choices[0].message.content);
curl https://api.mistral.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MISTRAL_KEY" \
-d '{
"model": "mistral-large-latest",
"messages": [{"role": "user", "content": "Hello!"}]
}'
| Model | Context Window | Use Case | Price (Input) | Price (Output) | Notes |
|---|---|---|---|---|---|
| mistral-large-latest | 128,000+ | Most capable hosted chat model alias | Check current pricing | Check current pricing | Use the docs/pricing API for exact current rates |
| mistral-small-latest | 32,000+ | Cost-effective chat model alias | Check current pricing | Check current pricing | Good default for routine tasks |
| codestral-latest | Model-dependent | Code generation and completion | Check current pricing | Check current pricing | Use for coding-specific workloads |
| mistral-small | 32,000 | Fast, cost-effective | €0.000002/tok | €0.000006/tok | Good balance |
| mistral-tiny | 8,000 | Fastest, cheapest | €0.00000025/tok | €0.00000025/tok | Quick tasks |
| mistral-small-latest | 32,000 | Sparsely-activated | €0.00000055/tok | €0.00000055/tok | Mixture of Experts |
| mistral-small-latest | 64,000 | High capacity | €0.0000007/tok | €0.0000007/tok | Scaling MoE |
| codestral-latest | 32,000 | Code generation | €0.0000007/tok | €0.0000021/tok | Coding specialist |
mistral-embedding - 1024 dimensionshttps://api.mistral.ai/v1/chat/completionshttps://api.mistral.ai/v1/embeddingshttps://api.mistral.ai/v1/modelshttps://api.mistral.ai/v1/models/{model_id}{
"model": "mistral-large-latest",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
"max_tokens": 1024,
"temperature": 0.7,
"top_p": 0.9,
"stream": false
}
| Parameter | Type | Default | Description |
|---|---|---|---|
| model | string | required | Model ID |
| messages | array | required | Message history |
| max_tokens | number | inf | Max output tokens (max: 32768 for most models) |
| temperature | number | 1.0 | Randomness (0-2) |
| top_p | number | 1.0 | Nucleus sampling |
| top_k | number | null | Top-k sampling |
| stream | boolean | false | Enable streaming |
| stop | string/array | null | Stop sequences |
| presence_penalty | number | 0 | Repetition penalty |
| frequency_penalty | number | 0 | Frequency penalty |
| user | string | null | User identifier |
| safe_mode | boolean | false | Enable safe mode (content filtering) |
| random_seed | number | null | Random seed for reproducibility |
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1717000000,
"model": "mistral-large-latest",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 25,
"completion_tokens": 10,
"total_tokens": 35
}
}
{
"id": "chatcmpl-123",
"object": "chat.completion.chunk",
"created": 1717000000,
"model": "mistral-large-latest",
"choices": [
{
"index": 0,
"delta": {"content": "Hello"},
"finish_reason": null
}
]
}
stop - Normal completionlength - Hit max tokensmodel_length - Context window exceedederror - Error occurredMistral supports function calling with tools:
{
"model": "mistral-large-latest",
"messages": [
{"role": "user", "content": "What's the weather in Paris?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
}
},
"required": ["location"]
}
}
}
]
}
Tool Call Response:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "I'll check the weather for you.",
"tool_calls": [
{
"id": "tool_123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": '{"location": "Paris"}'
}
}
]
}
}
]
}
Enable content filtering:
{
"model": "mistral-large-latest",
"messages": [...],
"safe_mode": true
}
Ensure reproducible outputs:
{
"model": "mistral-large-latest",
"messages": [...],
"random_seed": 42
}
All Mistral data is processed and stored in Europe (France), ensuring GDPR compliance and data sovereignty.
const response = await fetch('https://api.mistral.ai/v1/embeddings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model: 'mistral-embedding',
input: 'Your text here'
})
});
const data = await response.json();
console.log(data.data[0].embedding); // 1024-dimensional vector
{
"model": "mistral-embedding",
"input": [
"First text",
"Second text",
"Third text"
]
}
{
"object": "list",
"data": [
{
"object": "embedding",
"embedding": [0.1, 0.2, ..., 0.99],
"index": 0
}
],
"model": "mistral-embedding",
"usage": {
"prompt_tokens": 10,
"total_tokens": 10
}
}
import express from 'express';
import fetch from 'node-fetch';
const app = express();
app.use(express.json());
const MISTRAL_KEY = process.env.MISTRAL_KEY;
const MISTRAL_URL = 'https://api.mistral.ai/v1';
app.post('/v1/chat/completions', async (req, res) => {
try {
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(req.body)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Mistral error');
}
const data = await response.json();
res.json(data);
} catch (error: any) {
res.status(error.statusCode || 500).json({ error: error.message });
}
});
app.post('/v1/embeddings', async (req, res) => {
try {
const response = await fetch(`${MISTRAL_URL}/embeddings`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(req.body)
});
const data = await response.json();
res.json(data);
} catch (error: any) {
res.status(error.statusCode || 500).json({ error: error.message });
}
});
app.listen(3000);
app.post('/stream', async (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify({
...req.body,
stream: true
})
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader!.read();
if (done) break;
const chunk = decoder.decode(value);
if (chunk.includes('[DONE]')) break;
res.write(`data: ${chunk}\n\n`);
}
res.write('data: [DONE]\n\n');
res.end();
});
const MODEL_ALIASES: Record<string, string> = {
'large': 'mistral-large-latest',
'small': 'mistral-small',
'tiny': 'mistral-tiny',
'small': 'mistral-small-latest',
'code': 'codestral-latest',
'codestral': 'codestral-latest',
'embedding': 'mistral-embedding'
};
app.post('/mistral/:model/chat', async (req, res) => {
const { model } = req.params;
const actualModel = MODEL_ALIASES[model] || model;
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify({
model: actualModel,
messages: req.body.messages,
max_tokens: req.body.max_tokens || 4096,
temperature: req.body.temperature || 0.7
})
});
const data = await response.json();
res.json({ ...data, model: actualModel });
});
{
"object": "error",
"message": "Invalid request format",
"type": "BadRequestError",
"param": null,
"code": null
}
{
"object": "error",
"message": "Invalid or expired API key",
"type": "AuthenticationError"
}
{
"object": "error",
"message": "Access denied or quota exceeded",
"type": "PermissionError"
}
{
"object": "error",
"message": "Model not found",
"type": "NotFoundError"
}
{
"object": "error",
"message": "Rate limit exceeded",
"type": "RateLimitError"
}
{
"object": "error",
"message": "Internal server error",
"type": "InternalServerError"
}
function selectModel(task: string, budget: 'low' | 'medium' | 'high'): string {
const modelMap: Record<string, Record<'low' | 'medium' | 'high', string>> = {
chat: {
low: 'mistral-tiny',
medium: 'mistral-small',
high: 'mistral-large-latest'
},
coding: {
low: 'mistral-small',
medium: 'codestral-latest',
high: 'mistral-large-latest'
},
long_context: {
low: 'mistral-small-latest',
medium: 'mistral-small-latest',
high: 'mistral-large-latest'
},
embedding: {
low: 'mistral-embedding',
medium: 'mistral-embedding',
high: 'mistral-embedding'
}
};
return modelMap[task]?.[budget] || 'mistral-small';
}
async function withRetry(request: any, maxRetries = 3) {
let attempt = 0;
while (true) {
try {
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(request)
});
if (response.ok) {
return await response.json();
}
if (response.status !== 429 || attempt >= maxRetries) {
throw new Error(`Mistral error: ${response.status}`);
}
const retryAfter = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, retryAfter));
attempt++;
} catch (error) {
if (attempt >= maxRetries) {
throw error;
}
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
attempt++;
}
}
}
function createToolCall(name: string, description: string, parameters: any) {
return {
type: 'function',
function: {
name,
description,
parameters: {
type: 'object',
properties: parameters.properties,
required: parameters.required || []
}
}
};
}
function extractToolCalls(response: any) {
return response.choices[0]?.message?.tool_calls || [];
}
async function safeGenerate(prompt: string, model: string) {
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
safe_mode: true
})
});
const data = await response.json();
// Check if content was filtered
if (data.choices[0]?.message?.content?.includes('[SAFE_MODE]')) {
throw new Error('Content was filtered by safe mode');
}
return data.choices[0].message.content;
}
// Batch embeddings for efficiency
async function batchEmbed(texts: string[], model: string = 'mistral-embedding') {
const BATCH_SIZE = 100; // Mistral's batch limit
const batches = [];
for (let i = 0; i < texts.length; i += BATCH_SIZE) {
batches.push(texts.slice(i, i + BATCH_SIZE));
}
const results = [];
for (const batch of batches) {
const response = await fetch(`${MISTRAL_URL}/embeddings`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify({
model,
input: batch
})
});
const data = await response.json();
results.push(...data.data);
}
return results;
}
import { Agent } from 'https';
const httpsAgent = new Agent({
keepAlive: true,
keepAliveMsecs: 60000,
maxSockets: 100,
maxFreeSockets: 50
});
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
agent: httpsAgent,
method: 'POST',
// ...
});
import NodeCache from 'node-cache';
const cache = new NodeCache({ stdTTL: 300 }); // 5 minute cache
async function cachedGenerate(request: any) {
const cacheKey = JSON.stringify(request);
const cached = cache.get(cacheKey);
if (cached) {
return cached;
}
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(request)
});
const data = await response.json();
cache.set(cacheKey, data);
return data;
}
class MistralBatcher {
private queue: Array<{ request: any; resolve: Function; reject: Function }> = [];
private processing = false;
add(request: any) {
return new Promise((resolve, reject) => {
this.queue.push({ request, resolve, reject });
this.process();
});
}
async process() {
if (this.processing || this.queue.length < 3) return;
this.processing = true;
const batch = this.queue.splice(0, 3);
try {
const responses = await Promise.all(
batch.map(({ request }) =>
fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(request)
}).then(r => r.json())
)
);
batch.forEach((item, i) => item.resolve(responses[i]));
} catch (error) {
batch.forEach(item => item.reject(error));
} finally {
this.processing = false;
}
}
}
import { describe, it, expect, vi } from 'vitest';
describe('Mistral Proxy', () => {
it('generates content', async () => {
global.fetch = vi.fn(() => Promise.resolve({
ok: true,
json: () => Promise.resolve({
id: 'chatcmpl-123',
object: 'chat.completion',
created: 1717000000,
model: 'mistral-large-latest',
choices: [{
index: 0,
message: { role: 'assistant', content: 'Hello!' },
finish_reason: 'stop'
}],
usage: { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 }
})
}));
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer test-key'
},
body: JSON.stringify({
model: 'mistral-large-latest',
messages: [{ role: 'user', content: 'Hi' }]
})
});
const data = await response.json();
expect(data.choices[0].message.content).toBe('Hello!');
});
it('generates embeddings', async () => {
global.fetch = vi.fn(() => Promise.resolve({
ok: true,
json: () => Promise.resolve({
object: 'list',
data: [{
object: 'embedding',
embedding: [0.1, 0.2, 0.3],
index: 0
}],
model: 'mistral-embedding',
usage: { prompt_tokens: 5, total_tokens: 5 }
})
}));
const response = await fetch(`${MISTRAL_URL}/embeddings`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer test-key'
},
body: JSON.stringify({
model: 'mistral-embedding',
input: 'Test text'
})
});
const data = await response.json();
expect(data.data[0].embedding).toHaveLength(1024);
});
});
import { createProxy } from './proxy';
describe('Mistral Proxy Integration', () => {
it('proxies chat requests', async () => {
const proxy = createProxy({ port: 3001 });
const response = await fetch('http://localhost:3001/v1/chat/completions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'mistral-large-latest',
messages: [{ role: 'user', content: 'Test' }]
})
});
expect(response.status).toBe(200);
const data = await response.json();
expect(data.model).toBe('mistral-large-latest');
});
it('proxies embedding requests', async () => {
const proxy = createProxy({ port: 3001 });
const response = await fetch('http://localhost:3001/v1/embeddings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'mistral-embedding',
input: 'Test text'
})
});
expect(response.status).toBe(200);
const data = await response.json();
expect(data.data[0].embedding).toBeDefined();
});
});
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
COPY .env ./
EXPOSE 3000
CMD ["node", "dist/index.js"]
version: '3.8'
services:
mistral-proxy:
build: .
ports:
- "3000:3000"
environment:
- MISTRAL_KEY=${MISTRAL_KEY}
- PRIMARY_MODEL=mistral-large-latest
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
# Required
MISTRAL_KEY=...
# Optional
PRIMARY_MODEL=mistral-large-latest
MISTRAL_URL=https://api.mistral.ai/v1
PORT=3000
LOG_LEVEL=info
MAX_TOKENS=4096
TIMEOUT=30000
SAFE_MODE=false
RANDOM_SEED=null
import { createHistogram, createCounter, createGauge } from 'prom-client';
const requestLatency = createHistogram({
name: 'mistral_request_latency_seconds',
help: 'Request latency in seconds',
labelNames: ['model', 'endpoint'],
buckets: [0.1, 0.5, 1, 2, 5, 10]
});
const tokenUsage = createCounter({
name: 'mistral_tokens_total',
help: 'Total tokens used',
labelNames: ['model', 'type', 'endpoint']
});
const activeRequests = createGauge({
name: 'mistral_active_requests',
help: 'Number of active requests',
labelNames: ['model']
});
app.use((req, res, next) => {
const start = process.hrtime.bigint();
const model = req.body.model || 'unknown';
const endpoint = req.path.split('/')[2] || 'unknown';
activeRequests.labels(model).inc();
res.on('finish', () => {
const latency = Number(process.hrtime.bigint() - start) / 1e9;
requestLatency.labels(model, endpoint).observe(latency);
activeRequests.labels(model).dec();
});
next();
});
app.post('/v1/chat/completions', async (req, res) => {
const response = await fetch(`${MISTRAL_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(req.body)
});
const data = await response.json();
if (data.usage) {
tokenUsage.labels(req.body.model, 'input', 'chat').inc(data.usage.prompt_tokens);
tokenUsage.labels(req.body.model, 'output', 'chat').inc(data.usage.completion_tokens);
}
res.json(data);
});
app.post('/v1/embeddings', async (req, res) => {
const response = await fetch(`${MISTRAL_URL}/embeddings`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_KEY}`
},
body: JSON.stringify(req.body)
});
const data = await response.json();
if (data.usage) {
tokenUsage.labels(req.body.model, 'input', 'embedding').inc(data.usage.prompt_tokens);
}
res.json(data);
});
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'mistral-proxy.log' })
]
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
logger.info({
timestamp: new Date().toISOString(),
method: req.method,
path: req.path,
model: req.body.model,
endpoint: req.path.split('/')[2],
status: res.statusCode,
latencyMs: Date.now() - start,
ip: req.ip
});
});
next();
});
Invalid API Key
Model Not Available
/v1/modelsRate Limit Exceeded
Context Window Exceeded
Safe Mode Blocked
Function Call Format Error
# Enable verbose logging
DEBUG=mistral:* node index.js
# Or log full requests
import fetch from 'node-fetch';
const originalFetch = global.fetch;
global.fetch = async (url: string, options: any) => {
if (url.includes('mistral.ai')) {
console.log('Mistral Request:', url, options);
}
const response = await originalFetch(url, options);
const cloned = response.clone();
const body = await cloned.json();
if (url.includes('mistral.ai')) {
console.log('Mistral Response:', body);
}
return response;
};
| Feature | Mistral | OpenAI | Anthropic | Groq | DeepSeek |
|---|---|---|---|---|---|
| Models | Open-source & custom | Proprietary | Proprietary | Proprietary | Proprietary |
| Context Window | 8K-128K | 16K-128K | 200K | 8K-123K | 32K |
| Price (Input) | €0.00000025-0.000008 | $0.00001-0.00003 | $0.000003-0.000015 | $0.0000008 | $0.0000014-0.0000028 |
| Price (Output) | €0.00000025-0.000024 | $0.00003-0.00006 | $0.000015 | $0.0000008 | $0.0000014-0.0000028 |
| OpenAI Compatible | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Function Calling | ✅ Yes | ✅ Yes | ✅ Beta | ❌ No | ❌ No |
| Embeddings | ✅ Yes | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Multi-modal | ❌ No | ✅ Yes | ✅ Claude 3 | ❌ No | ❌ No |
| Data Residency | ✅ Europe | ❌ US/Global | ❌ US | ❌ US | ❌ US |
| Open Source | ✅ Yes | ❌ No | ❌ No | ❌ No | ❌ No |
async function complete(prompt: string, model: string = 'mistral-large-latest') {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }]
})
});
const data = await response.json();
return data.choices[0].message.content;
}
class MistralConversation {
private messages: any[] = [];
private model: string;
constructor(model: string = 'mistral-large-latest') {
this.model = model;
}
async send(prompt: string) {
this.messages.push({ role: 'user', content: prompt });
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model: this.model,
messages: this.messages,
max_tokens: 4096
})
});
const data = await response.json();
const content = data.choices[0].message.content;
this.messages.push({ role: 'assistant', content });
return content;
}
getHistory() {
return [...this.messages];
}
clear() {
this.messages = [];
}
setModel(model: string) {
this.model = model;
}
}
interface ToolDefinition {
name: string;
description: string;
parameters: {
type: string;
properties: Record<string, any>;
required?: string[];
};
}
async function callWithTools(prompt: string, tools: ToolDefinition[]) {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model: 'mistral-large-latest',
messages: [{ role: 'user', content: prompt }],
tools: tools.map(t => ({
type: 'function',
function: {
name: t.name,
description: t.description,
parameters: t.parameters
}
}))
})
});
const data = await response.json();
return {
content: data.choices[0].message.content,
toolCalls: data.choices[0].message.tool_calls || []
};
}
// Usage
const tools = [
{
name: 'get_weather',
description: 'Get current weather',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' }
},
required: ['location']
}
}
];
const result = await callWithTools('What is the weather in Paris?', tools);
console.log(result.content);
console.log(result.toolCalls);
async function getEmbedding(text: string, model: string = 'mistral-embedding') {
const response = await fetch('https://api.mistral.ai/v1/embeddings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model,
input: text
})
});
const data = await response.json();
return data.data[0].embedding; // 1024-dimensional vector
}
// Batch embeddings
async function getEmbeddings(texts: string[]) {
const response = await fetch('https://api.mistral.ai/v1/embeddings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model: 'mistral-embedding',
input: texts
})
});
const data = await response.json();
return data.data.map((d: any) => d.embedding);
}
async function* streamComplete(prompt: string, model: string) {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
stream: true
})
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader!.read();
if (done) break;
const chunk = decoder.decode(value);
if (chunk.includes('[DONE]')) break;
try {
const data = JSON.parse(chunk.replace(/^data: /, ''));
if (data.choices?.[0]?.delta?.content) {
yield data.choices[0].delta.content;
}
} catch (error) {
// Ignore parse errors
}
}
}
// Usage
for await (const chunk of streamComplete('Tell me a story', 'mistral-large-latest')) {
process.stdout.write(chunk);
}
async function safeComplete(prompt: string, model: string = 'mistral-large-latest') {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
safe_mode: true
})
});
const data = await response.json();
return data.choices[0].message.content;
}
async function deterministicComplete(prompt: string, model: string, seed: number) {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MISTRAL_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: 'user', content: prompt }],
random_seed: seed,
temperature: 0.0 // For deterministic output
})
});
const data = await response.json();
return data.choices[0].message.content;
}