PHP项目AI绘图如何对接后端接口生成

wen PHP项目 32

本文目录导读:

PHP项目AI绘图如何对接后端接口生成

  1. 主流AI绘图API提供商
  2. PHP后端对接示例(以Stable Diffusion为例)
  3. 异步任务处理(推荐方案)
  4. 前端请求示例
  5. 关键注意事项
  6. 完整API接口示例
  7. 部署建议

我来详细说明PHP项目对接AI绘图后端接口的完整流程:

主流AI绘图API提供商

服务商 接口类型 特点
Stable Diffusion 自建/API 开源可控,可本地部署
DALL-E 3 OpenAI API 质量高,费用较高
Midjourney Discord API 艺术风格好,需额外封装
百度文心一格 REST API 国内访问快

PHP后端对接示例(以Stable Diffusion为例)

1 发送绘图请求

<?php
class AIImageGenerator {
    private $apiUrl;
    private $apiKey;
    public function __construct($apiUrl, $apiKey = '') {
        $this->apiUrl = $apiUrl;
        $this->apiKey = $apiKey;
    }
    /**
     * 生成图像
     * @param string $prompt 描述文本
     * @param array $options 附加参数
     * @return array 返回结果
     */
    public function generate($prompt, $options = []) {
        $payload = array_merge([
            'prompt' => $prompt,
            'negative_prompt' => '',
            'width' => 512,
            'height' => 512,
            'steps' => 20,
            'cfg_scale' => 7,
            'batch_size' => 1
        ], $options);
        $ch = curl_init($this->apiUrl . '/sdapi/v1/txt2img');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->apiKey
            ],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 120, // 生成可能需要较长时间
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($httpCode !== 200) {
            throw new Exception("API请求失败: HTTP {$httpCode}");
        }
        return json_decode($response, true);
    }
}
// 使用示例
$generator = new AIImageGenerator('http://localhost:7860');
try {
    $result = $generator->generate('一只可爱的柴犬在草地上奔跑', [
        'width' => 1024,
        'height' => 1024,
        'steps' => 30
    ]);
    // 处理返回的base64图像数据
    $imageData = $result['images'][0];
    file_put_contents('generated_image.png', base64_decode($imageData));
    echo "图像生成成功!";
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}

2 使用OpenAI DALL-E 3

<?php
class DallEAPI {
    private $apiKey;
    public function __construct($apiKey) {
        $this->apiKey = $apiKey;
    }
    public function generateImage($prompt, $size = '1024x1024', $quality = 'standard') {
        $data = [
            'model' => 'dall-e-3',
            'prompt' => $prompt,
            'n' => 1,
            'size' => $size,
            'quality' => $quality
        ];
        $ch = curl_init('https://api.openai.com/v1/images/generations');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->apiKey
            ],
            CURLOPT_RETURNTRANSFER => true,
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($httpCode !== 200) {
            $error = json_decode($response, true);
            throw new Exception("API错误: " . ($error['error']['message'] ?? '未知错误'));
        }
        return json_decode($response, true);
    }
}
// 使用示例
$dalle = new DallEAPI('sk-your-api-key-here');
$result = $dalle->generateImage('Sunset over mountains, digital art style');
$imageUrl = $result['data'][0]['url'];
// 下载保存图像
$imageContent = file_get_contents($imageUrl);
file_put_contents('dalle_image.png', $imageContent);

异步任务处理(推荐方案)

<?php
// 异步绘图任务类
class AsyncImageGenerator {
    private $db;
    private $apiClient;
    public function __construct($db, $apiClient) {
        $this->db = $db;
        $this->apiClient = $apiClient;
    }
    /**
     * 创建绘图任务
     */
    public function createTask($prompt, $userId, $options = []) {
        $taskId = uniqid('img_', true);
        // 保存任务到数据库
        $stmt = $this->db->prepare("INSERT INTO image_tasks (task_id, user_id, prompt, options, status, created_at) 
                                   VALUES (?, ?, ?, ?, 'pending', NOW())");
        $stmt->execute([
            $taskId, 
            $userId, 
            $prompt, 
            json_encode($options)
        ]);
        // 将任务加入队列(使用Redis或消息队列)
        $this->addToQueue($taskId, [
            'prompt' => $prompt,
            'options' => $options
        ]);
        return $taskId;
    }
    /**
     * 检查任务状态
     */
    public function checkTask($taskId) {
        $stmt = $this->db->prepare("SELECT * FROM image_tasks WHERE task_id = ?");
        $stmt->execute([$taskId]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    /**
     * 处理队列中的任务(由Worker进程调用)
     */
    public function processQueue() {
        $task = $this->getNextTaskFromQueue();
        if (!$task) return;
        try {
            // 更新状态为处理中
            $this->updateTaskStatus($task['id'], 'processing');
            // 调用API生成图像
            $result = $this->apiClient->generate(
                $task['prompt'], 
                json_decode($task['options'], true)
            );
            // 保存图像到服务器
            $imagePath = $this->saveImage($result);
            // 更新任务状态为完成
            $this->updateTaskStatus($task['id'], 'completed', $imagePath);
        } catch (Exception $e) {
            // 标记为失败
            $this->updateTaskStatus($task['id'], 'failed', null, $e->getMessage());
        }
    }
    private function saveImage($result) {
        // 处理并保存图像
        $filename = uniqid() . '.png';
        $path = '/uploads/images/' . $filename;
        if (isset($result['images'][0])) {
            // base64格式
            file_put_contents($_SERVER['DOCUMENT_ROOT'] . $path, 
                             base64_decode($result['images'][0]));
        } elseif (isset($result['data'][0]['url'])) {
            // URL格式
            file_put_contents($_SERVER['DOCUMENT_ROOT'] . $path, 
                             file_get_contents($result['data'][0]['url']));
        }
        return $path;
    }
}

前端请求示例

// 前端JavaScript请求示例
async function generateImage() {
    const prompt = document.getElementById('prompt').value;
    const response = await fetch('/api/generate-image', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': 'your-csrf-token'
        },
        body: JSON.stringify({ prompt: prompt })
    });
    const result = await response.json();
    if (result.success) {
        // 轮询任务状态
        pollTaskStatus(result.task_id);
    }
}
// 轮询任务状态
async function pollTaskStatus(taskId) {
    const interval = setInterval(async () => {
        const response = await fetch(`/api/task-status/${taskId}`);
        const status = await response.json();
        if (status.status === 'completed') {
            clearInterval(interval);
            // 显示生成的图像
            displayImage(status.image_url);
        } else if (status.status === 'failed') {
            clearInterval(interval);
            showError(status.error_message);
        }
    }, 2000);
}

关键注意事项

1 错误处理

// 统一的错误处理中间件
class ImageAPIException extends Exception {
    public function __construct($message, $code = 400) {
        parent::__construct($message, $code);
    }
}
// 请求验证
function validatePrompt($prompt) {
    // 过滤敏感词
    $blockedWords = ['暴力', '色情', '敏感内容'];
    foreach ($blockedWords as $word) {
        if (strpos($prompt, $word) !== false) {
            throw new ImageAPIException('包含不允许的内容');
        }
    }
    // 长度限制
    if (strlen($prompt) > 1000) {
        throw new ImageAPIException('描述文本过长');
    }
}

2 性能优化

// 图像缓存
class ImageCache {
    private $cacheDir = '/tmp/image-cache/';
    public function getCached($prompt, $options) {
        $hash = md5($prompt . json_encode($options));
        $cacheFile = $this->cacheDir . $hash . '.png';
        if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 86400)) {
            return $cacheFile;
        }
        return null;
    }
    public function setCache($prompt, $options, $imageData) {
        $hash = md5($prompt . json_encode($options));
        file_put_contents($this->cacheDir . $hash . '.png', $imageData);
    }
}

完整API接口示例

// router.php
Route::post('/api/generate-image', function() {
    $input = json_decode(file_get_contents('php://input'), true);
    try {
        // 验证输入
        validatePrompt($input['prompt']);
        // 检查用户配额
        $quota = checkUserQuota($_SESSION['user_id']);
        if ($quota <= 0) {
            throw new ImageAPIException('今日生成次数已用完');
        }
        // 创建任务
        $generator = new AsyncImageGenerator($db, $apiClient);
        $taskId = $generator->createTask(
            $input['prompt'], 
            $_SESSION['user_id'],
            $input['options'] ?? []
        );
        // 扣减配额
        deductQuota($_SESSION['user_id']);
        return json_encode([
            'success' => true,
            'task_id' => $taskId,
            'message' => '任务已创建'
        ]);
    } catch (Exception $e) {
        http_response_code($e->getCode() ?: 400);
        return json_encode([
            'success' => false,
            'error' => $e->getMessage()
        ]);
    }
});

部署建议

  1. 本地部署Stable Diffusion:使用Automatic1111 WebUI API
  2. 生产环境:使用消息队列(Redis/RabbitMQ)处理异步任务
  3. 图像存储:建议使用云存储服务(OSS/S3)
  4. 费用控制:实现用户配额和速率限制
  5. 监控告警:记录API调用次数、成功率和响应时间

这样可以构建一个稳定、可扩展的AI绘图系统。

抱歉,评论功能暂时关闭!