阿里云AI接口接口

参考文章:https://cloud.tencent.com/developer/article/2550390

1.获取完成之后直接全部展示

php 复制代码
<?php

# 若没有配置环境变量,可用百炼API Key将下行替换为:$api_key="sk-xxx"。但不建议在生产环境中直接将API Key硬编码到代码中,以减少API Key泄露风险。
$api_key = "sk-290b2ab12318469b8571ef6352x012c1";
$application_id = '711dcbebd0d94354821e0032xaa2dx'; // 替换为实际的应用 ID

$url = "https://dashscope.aliyuncs.com/api/v1/apps/$application_id/completion";

// 构造请求数据
$data = [
    "input" => [
        'prompt' => '你是谁?'
    ]
];

// 将数据编码为 JSON
$dataString = json_encode($data);

// 检查 json_encode 是否成功
if (json_last_error() !== JSON_ERROR_NONE) {
    die("JSON encoding failed with error: " . json_last_error_msg());
}

// 初始化 cURL 对话
$ch = curl_init($url);

// 设置 cURL 选项
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $dataString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 在ai.php或相关文件中的curl请求前添加
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $api_key
]);

// 执行请求
$response = curl_exec($ch);

// 检查 cURL 执行是否成功
if ($response === false) {
    die("cURL Error: " . curl_error($ch));
}

// 获取 HTTP 状态码
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// 关闭 cURL 对话
curl_close($ch);
// 解码响应数据
$response_data = json_decode($response, true);
// 处理响应
if ($status_code == 200) {
    if (isset($response_data['output']['text'])) {
        echo "{$response_data['output']['text']}\n";
    } else {
        echo "No text in response.\n";
    }}
else {
    if (isset($response_data['request_id'])) {
        echo "request_id={$response_data['request_id']}\n";}
    echo "code={$status_code}\n";
    if (isset($response_data['message'])) {
        echo "message={$response_data['message']}\n";}
    else {
        echo "message=Unknown error\n";}
}
?>

2.SSE流式响应输出

php 复制代码
<?php
namespace app\controller;

use app\BaseController;
use think\facade\Log;

class APi extends BaseController
{
    // 统一API密钥(避免两处冗余配置)
    private $apiKey = 'xxx';
    private $baseUrl = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';



    /**
     * 流式对话方法(实际业务调用的核心方法)
     * @param string $prompt 用户输入的提示词
     * @param string $model 模型名称,默认 'qwen-plus'
     * @param callable $callback 流式响应的回调函数
     * @return array 最终结果
     */
    private function streamChat($prompt, $model = 'qwen-plus', $callback = null) {
        if (empty($prompt)) {
            throw new \Exception('请输入有效问题');
        }
        // 构建请求数据
        $data = [
            'model' => $model,
            'messages' => [
                ['role' => 'user', 'content' => $prompt]
            ],
            'stream' => true,
            'stream_options' => ['include_usage' => true]
        ];

        // 设置请求头
        $headers = [
            'Authorization: Bearer ' . $this->apiKey,
            'Content-Type: application/json; charset=utf-8' // 明确字符集,避免编码问题
        ];

        // 初始化curl
        $ch = curl_init();

        // 关键修复:统一禁用SSL验证(测试环境临时方案,生产环境请用CA证书)
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE), // 防止中文转义
            CURLOPT_WRITEFUNCTION => function($ch, $chunk) use ($callback) {
                $this->processStreamChunk($chunk, $callback);
                return strlen($chunk);
            },
            CURLOPT_TIMEOUT => 120, // 超时时间(秒)
            CURLOPT_SSL_VERIFYPEER => false, // 禁用服务器证书验证(核心修复点1)
            CURLOPT_SSL_VERIFYHOST => 0,     // 禁用主机名验证(核心修复点2,0为不验证)
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, // 强制HTTP/1.1,适配流式传输
            CURLOPT_CONNECTTIMEOUT => 30, // 连接超时,避免长时间等待
        ]);

        // 执行请求
        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            throw new \Exception('CURL Error: ' . curl_error($ch) . ' (错误码:' . curl_errno($ch) . ')');
        }

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            throw new \Exception('API Request Failed. HTTP Code: ' . $httpCode . ',响应内容:' . $response);
        }

        return [
            'success' => true,
            'message' => 'Stream completed'
        ];
    }

    /**
     * 处理流式响应的数据块
     */
    private function processStreamChunk($chunk, $callback) {
        if (empty($chunk)) return;
        // 按行分割数据(SSE格式,保留原始换行,避免trim丢失关键数据)
        $lines = explode("\n", $chunk);

        foreach ($lines as $line) {
            $line = trim($line);
            if (empty($line)) continue;

            // 解析SSE格式:data: {...}
            if (strpos($line, 'data: ') === 0) {
                $jsonStr = trim(substr($line, 6)); // 去掉 "data: " 并清理空格

                if ($jsonStr === '[DONE]') {
                    // 流式传输结束,触发done回调(核心修复:让前端感知结束)
                    if (is_callable($callback)) {
                        call_user_func($callback, [
                            'type' => 'done',
                            'message' => '传输完成'
                        ]);
                    }
                    continue;
                }

                try {
                    $data = json_decode($jsonStr, true);
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        Log::warning('JSON解析失败:' . json_last_error_msg() . ',原始数据:' . $jsonStr);
                        continue;
                    }
                    // 调用回调处理数据
                    if (is_callable($callback)) {
                        call_user_func($callback, $data);
                    } else {
                        $this->defaultStreamHandler($data);
                    }
                } catch (\Exception $e) {
                    Log::error('处理流式数据失败:' . $e->getMessage());
                    continue;
                }
            }
        }
    }

    /**
     * 默认的流式处理器
     */
    private function defaultStreamHandler($data) {
        if (isset($data['choices'][0]['delta']['content'])) {
            $content = $data['choices'][0]['delta']['content'];
            echo $content;
            flush();
        }
    }

    /**
     * SSE入口方法
     */
    public function index() {
        // 禁止ThinkPHP默认的输出缓冲(框架可能额外开启缓冲,导致SSE不实时)
        ob_end_clean();
        // 设置SSE响应头(必须在所有输出之前,包括框架的默认输出)
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache, no-store');
        header('Connection: keep-alive');
        header('X-Accel-Buffering: no'); // 禁用Nginx缓冲
        header('X-Cache: no-cache'); // 禁用CDN缓冲
        header('Access-Control-Allow-Origin: *'); // 允许跨域(前端调试需要可保留)
        ob_implicit_flush(1); // 开启隐式刷新,所有echo立即输出,无需重复调用flush()

        // 获取用户输入(过滤空值,避免无效请求)
        $question = trim($_GET['question'] ?? '');

        try {
            $this->streamChat($question, 'qwen-plus', function($data) {
                // 1. 处理流式内容(核心:AI实时返回的文字)
                if (isset($data['choices'][0]['delta']['content'])) {
                    $content = $data['choices'][0]['delta']['content'];
                    echo "event: update\n";
                    echo "data: " . json_encode(['content' => $content], JSON_UNESCAPED_UNICODE) . "\n\n";
                }
                // 2. 处理使用量统计(部分流式接口结束时返回)
                elseif (isset($data['usage'])) {
                    echo "event: usage\n";
                    echo "data: " . json_encode(['usage' => $data['usage']], JSON_UNESCAPED_UNICODE) . "\n\n";
                }
                // 3. 处理传输结束(核心修复:响应[DONE]标识,让前端停止监听)
                elseif (isset($data['type']) && $data['type'] === 'done') {
                    echo "event: end\n";
                    echo "data: " . json_encode(['message' => $data['message']], JSON_UNESCAPED_UNICODE) . "\n\n";
                }
                // 4. 处理其他异常数据(日志记录,不影响前端)
                else {
                    Log::info('未处理的流式数据:', $data);
                }
            });
        } catch (\Exception $e) {
            // 统一错误输出格式,前端可捕获error事件
            echo "event: error\n";
            echo "data: " . json_encode([
                    'message' => 'API调用失败: ' . $e->getMessage(),
                    'code' => -1
                ], JSON_UNESCAPED_UNICODE) . "\n\n";
            Log::error('SSE接口异常:' . $e->getMessage(), ['question' => $_GET['question'] ?? '']);
        }
        // 结束输出,避免后续框架输出干扰SSE
        exit;
    }

    /**
     * 备用AI流式接口(已修复重复SSL配置问题,与主方法统一密钥)
     */
    private function callAiStream(string $prompt, callable $callback)
    {
        if (empty($prompt)) {
            throw new \Exception('请输入有效提示词');
        }
        $application_id = '711dcbebd0d94354821e0032e9xxxd3';
        $url = "https://dashscope.aliyuncs.com/api/v1/apps/$application_id/completion";
        // 构造请求数据
        $data = [
            "input" => [
                'prompt' => $prompt
            ]
        ];
        $dataString = json_encode($data, JSON_UNESCAPED_UNICODE);

        $ch = curl_init();
        // 修复:统一在curl_setopt_array中设置所有配置,避免重复设置导致失效
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => false,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json; charset=utf-8',
                'Authorization: Bearer ' . $this->apiKey // 统一使用类的apiKey,避免冗余
            ],
            CURLOPT_POSTFIELDS => $dataString,
            CURLOPT_WRITEFUNCTION => function($ch, $data) use ($callback) {
                $callback($data);
                return strlen($data);
            },
            CURLOPT_TIMEOUT => 120,
            CURLOPT_CONNECTTIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false, // 禁用SSL验证
            CURLOPT_SSL_VERIFYHOST => 0,     // 禁用主机名验证
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        ]);

        curl_exec($ch);
        if (curl_errno($ch)) {
            throw new \Exception('CURL Error: ' . curl_error($ch) . ' (错误码:' . curl_errno($ch) . ')');
        }
        curl_close($ch);
    }

    /**
     * 解析AI响应数据
     */
    private function parseAiResponse(string $chunk): array
    {
        $result = ['content' => ''];
        if (empty($chunk)) return $result;

        $lines = explode("\n", $chunk);
        foreach ($lines as $line) {
            $line = trim($line);
            if (strpos($line, 'data: ') === 0) {
                $json = trim(substr($line, 6));
                if ($json === '[DONE]') break;

                $data = json_decode($json, true);
                if (json_last_error() === JSON_ERROR_NONE && isset($data['choices'][0]['delta']['content'])) {
                    $result['content'] .= $data['choices'][0]['delta']['content'];
                }
            }
        }
        return $result;
    }
}

前端页面

bash 复制代码
<template>
  <div>
    <input v-model="question" placeholder="输入问题...">
    <button @click="startStream">开始对话</button>

    <div id="output" v-html="output"></div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      question: '',
      output: '',
      eventSource: null
    }
  },
  methods: {
    startStream() {
      // 清空前一次输出
      this.output = '';

      // 关闭现有连接
      if (this.eventSource) this.eventSource.close();

      // 创建SSE连接
      this.eventSource = new EventSource(`/api/index?question=${encodeURIComponent(this.question)}`);

      // 监听消息事件
      this.eventSource.addEventListener('update', event => {
        const data = JSON.parse(event.data);
        this.output += data.content; // 增量更新内容
      });

      // 监听结束事件
      this.eventSource.addEventListener('end', () => {
        this.eventSource.close();
        console.log('流式传输结束');
      });

      // 错误处理
      this.eventSource.addEventListener('error', err => {

        console.error('SSE错误:', err);
        this.eventSource.close();
      });
    }
  },
  beforeUnmount() {
    // 组件卸载时关闭连接
    if (this.eventSource) this.eventSource.close();
  }
}
</script>
相关推荐
万博智云OneProCloud4 小时前
CloudEndure 退出中国市场之后,AWS 容灾该走向哪里?
云计算·aws
翼龙云_cloud5 小时前
亚马逊云渠道商:如何从本地环境安全访问AWS云数据库RDS?
数据库·云计算·aws
夜月蓝汐7 小时前
若依微服务版集成阿里云oss
java·阿里云·微服务
花间相见7 小时前
【阿里云】—— 云服务器 ECS搭建与使用
服务器·阿里云·云计算
希赛网7 小时前
26软考初级[信息系统运行管理员]考试核心:物联网、云计算运维
运维·网络·python·物联网·云计算·2026软考·信息系统运行管理员
天翼云开发者社区1 天前
上天翼云,一键开启你的AI助手“Moltbot”(原名Clawdbot)!
人工智能·云计算·ai助手·息壤
高校俱乐部1 天前
三步让阿里云配置好 clawdbot(moltbot)附上专属优惠
阿里云·云计算
maqiang_7201 天前
云计算 如何解决公司计算机性能不够用的问题
云计算
A-刘晨阳1 天前
Prometheus + Grafana + Alertmanager 实现邮件监控告警及配置告警信息
运维·云计算·grafana·prometheus·监控·邮件