Initial release v1.0.0
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import axios from "axios";
|
||||
import { PostProcessingProvider } from "./SettingsManager";
|
||||
|
||||
export interface ChatCompletionOptions {
|
||||
apiKey: string;
|
||||
model: string;
|
||||
endpoint?: string;
|
||||
provider?: "anthropic" | "openai" | "openrouter" | "custom";
|
||||
temperature?: number;
|
||||
maxTokens?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified AI service for all NibbleAI modules.
|
||||
* Supports OpenAI-compatible chat completions and Anthropic native API.
|
||||
*/
|
||||
export class AIService {
|
||||
/**
|
||||
* Call a chat completion API (OpenAI-compatible or Anthropic).
|
||||
* @param userMessage - The user's input text
|
||||
* @param systemPrompt - System-level instructions
|
||||
* @param options - API configuration
|
||||
* @returns The model's response text
|
||||
*/
|
||||
static async callChatCompletion(
|
||||
userMessage: string,
|
||||
systemPrompt: string,
|
||||
options: ChatCompletionOptions
|
||||
): Promise<string> {
|
||||
const provider = options.provider || "openai";
|
||||
const endpoint =
|
||||
options.endpoint || "https://openrouter.ai/api/v1/chat/completions";
|
||||
|
||||
if (provider === "anthropic") {
|
||||
return AIService.callAnthropic(userMessage, systemPrompt, options);
|
||||
}
|
||||
|
||||
return AIService.callOpenAI(userMessage, systemPrompt, {
|
||||
...options,
|
||||
endpoint,
|
||||
});
|
||||
}
|
||||
|
||||
private static async callOpenAI(
|
||||
userMessage: string,
|
||||
systemPrompt: string,
|
||||
options: ChatCompletionOptions
|
||||
): Promise<string> {
|
||||
const response = await axios.post(
|
||||
options.endpoint ||
|
||||
"https://openrouter.ai/api/v1/chat/completions",
|
||||
{
|
||||
model: options.model,
|
||||
messages: [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: userMessage },
|
||||
],
|
||||
temperature: options.temperature ?? 0.3,
|
||||
max_tokens: options.maxTokens ?? 2000,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${options.apiKey}`,
|
||||
"Content-Type": "application/json",
|
||||
...(options.endpoint?.includes("openrouter.ai")
|
||||
? {
|
||||
"HTTP-Referer": "https://obsidian.md",
|
||||
"X-Title": "Obsidian NibbleAI",
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
}
|
||||
);
|
||||
return response.data.choices[0].message.content.trim();
|
||||
}
|
||||
|
||||
private static async callAnthropic(
|
||||
userMessage: string,
|
||||
systemPrompt: string,
|
||||
options: ChatCompletionOptions
|
||||
): Promise<string> {
|
||||
const response = await axios.post(
|
||||
options.endpoint || "https://api.anthropic.com/v1/messages",
|
||||
{
|
||||
model: options.model,
|
||||
max_tokens: options.maxTokens ?? 8192,
|
||||
system: systemPrompt,
|
||||
messages: [{ role: "user", content: userMessage }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"x-api-key": options.apiKey,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"anthropic-dangerous-direct-browser-access": "true",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
return response.data.content[0].text;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user