| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- <?php
- namespace App\Servers\Aliyun;
- use \Exception;
- /**
- * 通义千问大模型API
- * 提供简单易用的接口调用阿里云百炼大模型平台
- * @author 唐远望
- * @version 1.0
- * @date 2025-12-22
- */
- class TongyiQianwen
- {
- private $apiKey;
- private $baseUrl = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';
- private $model = 'qwen-flash';
- private $timeout = 30;
- /**
- * 构造函数
- *
- * @param string $apiKey API密钥,如果不传则尝试从环境变量获取
- * @throws Exception 当API密钥未设置时抛出异常
- */
- public function __construct($apiKey = null)
- {
- if ($apiKey) {
- $this->apiKey = $apiKey;
- } else {
- $this->apiKey = config('aliyun.bailian_access_key', '');
- }
- if (empty($this->apiKey)) {
- throw new Exception('API密钥未设置,请通过构造函数传入或设置DASHSCOPE_API_KEY环境变量');
- }
- }
- /**
- * 设置模型
- *
- * @param string $model 模型名称
- * @return $this
- */
- public function setModel($model)
- {
- $this->model = $model;
- return $this;
- }
- /**
- * 设置请求超时时间
- *
- * @param int $timeout 超时时间(秒)
- * @return $this
- */
- public function setTimeout($timeout)
- {
- $this->timeout = $timeout;
- return $this;
- }
- /**
- * 发送消息并获取回复
- *
- * @param string|array $messages 消息内容,可以是字符串或消息数组
- * @param string $systemPrompt 系统提示词
- * @return array 包含响应数据和错误信息的数组
- */
- public function sendMessage($messages, $systemPrompt = "")
- {
- // 格式化消息
- $formattedMessages = $this->formatMessages($messages, $systemPrompt);
- // 准备请求数据
- $data = [
- "model" => $this->model,
- "messages" => $formattedMessages
- ];
- // 设置请求头
- $headers = [
- 'Authorization: Bearer ' . $this->apiKey,
- 'Content-Type: application/json'
- ];
- // 初始化cURL
- $ch = curl_init();
- curl_setopt_array($ch, [
- CURLOPT_URL => $this->baseUrl,
- CURLOPT_POST => true,
- CURLOPT_POSTFIELDS => json_encode($data),
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_TIMEOUT => $this->timeout,
- CURLOPT_SSL_VERIFYPEER => true,
- ]);
- // 执行请求
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- $error = curl_error($ch);
- curl_close($ch);
- // 处理响应
- if ($error) {
- return [
- 'success' => false,
- 'error' => 'CURL错误: ' . $error,
- 'data' => null
- ];
- }
- $decodedResponse = json_decode($response, true);
- if ($httpCode !== 200) {
- return [
- 'success' => false,
- 'error' => 'API请求失败,HTTP状态码: ' . $httpCode,
- 'data' => $decodedResponse
- ];
- }
- return [
- 'success' => true,
- 'error' => null,
- 'data' => $decodedResponse
- ];
- }
- /**
- * 格式化消息为API所需的格式
- *
- * @param string|array $messages 消息内容
- * @param string $systemPrompt 系统提示词
- * @return array 格式化后的消息数组
- */
- private function formatMessages($messages, $systemPrompt)
- {
- $formattedMessages = [];
- // 添加系统提示
- if (!empty($systemPrompt)) {
- $formattedMessages[] = [
- "role" => "system",
- "content" => $systemPrompt
- ];
- }
- // 处理不同类型的消息输入
- if (is_string($messages)) {
- // 单条用户消息
- $formattedMessages[] = [
- "role" => "user",
- "content" => $messages
- ];
- } elseif (is_array($messages)) {
- // 多条消息
- foreach ($messages as $message) {
- if (is_string($message)) {
- $formattedMessages[] = [
- "role" => "user",
- "content" => $message
- ];
- } elseif (is_array($message) && isset($message['role']) && isset($message['content'])) {
- $formattedMessages[] = $message;
- }
- }
- }
- return $formattedMessages;
- }
- /**
- * 从响应中提取助手的回复内容
- *
- * @param array $responseData sendMessage返回的数据
- * @return string|null 助手的回复内容,如果不存在则返回null
- */
- public function getAssistantReply($responseData)
- {
- if (!$responseData['success'] || !isset($responseData['data']['choices'][0]['message']['content'])) {
- return null;
- }
- return $responseData['data']['choices'][0]['message']['content'];
- }
- /**
- * 从响应中提取助手的回复消息ID
- *
- * @param array $responseData sendMessage返回的数据
- * @return string|null 助手的回复内容,如果不存在则返回null
- */
- public function getAssistantReplyId($responseData)
- {;
- if (!$responseData['success'] || !isset($responseData['data']['id'])) {
- return null;
- }
- return $responseData['data']['id'];
- }
- /**
- * 简化调用 - 发送消息并直接获取回复文本
- *
- * @param string $message 用户消息
- * @param string $systemPrompt 系统提示词
- * @return string 助手的回复内容,如果出错则返回错误信息
- */
- public function ask($message, $systemPrompt = "You are a helpful assistant.")
- {
- $response = $this->sendMessage($message, $systemPrompt);
- if (!$response['success']) {
- return "错误: " . $response['error'];
- }
- $reply = $this->getAssistantReply($response);
- return $reply ?: "未能获取到有效回复";
- }
- }
|