visuddhinanda пре 4 месеци
родитељ
комит
38310dc889
1 измењених фајлова са 104 додато и 6 уклоњено
  1. 104 6
      api-v8/app/Services/EmbeddingService.php

+ 104 - 6
api-v8/app/Services/EmbeddingService.php

@@ -2,17 +2,115 @@
 
 namespace App\Services;
 
-use Symfony\Component\Process\Process;
+use Illuminate\Support\Facades\Http;
+use App\Services\AIModelService;
 
 class EmbeddingService
 {
+    protected string $modelId;
+    protected string $apiUrl = '';
+    protected int $maxRetries = 3;
+
+    /**
+     * 创建服务实例,初始化 OpenAI API Key
+     *
+     * @return void
+     */
+    public function __construct(AIModelService $aiModels)
+    {
+        $models = $aiModels->getSysModels('embedding');
+        $this->modelId = $models[0]['uid'];
+        $this->apiUrl = config('mint.ai.proxy') . '/api/openai';
+    }
+
     public function generate($text)
     {
-        $process = new Process(['python3', 'scripts/generate_embedding.py', $text]);
-        $process->run();
-        if (!$process->isSuccessful()) {
-            throw new \Exception('Embedding generation failed');
+        return $this->callOpenAI($text);
+    }
+
+    /**
+     * 调用 OpenAI GPT 模型生成embedding
+     *
+     * {
+  "object": "list",
+  "data": [
+    {
+      "object": "embedding",
+      "index": 0,
+      "embedding": [
+        -0.012345,
+        0.021876,
+        0.004231,
+        -0.037654,
+        0.016482,
+        -0.001273,
+        0.029871,
+        -0.015630
+        // ... 共1536个浮点数
+      ]
+    }
+  ],
+  "model": "text-embedding-3-small",
+  "usage": {
+    "prompt_tokens": 16,
+    "total_tokens": 16
+  }
+}
+
+     *
+     * 带有重试机制和指数退避。
+     * 在 429 或 500+ 错误时重试,最大重试次数为 maxRetries。
+     * 其他错误直接返回空字符串。
+     *
+     * @param  string  $text       输入文本
+     * @param  int     $maxTokens  每次请求允许的最大 tokens 数
+     * @return string              模型返回的摘要文本
+     */
+    protected function callOpenAI(string $text): string
+    {
+        $attempt = 0;
+        $delay = 1;
+
+        $payload = [
+            'model' => $this->modelId,
+            'input' => $text,
+        ];
+        while ($attempt < $this->maxRetries) {
+            try {
+                $response = Http::timeout(100)
+                    ->withHeaders([
+                        'Authorization' => 'Bearer ',
+                        'Content-Type' => 'application/json',
+                    ])->post($this->apiUrl, [
+                        'model_id' => $this->modelId,
+                        'payload' => $payload
+                    ]);
+
+                if ($response->successful()) {
+                    $data = $response->json();
+                    if (isset($data['data']['embedding'])) {
+                        return $data['data']['embedding'];
+                    } else {
+                        return false;
+                    }
+                }
+
+                if (in_array($response->status(), [429, 500, 502, 503, 504])) {
+                    throw new \Exception("Temporary server error: " . $response->status());
+                }
+
+                return false;
+            } catch (\Exception $e) {
+                $attempt++;
+                if ($attempt >= $this->maxRetries) {
+                    return false;
+                }
+
+                sleep($delay);
+                $delay *= 10;
+            }
         }
-        return json_decode($process->getOutput(), true);
+
+        return false;
     }
 }