An open API service indexing awesome lists of open source software.

https://github.com/projectsaturnstudios/llm-speak-mistral


https://github.com/projectsaturnstudios/llm-speak-mistral

Last synced: 6 months ago
JSON representation

Awesome Lists containing this project

README

          

# LLMSpeak Mistral AI

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![PHP](https://img.shields.io/badge/PHP-8.2%2B-blue.svg)](https://php.net/releases/)
[![Laravel](https://img.shields.io/badge/Laravel-10.x%7C11.x%7C12.x-red.svg)](https://laravel.com)
[![Latest Version on Packagist](https://img.shields.io/packagist/v/llm-speak/mistral-ai.svg?style=flat-square)](https://packagist.org/packages/llm-speak/mistral-ai)
[![Total Downloads](https://img.shields.io/packagist/dt/llm-speak/mistral-ai.svg?style=flat-square)](https://packagist.org/packages/llm-speak/mistral-ai)

**LLMSpeak Mistral AI** is a Laravel package that provides a fluent, Laravel-native interface for integrating with Mistral AI's powerful language models. Built as part of the LLMSpeak ecosystem, it offers seamless access to Mistral's cutting-edge models including Mistral Large, Mistral Medium, and specialized models like Codestral for code generation.

> **Note:** This package is part of the larger [LLMSpeak ecosystem](https://github.com/projectsaturnstudios/llm-speak). For universal provider switching and standardized interfaces, check out the [LLMSpeak Core](https://github.com/projectsaturnstudios/llm-speak-core) package.

## Table of Contents
- [Features](#features)
- [Get Started](#get-started)
- [Usage](#usage)
- [Chat Completions](#chat-completions)
- [Embeddings](#embeddings)
- [Fluent Request Building](#fluent-request-building)
- [Tool Calling](#tool-calling)
- [Multiple Choices](#multiple-choices)
- [Response Formatting](#response-formatting)
- [Streaming Responses](#streaming-responses)
- [Advanced Configuration](#advanced-configuration)
- [Response Handling](#response-handling)
- [Testing](#testing)
- [Credits](#credits)
- [License](#license)

## Features

- **🧠 Advanced Models**: Access to Mistral Large, Medium, Small, and specialized models like Codestral
- **🚀 Laravel Native**: Full Laravel integration with automatic service discovery
- **🔧 Fluent Interface**: Expressive request builders with method chaining
- **📊 Laravel Data**: Powered by Spatie Laravel Data for robust data validation
- **🛠️ Tool Support**: Complete function calling capabilities with flexible tool choice
- **📝 Embeddings**: Advanced embedding generation with multiple output formats
- **🎛️ Output Control**: Precise control over embedding dimensions and data types
- **💨 Streaming**: Real-time streaming responses for chat completions
- **🎯 JSON Mode**: Structured output generation for reliable data extraction
- **🎯 Type Safety**: Full PHP 8.2+ type declarations and IDE support
- **🔐 Secure**: Built-in API key management and request validation

## Get Started

> **Requires [PHP 8.2+](https://php.net/releases/) and Laravel 10.x/11.x/12.x**

Install the package via [Composer](https://getcomposer.org/):

```bash
composer require llm-speak/mistral-ai
```

The package will automatically register itself via Laravel's package discovery.

### Environment Configuration

Add your Mistral AI API key to your `.env` file:

```env
MISTRAL_API_KEY=your_mistral_api_key_here
```

Get your API key from [Mistral AI Console](https://console.mistral.ai/).

## Usage

### Chat Completions

The simplest way to chat with Mistral AI models:

```php
use LLMSpeak\Mistral\MistralCompletionsRequest;

$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
['role' => 'user', 'content' => 'Explain quantum computing in simple terms']
]
);

$response = $request->post();

echo $response->getTextContent(); // "Quantum computing is..."
```

### Model Selection

Choose the right Mistral model for your use case:

```php
// Most capable model for complex reasoning
$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: $messages
);

// Balanced performance and speed
$request = new MistralCompletionsRequest(
model: 'mistral-medium-latest',
messages: $messages
);

// Fast and efficient for simple tasks
$request = new MistralCompletionsRequest(
model: 'mistral-small-latest',
messages: $messages
);

// Specialized for code generation
$request = new MistralCompletionsRequest(
model: 'codestral-latest',
messages: $messages
);
```

### Embeddings

Generate embeddings with advanced output control:

```php
use LLMSpeak\Mistral\MistralEmbeddingsRequest;

// Simple text embedding
$request = new MistralEmbeddingsRequest(
model: 'mistral-embed',
input: 'Generate embeddings for this text'
);

$response = $request->post();

$embeddings = $response->getEmbeddings();
$dimensions = $response->getDimensions();
```

### Advanced Embedding Configuration

Control output format and dimensions:

```php
// High-precision embeddings
$request = new MistralEmbeddingsRequest(
model: 'mistral-embed',
input: 'Research paper abstract content'
)
->setOutputDimension(1024) // Custom dimensions
->setOutputDtype('float'); // High precision

// Memory-efficient embeddings
$request = new MistralEmbeddingsRequest(
model: 'mistral-embed',
input: ['Text 1', 'Text 2', 'Text 3'] // Batch processing
)
->setOutputDimension(512) // Reduced dimensions
->setOutputDtype('int8'); // Quantized format

// Ultra-compact embeddings
$request = new MistralEmbeddingsRequest(
model: 'mistral-embed',
input: $documentTexts
)
->setOutputDimension(256)
->setOutputDtype('binary'); // Maximum compression

$response = $request->post();

// Access different embedding formats
$embeddings = $response->getEmbeddings(); // Raw embeddings
$firstEmbedding = $response->getFirstEmbedding(); // Single vector
$count = $response->getEmbeddingCount(); // Number of embeddings
```

### Universal LLMSpeak Interface

For **provider-agnostic embeddings** that work across Mistral, Gemini, Ollama, and other providers, use the universal LLMSpeak interface:

```php
use LLMSpeak\Core\Support\Facades\LLMSpeak;
use LLMSpeak\Core\Support\Requests\LLMSpeakEmbeddingsRequest;

// Universal request works with ANY provider
$request = new LLMSpeakEmbeddingsRequest(
model: 'mistral-embed',
input: 'Generate embeddings for this text',
encoding_format: 'float', // Maps to Mistral's outputDtype
dimensions: 1024, // Maps to Mistral's outputDimension
task_type: null // Not applicable for Mistral
);

// Execute with Mistral - same code works with other providers!
$response = LLMSpeak::embeddingsFrom('mistral', $request);

// Universal response methods
$embeddings = $response->getAllEmbeddings();
$firstVector = $response->getFirstEmbedding();
$dimensions = $response->getDimensions();
$tokenUsage = $response->getTotalTokens();
```

### Universal Format Mapping

The universal interface automatically maps encoding formats to Mistral's native types:

```php
// Float precision (maps to Mistral's outputDtype: 'float')
$floatRequest = new LLMSpeakEmbeddingsRequest(
model: 'mistral-embed',
input: 'High precision embeddings',
encoding_format: 'float', // → outputDtype: 'float'
dimensions: 1024, // → outputDimension: 1024
task_type: null
);

$floatResponse = LLMSpeak::embeddingsFrom('mistral', $floatRequest);

// Quantized format (maps to Mistral's outputDtype: 'int8')
$quantizedRequest = new LLMSpeakEmbeddingsRequest(
model: 'mistral-embed',
input: 'Memory-efficient embeddings',
encoding_format: 'base64', // → outputDtype: 'int8' (quantized)
dimensions: 512, // → outputDimension: 512
task_type: null
);

$quantizedResponse = LLMSpeak::embeddingsFrom('mistral', $quantizedRequest);

// Batch processing with universal interface
$batchRequest = new LLMSpeakEmbeddingsRequest(
model: 'mistral-embed',
input: [
'Document one for embeddings',
'Document two for embeddings',
'Document three for embeddings'
],
encoding_format: 'float',
dimensions: null, // Use model default
task_type: null
);

$batchResponse = LLMSpeak::embeddingsFrom('mistral', $batchRequest);

echo "Generated {$batchResponse->getEmbeddingCount()} embeddings";
echo "Vector dimensions: {$batchResponse->getDimensions()}";
```

### Advanced Universal Configuration

Access Mistral's advanced features through the universal interface:

```php
// Ultra-compact embeddings with automatic format mapping
$compactRequest = new LLMSpeakEmbeddingsRequest(
model: 'mistral-embed',
input: 'Large document corpus for storage',
encoding_format: 'base64', // Automatically maps to binary/int8
dimensions: 256, // Reduced dimensions for storage
task_type: null
);

$compactResponse = LLMSpeak::embeddingsFrom('mistral', $compactRequest);

// Different models with same interface
$models = ['mistral-embed', 'codestral-embed'];
foreach ($models as $model) {
$request = new LLMSpeakEmbeddingsRequest(
model: $model,
input: 'Code snippet for analysis',
encoding_format: 'float',
dimensions: 1024,
task_type: null
);

$response = LLMSpeak::embeddingsFrom('mistral', $request);
echo "Model {$model}: {$response->getDimensions()} dimensions";
}
```

### Why Use Universal Interface?

**✅ Provider Independence:** Switch between Mistral, Gemini, Ollama with zero code changes
**✅ Automatic Mapping:** Encoding formats automatically mapped to provider-specific types
**✅ Future Proof:** New providers automatically supported
**✅ Consistent API:** Same methods across all providers
**✅ Type Safety:** Full PHP type declarations and IDE support

```php
// Same request works with different providers!
$request = new LLMSpeakEmbeddingsRequest(
model: 'embedding-model',
input: 'Universal text input',
encoding_format: 'float',
dimensions: 512,
task_type: null
);

$mistralResponse = LLMSpeak::embeddingsFrom('mistral', $request); // Mistral AI
$geminiResponse = LLMSpeak::embeddingsFrom('gemini', $request); // Google AI
$ollamaResponse = LLMSpeak::embeddingsFrom('ollama', $request); // Local models
```

### Fluent Request Building

Build complex requests using the fluent interface:

```php
use LLMSpeak\Mistral\MistralCompletionsRequest;

$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
['role' => 'user', 'content' => 'Write a creative story about AI']
]
)
->setMaxTokens(2000)
->setTemperature(0.8)
->setPresencePenalty(0.1)
->setFrequencyPenalty(0.1)
->setStop(['THE END', '---']);

$response = $request->post();

// Access response properties
echo $response->id; // chatcmpl-abc123
echo $response->model; // mistral-large-latest
echo $response->getTotalTokens(); // 1850
echo $response->getTextContent(); // Generated story
```

### Batch Configuration

Set multiple parameters at once:

```php
$request = new MistralCompletionsRequest(
model: 'mistral-medium-latest',
messages: $conversation
)->setMultiple([
'maxTokens' => 1500,
'temperature' => 0.7,
'presencePenalty' => 0.2,
'frequencyPenalty' => 0.1,
'stop' => ['Human:', 'Assistant:'],
'n' => 3 // Generate 3 different responses
]);
```

### Tool Calling

Enable Mistral models to use external functions:

```php
$tools = [
[
'type' => 'function',
'function' => [
'name' => 'get_weather_forecast',
'description' => 'Get weather forecast for a specific location',
'parameters' => [
'type' => 'object',
'properties' => [
'location' => [
'type' => 'string',
'description' => 'City and country (e.g., "Paris, France")'
],
'days' => [
'type' => 'integer',
'description' => 'Number of days to forecast (1-7)',
'minimum' => 1,
'maximum' => 7
]
],
'required' => ['location']
]
]
]
];

$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
['role' => 'user', 'content' => 'What\'s the weather forecast for London this week?']
]
)
->setTools($tools)
->setToolChoice('auto'); // Let model decide when to use tools

$response = $request->post();

// Check for tool usage
if ($response->usedTools()) {
$toolCalls = $response->getToolCalls();
foreach ($toolCalls as $call) {
echo "Function: {$call['function']['name']}\n";
echo "Arguments: " . json_encode($call['function']['arguments']) . "\n";
}
}
```

### Multiple Choices

Generate multiple response alternatives:

```php
$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
['role' => 'user', 'content' => 'Give me three different marketing slogans for an eco-friendly product']
]
)
->setN(3) // Generate 3 different responses
->setTemperature(0.9); // Higher creativity for variety

$response = $request->post();

// Access all choices
$allChoices = $response->getAllChoices();
foreach ($allChoices as $index => $choice) {
echo "Option " . ($index + 1) . ": " . $choice['message']['content'] . "\n\n";
}

// Or get a specific choice
$firstChoice = $response->getChoice(0);
$secondChoice = $response->getChoice(1);
```

### Response Formatting

Control output format for structured data:

```php
$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
[
'role' => 'user',
'content' => 'Extract the following information from this text as JSON: name, age, occupation. Text: "John Smith is a 35-year-old software engineer."'
]
]
)
->setResponseFormat(['type' => 'json_object'])
->setMaxTokens(200);

$response = $request->post();

$jsonContent = $response->getTextContent();
$data = json_decode($jsonContent, true);

echo "Name: " . $data['name']; // John Smith
echo "Age: " . $data['age']; // 35
echo "Occupation: " . $data['occupation']; // software engineer
```

### Streaming Responses

Enable real-time streaming for long responses:

```php
$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: [
['role' => 'user', 'content' => 'Write a detailed technical article about machine learning']
]
)
->setStream(true)
->setMaxTokens(4000);

$response = $request->post();

// Stream handling will be processed by the CompletionsEndpoint
// Response contains streaming data format
```

### Advanced Configuration

Configure advanced parameters for optimal performance:

```php
$request = new MistralCompletionsRequest(
model: 'mistral-large-latest',
messages: $conversationHistory
)
->setMaxTokens(4000)
->setTemperature(0.7)
->setPresencePenalty(0.3) // Encourage topic diversity
->setFrequencyPenalty(0.2) // Reduce repetition
->setStop(['[END]', '###']) // Custom stop sequences
->setN(2) // Generate 2 alternatives
->setResponseFormat(['type' => 'json_object']);

$response = $request->post();
```

## Response Handling

Access comprehensive response data:

```php
$response = $request->post();

// Basic response info
$responseId = $response->id;
$modelUsed = $response->model;
$timestamp = $response->created;
$responseObject = $response->object;

// Content access
$textContent = $response->getTextContent();
$allChoices = $response->getAllChoices();
$firstChoice = $response->getChoice(0);

// Token usage analysis
$totalTokens = $response->getTotalTokens();
$promptTokens = $response->getPromptTokens();
$completionTokens = $response->getCompletionTokens();

// Completion analysis
$finishReason = $response->getFinishReason();
$completedNaturally = $response->completedNaturally();
$hitTokenLimit = $response->reachedTokenLimit();
$stoppedBySequence = $response->stoppedBySequence();

// Tool usage analysis
$usedTools = $response->usedTools();
$toolCalls = $response->getToolCalls();
$hasAnyToolCalls = $response->hasAnyToolCalls();

// Quality metrics
$responseQuality = $response->calculateQualityScore();
$isHighQuality = $response->isHighQuality();

// System information
$systemFingerprint = $response->system_fingerprint;

// Convert to array for storage
$responseArray = $response->toArray();

// Embeddings Response Handling
$embeddingResponse = $embeddingRequest->post();

$embeddings = $embeddingResponse->getEmbeddings();
$firstVector = $embeddingResponse->getFirstEmbedding();
$dimensions = $embeddingResponse->getDimensions();
$embeddingCount = $embeddingResponse->getEmbeddingCount();
$tokenUsage = $embeddingResponse->getTotalTokens();
```

## Testing

The package provides testing utilities for mocking Mistral responses:

```php
use LLMSpeak\Mistral\MistralCompletionsRequest;
use LLMSpeak\Mistral\MistralCompletionsResponse;
use LLMSpeak\Mistral\MistralEmbeddingsResponse;

// Create a mock chat completion response
$mockResponse = new MistralCompletionsResponse(
id: 'chatcmpl-test123',
object: 'chat.completion',
created: time(),
model: 'mistral-large-latest',
choices: [
[
'index' => 0,
'message' => [
'role' => 'assistant',
'content' => 'Mock response content'
],
'finish_reason' => 'stop'
]
],
usage: [
'prompt_tokens' => 15,
'completion_tokens' => 20,
'total_tokens' => 35
]
);

// Test your application logic
$this->assertEquals('Mock response content', $mockResponse->getTextContent());
$this->assertEquals(35, $mockResponse->getTotalTokens());
$this->assertTrue($mockResponse->completedNaturally());

// Create a mock embeddings response
$mockEmbeddingResponse = new MistralEmbeddingsResponse(
id: 'emb-test123',
object: 'list',
data: [
[
'object' => 'embedding',
'embedding' => array_fill(0, 1024, 0.1),
'index' => 0
]
],
model: 'mistral-embed',
usage: [
'prompt_tokens' => 5,
'total_tokens' => 5
],
status_code: 200,
headers: []
);

// Test embedding functionality
$this->assertEquals(1024, $mockEmbeddingResponse->getDimensions());
$this->assertEquals(1, $mockEmbeddingResponse->getEmbeddingCount());
```

## Credits

- [Project Saturn Studios](https://github.com/projectsaturnstudios)
- [Mistral AI](https://mistral.ai) for providing advanced language models

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

---

**Part of the LLMSpeak Ecosystem** - Built with ❤️ by [Project Saturn Studios](https://projectsaturnstudios.com)