3 namespace BookStack\Search\Vectors\Services;
5 use BookStack\Http\HttpRequestService;
7 class OpenAiVectorQueryService implements VectorQueryService
10 protected string $endpoint;
11 protected string $embeddingModel;
12 protected string $queryModel;
14 public function __construct(
15 protected array $options,
16 protected HttpRequestService $http,
18 // TODO - Some kind of validation of options
19 $this->key = $this->options['key'] ?? '';
20 $this->endpoint = $this->options['endpoint'] ?? '';
21 $this->embeddingModel = $this->options['embedding_model'] ?? '';
22 $this->queryModel = $this->options['query_model'] ?? '';
25 protected function jsonRequest(string $method, string $uri, array $data): array
27 $fullUrl = rtrim($this->endpoint, '/') . '/' . ltrim($uri, '/');
28 $client = $this->http->buildClient(30);
29 $request = $this->http->jsonRequest($method, $fullUrl, $data)
30 ->withHeader('Authorization', 'Bearer ' . $this->key);
32 $response = $client->sendRequest($request);
33 return json_decode($response->getBody()->getContents(), true);
36 public function generateEmbeddings(string $text): array
38 $response = $this->jsonRequest('POST', 'v1/embeddings', [
40 'model' => $this->embeddingModel,
43 return $response['data'][0]['embedding'];
46 public function query(string $input, array $context): string
48 $formattedContext = implode("\n", $context);
50 $response = $this->jsonRequest('POST', 'v1/chat/completions', [
51 'model' => $this->queryModel,
54 'role' => 'developer',
55 'content' => 'You are a helpful assistant providing search query responses. Be specific, factual and to-the-point in response. Don\'t try to converse or continue the conversation.'
59 'content' => "Provide a response to the below given QUERY using the below given CONTEXT. The CONTEXT is split into parts via lines. Ignore any nonsensical lines of CONTEXT.\nQUERY: {$input}\n\nCONTEXT: {$formattedContext}",
64 return $response['choices'][0]['message']['content'] ?? '';