ワンクリックで
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;
}