feat: add src/lib/ai/anthropic.ts

swadhinbiswas committed 8 months ago
39def2b
1 parent 6bea0e1
commit 39def2b
1 file changed
+73 -0
Showing 1 changed file+73-0
▼src/lib/ai/anthropic.ts
+73-0
1
+import type { AIAdapter, AICompletionResult, AIConfig, AIReviewPrompt } from "./types";
2
+import { logger } from "@/lib/logger";
3
+
4
+type AnthropicResponse = {
5
+ content?: Array<{ type: string; text?: string }>;
6
+ usage?: {
7
+ input_tokens?: number;
8
+ output_tokens?: number;
9
+ };
10
+};
11
+
12
+export class AnthropicAdapter implements AIAdapter {
13
+ async complete(prompt: AIReviewPrompt, config: AIConfig): Promise<AICompletionResult> {
14
+ const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
15
+ if (!apiKey) throw new Error("Anthropic API key not configured");
16
+
17
+ const model = config.model || "claude-3-5-sonnet-latest";
18
+ const maxTokens = config.maxTokens ?? 2048;
19
+
20
+ logger.info({ model, provider: "anthropic" }, "Calling Anthropic");
21
+
22
+ try {
23
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
24
+ method: "POST",
25
+ headers: {
26
+ "Content-Type": "application/json",
27
+ "x-api-key": apiKey,
28
+ "anthropic-version": "2023-06-01",
29
+ },
30
+ body: JSON.stringify({
31
+ model,
32
+ max_tokens: maxTokens,
33
+ temperature: config.temperature ?? 0.2,
34
+ system: prompt.system,
35
+ messages: [
36
+ {
37
+ role: "user",
38
+ content: prompt.user,
39
+ },
40
+ ],
41
+ }),
42
+ });
43
+
44
+ if (!response.ok) {
45
+ const errorText = await response.text();
46
+ throw new Error(`Anthropic API Error: ${response.status} - ${errorText}`);
47
+ }
48
+
49
+ const data = (await response.json()) as AnthropicResponse;
50
+ const content =
51
+ data.content
52
+ ?.filter((c) => c.type === "text" && c.text)
53
+ .map((c) => c.text)
54
+ .join("\n")
55
+ .trim() || "{}";
56
+
57
+ const inputTokens = data.usage?.input_tokens ?? 0;
58
+ const outputTokens = data.usage?.output_tokens ?? 0;
59
+
60
+ return {
61
+ content,
62
+ usage: {
63
+ inputTokens,
64
+ outputTokens,
65
+ totalTokens: inputTokens + outputTokens,
66
+ },
67
+ };
68
+ } catch (error: any) {
69
+ logger.error({ error: error.message }, "Anthropic Error");
70
+ throw error;
71
+ }
72
+ }
73
+}
0
74