laraveliaphpllphantlangchain

LLPhant en Laravel: Integra IA Generativa sin Complejidad

Introducción

Desde hace meses, la inteligencia artificial generativa ha revolucionado la forma en que construimos aplicaciones web. Sin embargo, la mayoría de herramientas populares como LangChain están diseñadas para Python, dejando a los desarrolladores PHP en una posición incómoda.

Entra LLPhant: un framework PHP que trae los patrones y capacidades de LangChain directamente a tu ecosistema Laravel. Si has querido integrar IA generativa en tus proyectos pero no sabías por dónde empezar, este artículo te dará todas las herramientas que necesitas.

En esta guía veremos qué es LLPhant, cómo instalarlo, y cómo construir aplicaciones reales con soporte para múltiples proveedores de LLM, embeddings, vector stores y RAG (Retrieval-Augmented Generation).

¿Qué es LLPhant?

LLPhant es un framework PHP para construir aplicaciones de inteligencia artificial generativa. Está inspirado en LangChain pero diseñado específicamente para PHP y Laravel, lo que significa:

  • Sintaxis PHP nativa: No necesitas aprender una API completamente nueva
  • Integración con Laravel: Funciona perfectamente con tus modelos, jobs y servicios
  • Múltiples proveedores de LLM: OpenAI, Anthropic, Google, y más
  • Vector stores: Integración con Pinecone, Weaviate, Milvus y otros
  • RAG capabilities: Implementa sistemas de recuperación de información avanzados
  • Embeddings: Convierte texto en vectores para búsquedas semánticas

Básicamente, LLPhant abstrae la complejidad de trabajar con modelos de lenguaje, permitiéndote enfocarte en la lógica de tu aplicación.

Instalación de LLPhant

Primero, instala el paquete mediante Composer:

composer require llphant/llphant

Luego, configura tus credenciales de API en el archivo .env:

OPENAI_API_KEY=sk-xxxxxxxxxxxxx
OPENAI_ORG_ID=org-xxxxxxxxxxxxx

Si usas otro proveedor como Anthropic:

ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxx
GOOGLE_API_KEY=xxxxxxxxxxxxx

Configuración Básica en Laravel

Crea un archivo de configuración config/llphant.php:

<?php

return [
    'default_llm' => env('LLPHANT_DEFAULT_LLM', 'openai'),
    
    'llms' => [
        'openai' => [
            'driver' => 'openai',
            'api_key' => env('OPENAI_API_KEY'),
            'org_id' => env('OPENAI_ORG_ID'),
            'model' => 'gpt-4-turbo',
        ],
        'anthropic' => [
            'driver' => 'anthropic',
            'api_key' => env('ANTHROPIC_API_KEY'),
            'model' => 'claude-3-opus-20240229',
        ],
    ],
    
    'embeddings' => [
        'driver' => 'openai',
        'model' => 'text-embedding-3-small',
    ],
    
    'vector_store' => [
        'driver' => env('VECTOR_STORE_DRIVER', 'pinecone'),
        'api_key' => env('PINECONE_API_KEY'),
        'environment' => env('PINECONE_ENVIRONMENT', 'us-west1-gcp'),
    ],
];

Tu Primer Agente IA con LLPhant

Vamos a crear un agente simple que responda preguntas usando LLPhant. Primero, crea un servicio:

<?php

namespace App\Services;

use LLPhant\Agent\Agent;
use LLPhant\LLM\OpenAI\OpenAI;

class AIAgentService
{
    protected Agent $agent;
    
    public function __construct()
    {
        $llm = new OpenAI([
            'apiKey' => env('OPENAI_API_KEY'),
            'model' => 'gpt-4-turbo',
        ]);
        
        $this->agent = new Agent($llm);
    }
    
    public function ask(string $question): string
    {
        return $this->agent->run($question);
    }
    
    public function chat(array $messages): string
    {
        return $this->agent->chat($messages);
    }
}

Ahora, usa este servicio en un controlador:

<?php

namespace App\Http\Controllers;

use App\Services\AIAgentService;
use Illuminate\Http\Request;

class AIController extends Controller
{
    public function __construct(
        protected AIAgentService $aiService
    ) {}
    
    public function ask(Request $request)
    {
        $question = $request->input('question');
        
        $response = $this->aiService->ask($question);
        
        return response()->json([
            'question' => $question,
            'answer' => $response,
        ]);
    }
}

RAG: Recuperación Aumentada por Generación

RAG es poderoso para cuando quieres que tu IA responda basándose en documentos específicos. Con LLPhant es sencillo:

<?php

namespace App\Services;

use LLPhant\Agent\Agent;
use LLPhant\LLM\OpenAI\OpenAI;
use LLPhant\Embeddings\EmbeddingGenerator\OpenAIEmbeddingGenerator;
use LLPhant\DocumentStore\DocumentStore;
use LLPhant\Document\Document;

class RAGService
{
    protected Agent $agent;
    protected DocumentStore $documentStore;
    
    public function __construct()
    {
        $llm = new OpenAI([
            'apiKey' => env('OPENAI_API_KEY'),
        ]);
        
        $embeddingGenerator = new OpenAIEmbeddingGenerator(
            env('OPENAI_API_KEY')
        );
        
        $this->documentStore = new DocumentStore(
            $embeddingGenerator,
            new PineconeStore() // Tu vector store
        );
        
        $this->agent = new Agent($llm);
    }
    
    public function addDocuments(array $texts): void
    {
        foreach ($texts as $text) {
            $document = new Document($text);
            $this->documentStore->addDocument($document);
        }
    }
    
    public function queryWithRAG(string $query): string
    {
        // Recupera documentos relevantes
        $relevantDocs = $this->documentStore->search($query, limit: 5);
        
        // Construye el contexto
        $context = implode("\n\n", 
            array_map(fn($doc) => $doc->content, $relevantDocs)
        );
        
        // Envía al agente con contexto
        $prompt = "Basándote en esta información:\n\n{$context}\n\nResponde: {$query}";
        
        return $this->agent->run($prompt);
    }
}

Integrando con Colas de Laravel

Para queries pesadas, es ideal procesarlas en background con jobs:

<?php

namespace App\Jobs;

use App\Services\AIAgentService;
use App\Models\AIQuery;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessAIQuery implements ShouldQueue
{
    use Queueable, SerializesModels, InteractsWithQueue;
    
    public function __construct(
        protected AIQuery $query
    ) {}
    
    public function handle(AIAgentService $aiService): void
    {
        try {
            $response = $aiService->ask($this->query->text);
            
            $this->query->update([
                'response' => $response,
                'status' => 'completed',
                'processed_at' => now(),
            ]);
        } catch (\Exception $e) {
            $this->query->update([
                'status' => 'failed',
                'error' => $e->getMessage(),
            ]);
            
            $this->fail($e);
        }
    }
}

En tu controlador:

public function askAsync(Request $request)
{
    $query = AIQuery::create([
        'text' => $request->input('question'),
        'status' => 'pending',
    ]);
    
    ProcessAIQuery::dispatch($query);
    
    return response()->json([
        'id' => $query->id,
        'status' => 'processing',
    ]);
}

Trabajando con Múltiples Proveedores

Crea un factory que facilite cambiar entre proveedores:

<?php

namespace App\Services;

use LLPhant\LLM\OpenAI\OpenAI;
use LLPhant\LLM\Anthropic\Anthropic;
use LLPhant\LLM\Google\Gemini;

class LLMFactory
{
    public static function create(string $provider = null)
    {
        $provider = $provider ?? config('llphant.default_llm');
        
        return match($provider) {
            'openai' => new OpenAI([
                'apiKey' => env('OPENAI_API_KEY'),
                'model' => 'gpt-4-turbo',
            ]),
            'anthropic' => new Anthropic([
                'apiKey' => env('ANTHROPIC_API_KEY'),
                'model' => 'claude-3-opus-20240229',
            ]),
            'google' => new Gemini([
                'apiKey' => env('GOOGLE_API_KEY'),
                'model' => 'gemini-2.0-flash',
            ]),
            default => throw new \InvalidArgumentException(
                "Proveedor LLM desconocido: {$provider}"
            ),
        };
    }
}

Embeddings y Búsqueda Semántica

Usa embeddings para búsquedas inteligentes:

<?php

namespace App\Services;

use LLPhant\Embeddings\EmbeddingGenerator\OpenAIEmbeddingGenerator;
use App\Models\Article;

class SemanticSearchService
{
    protected OpenAIEmbeddingGenerator $generator;
    
    public function __construct()
    {
        $this->generator = new OpenAIEmbeddingGenerator(
            env('OPENAI_API_KEY'),
            'text-embedding-3-small'
        );
    }
    
    public function search(string $query, int $limit = 5): array
    {
        $queryEmbedding = $this->generator->generateEmbedding($query);
        
        // Busca artículos similares usando distancia coseno
        return Article::query()
            ->selectRaw(
                'articles.*',
                'articles.embedding <=> ? as similarity',
                [$queryEmbedding]
            )
            ->orderByRaw('articles.embedding <=> ?', [$queryEmbedding])
            ->limit($limit)
            ->get();
    }
}

Mejores Prácticas

1. Manejo de Errores Robusto

public function safeAsk(string $question): array
{
    try {
        $answer = $this->agent->run($question);
        
        return [
            'success' => true,
            'answer' => $answer,
        ];
    } catch (\LLPhant\Exception\RateLimitException $e) {
        // Maneja rate limits con retry
        sleep(60);
        return $this->safeAsk($question);
    } catch (\LLPhant\Exception\TokenLimitException $e) {
        return [
            'success' => false,
            'error' => 'La pregunta es demasiado larga',
        ];
    } catch (\Exception $e) {
        Log::error('Error en LLPhant', ['error' => $e->getMessage()]);
        
        return [
            'success' => false,
            'error' => 'Error procesando tu solicitud',
        ];
    }
}

2. Cachea Respuestas

public function askWithCache(string $question): string
{
    return Cache::remember(
        "ai_question:" . md5($question),
        now()->addHours(24),
        fn() => $this->aiService->ask($question)
    );
}

3. Limita Costos

$llm = new OpenAI([
    'apiKey' => env('OPENAI_API_KEY'),
    'model' => 'gpt-3.5-turbo', // Más económico
    'max_tokens' => 500, // Limita tokens
]);

Conclusión

LLPhant abre un mundo de posibilidades para integrar IA en tus aplicaciones Laravel. Ya sea que necesites chatbots, búsqueda semántica, análisis de documentos o asistentes inteligentes, este framework proporciona abstracciones claras y eficientes.

La curva de aprendizaje es suave si ya estás familiarizado con Laravel, y puedes comenzar pequeño—una simple consulta a un LLM—y escalar a sistemas complejos con RAG y múltiples proveedores.

Lo importante es empezar. Crea tu primer agente hoy, experimenta con diferentes modelos, y descubre cómo la IA puede mejorar la experiencia de tus usuarios.

Puntos Clave

  • LLPhant es el LangChain de PHP: Abstrae la complejidad de trabajar con modelos de lenguaje
  • Múltiples proveedores: Soporta OpenAI, Anthropic, Google Gemini y más
  • RAG integrado: Recupera documentos relevantes para respuestas contextuales
  • Integración natural con Laravel: Jobs, colas, caché y validación funcionan sin fricciones
  • Embeddings para búsqueda semántica: Encuentra contenido similar en lugar de coincidencias exactas
  • Gestión de costos importante: Limita tokens, usa modelos económicos y cachea respuestas
  • Manejo robusto de errores: Rate limits, token limits y fallos de API requieren estrategias específicas
  • Comienza simple: Una consulta a un LLM y crece desde ahí hacia sistemas más complejos