| 113 | } |
| 114 | |
| 115 | async function callOpenAIEmbed(input: string[], signal: AbortSignal): Promise<number[][]> { |
| 116 | const url = `${OPENAI_BASE_URL.replace(/\/+$/, "")}/embeddings`; |
| 117 | const response = await fetch(url, { |
| 118 | method: "POST", |
| 119 | headers: { |
| 120 | "Content-Type": "application/json", |
| 121 | "Authorization": `Bearer ${OPENAI_API_KEY}`, |
| 122 | }, |
| 123 | body: JSON.stringify({ model: OPENAI_EMBED_MODEL, input }), |
| 124 | signal, |
| 125 | }); |
| 126 | |
| 127 | if (!response.ok) { |
| 128 | const body = await response.text().catch(() => ""); |
| 129 | throw new Error(`OpenAI embed API error ${response.status}: ${body}`); |
| 130 | } |
| 131 | |
| 132 | const data = await response.json() as { data: { embedding: number[] }[] }; |
| 133 | return data.data.map((item) => item.embedding); |
| 134 | } |
| 135 | |
| 136 | async function callProviderEmbed(input: string[], signal: AbortSignal): Promise<number[][]> { |
| 137 | if (EMBED_PROVIDER === "openai") { |