@@ -0,0 +1,70 @@
|
||||
import type { ChatMessage, RequestAIParams } from "./types"
|
||||
|
||||
/**
|
||||
* Generic, reusable OpenAI-compatible chat completion request.
|
||||
* Not coupled to any specific business logic.
|
||||
*/
|
||||
export async function requestOpenAICompatible(params: RequestAIParams): Promise<string> {
|
||||
const {
|
||||
baseUrl,
|
||||
apiKey,
|
||||
model,
|
||||
systemPrompt,
|
||||
customPrompt,
|
||||
messages,
|
||||
temperature = 0.3,
|
||||
maxTokens = 4000,
|
||||
stream = false,
|
||||
signal,
|
||||
} = params
|
||||
|
||||
const finalMessages: ChatMessage[] = []
|
||||
|
||||
if (systemPrompt) {
|
||||
finalMessages.push({ role: "system", content: systemPrompt })
|
||||
}
|
||||
|
||||
if (customPrompt) {
|
||||
finalMessages.push({ role: "user", content: customPrompt })
|
||||
}
|
||||
|
||||
finalMessages.push(...messages)
|
||||
|
||||
const url = `${baseUrl.replace(/\/$/, "")}/chat/completions`
|
||||
|
||||
let response: Response
|
||||
try {
|
||||
response = await fetch(url, {
|
||||
method: "POST",
|
||||
signal,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model,
|
||||
messages: finalMessages,
|
||||
temperature,
|
||||
max_tokens: maxTokens,
|
||||
stream,
|
||||
}),
|
||||
})
|
||||
} catch (err) {
|
||||
if (err instanceof DOMException && err.name === "AbortError") throw err
|
||||
throw new Error(`无法连接到 AI 服务:${(err as Error).message}`)
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text().catch(() => "")
|
||||
throw new Error(`AI 请求失败:${response.status} ${errorText}`)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
const content = data?.choices?.[0]?.message?.content
|
||||
|
||||
if (!content) {
|
||||
throw new Error("AI 没有返回有效内容")
|
||||
}
|
||||
|
||||
return content as string
|
||||
}
|
||||
Reference in New Issue
Block a user