apiKey = (string) (AiConfig::getVal('embedding_api_key', '') ?: env('DASHSCOPE_API_KEY', '')); $this->baseUrl = (string) (AiConfig::getVal('embedding_base_url', '') ?: self::DASHSCOPE_BASE_URL); $this->model = (string) (AiConfig::getVal('embedding_model', '') ?: self::DASHSCOPE_EMBEDDING_MODEL); $this->defaultDim = (int) (AiConfig::getVal('embedding_dim', '') ?: '1024'); } /** * @param string|array $input */ public function embed($input, array $options = []): array { $apiKey = $options['api_key'] ?? $this->apiKey; $baseUrl = rtrim($options['base_url'] ?? $this->baseUrl, '/'); $model = $options['model'] ?? $this->model; if ($apiKey === '' || $baseUrl === '' || $model === '') { return [ 'success' => false, 'error' => 'Embedding API配置未完成', 'embeddings' => [], 'cost_ms' => 0, ]; } $payload = [ 'model' => $model, 'input' => $input, ]; if (!empty($options['dimensions'])) { $payload['dimensions'] = (int) $options['dimensions']; } elseif ($this->defaultDim > 0) { $payload['dimensions'] = $this->defaultDim; } $startTime = microtime(true); $ch = curl_init($baseUrl . '/v1/embeddings'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $apiKey, ], CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60, CURLOPT_SSL_VERIFYPEER => false, ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); $costMs = (int) ((microtime(true) - $startTime) * 1000); if ($error) { return [ 'success' => false, 'error' => 'Embedding cURL错误: ' . $error, 'embeddings' => [], 'cost_ms' => $costMs, ]; } $data = json_decode((string) $response, true); if ($httpCode !== 200 || empty($data['data']) || !is_array($data['data'])) { return [ 'success' => false, 'error' => $data['error']['message'] ?? ('HTTP ' . $httpCode), 'embeddings' => [], 'cost_ms' => $costMs, ]; } $embeddings = []; foreach ($data['data'] as $row) { $embedding = $row['embedding'] ?? []; if (is_array($embedding) && !empty($embedding)) { $embeddings[] = array_map('floatval', $embedding); } } return [ 'success' => !empty($embeddings), 'error' => !empty($embeddings) ? '' : 'Embedding结果为空', 'embeddings' => $embeddings, 'model' => $model, 'dimension' => count($embeddings[0] ?? []), 'tokens' => (int) ($data['usage']['total_tokens'] ?? 0), 'cost_ms' => $costMs, ]; } }