Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ai Voyage Platform Laravel Package

symfony/ai-voyage-platform

Symfony AI bridge for Voyage AI: integrate Voyage text and multimodal embeddings into Symfony apps. Provides a platform connector to call Voyage APIs and use embedding models for semantic search, RAG, and vector workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies:

    composer require symfony/ai symfony/ai-voyage-platform symfony/http-client
    

    For Laravel-only stacks, add a Symfony-compatible container (e.g., php-di/php-di).

  2. Configure API Key: Add Voyage’s API key to config/services.php:

    'voyage' => [
        'api_key' => env('VOYAGE_API_KEY'),
    ],
    
  3. First Use Case: Generate embeddings for a text string:

    use Symfony\AI\Voyage\VoyageEmbeddingModel;
    
    $model = new VoyageEmbeddingModel('text-embedding-v1');
    $embeddings = $model->generate(['Your text here']);
    
  4. Laravel Integration: Bind the model in a service provider:

    $this->app->singleton(VoyageEmbeddingModel::class, function ($app) {
        return new VoyageEmbeddingModel('text-embedding-v1', $app['voyage.client']);
    });
    

Where to Look First


Implementation Patterns

Usage Patterns

1. Basic Embedding Generation

// Laravel Service
public function generateEmbeddings(string $text): array
{
    $model = app(VoyageEmbeddingModel::class);
    return $model->generate([$text]);
}

2. Dynamic Model Routing (v0.8.0+)

// Route models based on configuration
$modelName = config('ai.voyage.model');
$model = new VoyageEmbeddingModel($modelName);

3. Batch Processing

// Process multiple texts in one API call
$embeddings = $model->generate([
    'Text 1',
    'Text 2',
    // ...
]);

4. Multimodal Embeddings

// For images/text combinations
$model = new VoyageEmbeddingModel('multimodal-embedding-v1');
$embeddings = $model->generate([
    ['text' => 'Describe this image:', 'image_url' => 'https://example.com/image.jpg'],
]);

5. Integration with Vector Databases

// Store embeddings in Meilisearch/TypeORM
$embeddings = $this->generateEmbeddings($text);
$vectorDB->addDocument($text, $embeddings);

Workflows

Semantic Search Pipeline

  1. Generate embeddings for user query.
  2. Query vector database (e.g., Meilisearch) with embeddings.
  3. Return top-k results.
$queryEmbeddings = $this->generateEmbeddings($userQuery);
$results = $vectorDB->search($queryEmbeddings, limit: 5);

Hybrid Recommendation System

  1. Embed user profile and items.
  2. Compute similarity scores (e.g., cosine similarity).
  3. Rank items.
$userEmbedding = $this->generateEmbeddings($userProfile);
$itemEmbeddings = $this->generateEmbeddings($items);
$scores = $this->computeSimilarity($userEmbedding, $itemEmbeddings);

Integration Tips

  • Caching: Cache embeddings in Redis to reduce API calls:

    $cacheKey = "embedding:{$text}";
    $embeddings = cache()->remember($cacheKey, now()->addHours(1), function() use ($text) {
        return $this->generateEmbeddings($text);
    });
    
  • Error Handling: Wrap API calls in try-catch:

    try {
        $embeddings = $model->generate([$text]);
    } catch (\Symfony\Contracts\HttpClient\Exception\ClientException $e) {
        log::error("Voyage API error: " . $e->getMessage());
        return fallbackEmbeddings();
    }
    
  • Laravel Facade:

    // app/Facades/VoyageFacade.php
    namespace App\Facades;
    use Illuminate\Support\Facades\Facade;
    
    class VoyageFacade extends Facade {
        protected static function getFacadeAccessor() { return 'voyage.embedding'; }
    }
    

    Bind in AppServiceProvider:

    $this->app->bind('voyage.embedding', function ($app) {
        return new VoyageEmbeddingModel(config('ai.voyage.model'), $app['voyage.client']);
    });
    

    Usage:

    $embeddings = VoyageFacade::generate(['text']);
    

Gotchas and Tips

Pitfalls

  1. Symfony DI Conflicts:

    • Laravel’s container may clash with Symfony’s. Use php-di/php-di as a neutral container or wrap Symfony services in Laravel bindings.
  2. API Rate Limits:

    • Voyage’s free tier has strict limits. Implement retries with exponential backoff:
      use Symfony\Contracts\HttpClient\HttpClientInterface;
      
      $client = HttpClient::create([
          'timeout' => 30,
          'base_uri' => 'https://api.voyage.ai',
          'options' => [
              'headers' => ['Authorization' => 'Bearer ' . config('services.voyage.api_key')],
              'retries' => 3,
          ],
      ]);
      
  3. Model Name Mismatches:

    • Voyage’s model names (e.g., text-embedding-v1) differ from OpenAI’s. Double-check the Voyage docs.
  4. Multimodal Input Format:

    • Multimodal embeddings require specific input structure:
      // Correct
      $model->generate([['text' => 'Describe this:', 'image_url' => '...']]);
      
      // Incorrect (will fail)
      $model->generate(['Describe this:', 'image_url']);
      
  5. Laravel’s env() vs. Symfony Config:

    • Symfony’s Container uses parameter_bag, while Laravel uses env(). Bridge them:
      $container->setParameter('voyage.api_key', env('VOYAGE_API_KEY'));
      

Debugging

  • Enable Symfony Debug Mode:

    $client = HttpClient::create([
        'debug' => true,
    ]);
    

    Check logs for HTTP errors.

  • Validate Inputs:

    • Voyage rejects malformed inputs (e.g., empty strings, invalid URLs). Sanitize data:
      $text = trim($text);
      if (empty($text)) throw new \InvalidArgumentException("Text cannot be empty");
      
  • Check API Responses:

    • Voyage returns structured errors. Parse them:
      try {
          $response = $client->request('POST', '/v1/embeddings', [
              'json' => ['input' => [$text]],
          ]);
          $data = $response->toArray();
          if (isset($data['error'])) {
              throw new \RuntimeException($data['error']['message']);
          }
      } catch (\Throwable $e) {
          log::error("Voyage API failed: " . $e->getMessage());
      }
      

Config Quirks

  • Dynamic Model Routing: Configure in config/ai.php:

    'voyage' => [
        'model' => env('VOYAGE_MODEL', 'text-embedding-v1'),
        'timeout' => 30,
    ],
    
  • HTTP Client Overrides: Customize the client in a service provider:

    $this->app->singleton(HttpClientInterface::class, function ($app) {
        return HttpClient::create([
            'base_uri' => 'https://api.voyage.ai',
            'auth_bearer' => config('services.voyage.api_key'),
            'timeout' => config('ai.voyage.timeout'),
        ]);
    });
    

Extension Points

  1. Custom Providers: Extend the Provider abstraction to support multiple services:

    namespace App\AI\Providers;
    
    use Symfony\AI\Provider\EmbeddingProviderInterface;
    
    class CustomVoyageProvider implements EmbeddingProviderInterface {
        public function generate(array $inputs): array {
            // Custom logic (e.g., retry, caching)
            return $model->generate($inputs);
        }
    }
    
  2. Laravel Events: Dispatch events for embedding generation:

    event(new EmbeddingsGenerated($text, $embeddings));
    
  3. Model Factories: Create a factory for different embedding models

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky