从零构建Prism自定义AI提供者:解锁LLM集成新范式

从零构建Prism自定义AI提供者:解锁LLM集成新范式

【免费下载链接】prism A unified interface for working with LLMs in Laravel 【免费下载链接】prism 项目地址: https://gitcode.com/gh_mirrors/prism14/prism

你是否曾因现有AI服务无法满足特定业务需求而困扰?是否希望将内部自研模型或小众AI服务无缝接入Laravel应用?Prism的自定义提供者机制为你打开了可能性之门。本文将系统带你掌握从接口设计到错误处理的全流程开发技巧,让你在1小时内拥有生产级别的AI服务集成能力。

核心概念与架构设计

Prism通过统一抽象层实现多AI服务的无缝切换,其核心在于Provider抽象类定义的标准化接口。该架构采用"最小实现原则",允许开发者仅覆盖需要支持的功能方法,大幅降低集成门槛。

mermaid

关键接口方法解析

  • text(): 处理文本生成请求,返回完整文本响应
  • stream(): 实现流式输出,返回Chunk生成器
  • structured(): 支持结构化数据输出,需配合Schema使用
  • handleRequestException(): 自定义错误处理逻辑,必须抛出异常

实战开发步骤

1. 创建提供者类

创建app/Prism/Providers/MyCustomProvider.php,继承抽象基类并实现核心方法:

namespace App\Prism\Providers;

use Generator;
use Prism\Prism\Providers\Provider;
use Prism\Prism\Text\Request as TextRequest;
use Prism\Prism\Text\Response as TextResponse;
use Prism\Prism\Text\Chunk;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;

class MyCustomProvider extends Provider
{
    protected PendingRequest $client;

    public function __construct(protected string $apiKey, protected string $baseUrl)
    {
        $this->client = Http::baseUrl($baseUrl)
            ->withHeaders([
                'Authorization' => "Bearer {$apiKey}",
                'Content-Type' => 'application/json',
            ]);
    }

    public function text(TextRequest $request): TextResponse
    {
        try {
            $response = $this->client->post('/completions', [
                'model' => $request->model,
                'prompt' => $request->prompt,
                'max_tokens' => $request->maxTokens,
            ]);

            return new TextResponse(
                text: $response->json('choices.0.text'),
                finishReason: $response->json('choices.0.finish_reason'),
                usage: new \Prism\Prism\ValueObjects\Usage(
                    promptTokens: $response->json('usage.prompt_tokens'),
                    completionTokens: $response->json('usage.completion_tokens'),
                ),
            );
        } catch (\Illuminate\Http\Client\RequestException $e) {
            $this->handleRequestException($request->model, $e);
        }
    }

    public function stream(TextRequest $request): Generator
    {
        $response = $this->client->send('POST', '/stream', [
            'body' => json_encode([
                'model' => $request->model,
                'prompt' => $request->prompt,
                'stream' => true,
            ]),
        ]);

        foreach (explode("\n", $response->body()) as $line) {
            if (str_starts_with($line, 'data: ')) {
                $data = json_decode(substr($line, 6), true);
                yield new Chunk(
                    content: $data['choices.0.text'],
                    finishReason: $data['choices.0.finish_reason'],
                );
            }
        }
    }
}

2. 服务注册与配置

AppServiceProvider中注册自定义提供者:

// app/Providers/AppServiceProvider.php
public function boot(): void
{
    $this->app['prism-manager']->extend('my-custom-provider', function ($app, $config) {
        return new \App\Prism\Providers\MyCustomProvider(
            apiKey: $config['api_key'],
            baseUrl: $config['base_url'] ?? 'https://api.my-custom-ai.com/v1',
        );
    });
}

添加配置到config/prism.php

return [
    'providers' => [
        // ...现有提供者
        'my-custom-provider' => [
            'api_key' => env('MY_CUSTOM_PROVIDER_API_KEY'),
            'base_url' => env('MY_CUSTOM_PROVIDER_BASE_URL'),
        ],
    ],
];

3. 高级错误处理

重写handleRequestException实现精细化错误控制:

public function handleRequestException(string $model, \Illuminate\Http\Client\RequestException $e): never
{
    $statusCode = $e->response->status();
    $responseBody = $e->response->json();

    match (true) {
        $statusCode === 429 => throw \Prism\Prism\Exceptions\PrismRateLimitedException::make(
            rateLimits: [
                'limit' => $e->response->header('X-RateLimit-Limit'),
                'remaining' => $e->response->header('X-RateLimit-Remaining'),
                'reset' => $e->response->header('X-RateLimit-Reset'),
            ],
            retryAfter: $e->response->header('Retry-After'),
        ),
        $statusCode === 400 && $responseBody['error']['type'] === 'invalid_schema' => 
            throw new \Prism\Prism\Exceptions\PrismStructuredDecodingException(
                message: $responseBody['error']['message'],
                errors: $responseBody['error']['details'],
            ),
        default => parent::handleRequestException($model, $e),
    };
}

测试与验证策略

单元测试实现

// tests/Unit/Providers/MyCustomProviderTest.php
use Prism\Prism\Facades\Prism;
use Prism\Prism\Enums\Provider as ProviderEnum;

it('can generate text with custom provider', function () {
    // 模拟API响应
    \Illuminate\Support\Facades\Http::fake([
        'https://api.my-custom-ai.com/v1/completions' => \Illuminate\Support\Facades\Http::response([
            'choices' => [['text' => 'Hello from custom AI', 'finish_reason' => 'stop']],
            'usage' => ['prompt_tokens' => 5, 'completion_tokens' => 10],
        ], 200),
    ]);

    $response = Prism::text()
        ->using('my-custom-provider', 'custom-model-1.0')
        ->withPrompt('Hello')
        ->asText();

    expect($response->text)->toBe('Hello from custom AI')
        ->and($response->usage->promptTokens)->toBe(5);
});

集成测试检查清单

✅ 验证所有实现的方法是否按预期工作
✅ 测试异常状态码处理(429/400/500等)
✅ 确认流式输出正确解析
✅ 检查配置参数是否正确传递
✅ 验证工具调用和结构化输出功能(如实现)

性能优化与最佳实践

连接池管理

为高频调用优化HTTP客户端配置:

protected function client(): PendingRequest
{
    return Http::baseUrl($this->baseUrl)
        ->withHeaders($this->headers)
        ->timeout(30)
        ->connectTimeout(5)
        ->pooled(); // 启用连接池
}

缓存策略实现

use Illuminate\Cache\CacheManager;

public function __construct(
    protected string $apiKey,
    protected CacheManager $cache,
) {}

public function embeddings(\Prism\Prism\Embeddings\Request $request): \Prism\Prism\Embeddings\Response
{
    $cacheKey = 'prism:embeddings:'.md5(implode(',', $request->texts).$request->model);
    
    if ($cached = $this->cache->get($cacheKey)) {
        return new \Prism\Prism\Embeddings\Response(
            embeddings: $cached['embeddings'],
            usage: new \Prism\Prism\ValueObjects\EmbeddingsUsage(...$cached['usage']),
        );
    }
    
    // API调用逻辑...
    
    $this->cache->put($cacheKey, [
        'embeddings' => $embeddings,
        'usage' => $usage->toArray(),
    ], now()->hourly());
    
    return $response;
}

安全最佳实践

  1. 敏感数据处理:避免日志记录API密钥,使用环境变量
  2. 输入验证:实现请求参数净化
    protected function sanitizePrompt(string $prompt): string
    {
        return trim(preg_replace('/[\r\n]+/', ' ', $prompt));
    }
    
  3. 权限控制:添加请求签名验证

常见问题与解决方案

问题场景解决方案代码示例
API响应格式不匹配实现响应适配器$this->adaptResponse($rawResponse)
模型不支持特定方法抛出UnsupportedAction异常throw PrismException::unsupportedProviderAction('stream', self::class)
长文本截断处理实现自动分块逻辑$chunks = str_split($text, 4096);
多模态输入支持使用Media对象包装Image::fromLocalPath($path)->toArray()

生产环境部署清单

  •  完成单元测试覆盖率≥80%
  •  实现请求重试机制
  •  添加性能监控指标
    // 在text()方法中添加
    \Illuminate\Support\Facades\Log::info('Prism custom provider usage', [
        'model' => $request->model,
        'duration' => microtime(true) - LARAVEL_START,
    ]);
    
  •  配置熔断保护
  •  编写操作文档

通过这套开发框架,你可以将任何AI服务标准化为Prism兼容的提供者,实现"一次集成,处处可用"的效果。无论是企业内部模型、开源LLM还是新兴AI服务,Prism的抽象层都能确保你的Laravel应用保持一致的调用体验。

想进一步提升?考虑实现:

  • 分布式追踪集成
  • 动态模型路由
  • A/B测试框架
  • 成本计量系统

【免费下载链接】prism A unified interface for working with LLMs in Laravel 【免费下载链接】prism 项目地址: https://gitcode.com/gh_mirrors/prism14/prism

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值