Files
docmost/apps/client/src/ee/ai/services/ai-search-service.ts
T
Philip Okugbe 9fb16bc842 feat(EE): AI vector search (#1691)
* WIP

* AI module - init

* WIP

* sync

* WIP

* refactor naming

* new columns

* sync

* sync

* fix search bug

* stream response

* WIP

* feat embeddings sync

* refine

* Add workspaceId to page events

* refine

* WIP

* add translation string

* sync

* reset ai answer on query change

* hide AI search in cloud

* capture streaming error

* sync
2025-12-01 11:50:25 +00:00

80 lines
1.9 KiB
TypeScript

import api from "@/lib/api-client.ts";
import { IPageSearchParams } from "@/features/search/types/search.types.ts";
export interface IAiSearchResponse {
answer: string;
sources?: Array<{
pageId: string;
title: string;
slugId: string;
spaceSlug: string;
similarity: number;
distance: number;
chunkIndex: number;
excerpt: string;
}>;
}
export async function askAi(
params: IPageSearchParams,
onChunk?: (chunk: { content?: string; sources?: any[] }) => void,
): Promise<IAiSearchResponse> {
const response = await fetch("/api/ai/ask", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
credentials: "include",
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body?.getReader();
const decoder = new TextDecoder();
let answer = "";
let sources: any[] = [];
if (reader) {
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split("\n");
for (const line of lines) {
if (line.startsWith("data: ")) {
const data = line.slice(6);
if (data === "[DONE]") break;
try {
const parsed = JSON.parse(data);
if (parsed.error) {
throw new Error(parsed.error);
}
if (parsed.content) {
answer += parsed.content;
onChunk?.({ content: parsed.content });
}
if (parsed.sources) {
sources = parsed.sources;
onChunk?.({ sources: parsed.sources });
}
} catch (e) {
if (e instanceof Error) {
throw e;
}
// Skip invalid JSON
}
}
}
}
}
return { answer, sources };
}