-
Notifications
You must be signed in to change notification settings - Fork 956
/
Anthropic.ts
107 lines (98 loc) · 2.92 KB
/
Anthropic.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {
ChatMessage,
CompletionOptions,
LLMOptions,
ModelProvider,
} from "../../index.js";
import { stripImages } from "../countTokens.js";
import { BaseLLM } from "../index.js";
import { streamSse } from "../stream.js";
class Anthropic extends BaseLLM {
static providerName: ModelProvider = "anthropic";
static defaultOptions: Partial<LLMOptions> = {
model: "claude-3-5-sonnet-20240620",
contextLength: 200_000,
completionOptions: {
model: "claude-3-5-sonnet-20240620",
maxTokens: 4096,
},
apiBase: "https://api.anthropic.com/v1/",
};
private _convertArgs(options: CompletionOptions) {
const finalOptions = {
top_k: options.topK,
top_p: options.topP,
temperature: options.temperature,
max_tokens: options.maxTokens ?? 2048,
model: options.model === "claude-2" ? "claude-2.1" : options.model,
stop_sequences: options.stop?.filter((x) => x.trim() !== ""),
stream: options.stream ?? true,
};
return finalOptions;
}
private _convertMessages(msgs: ChatMessage[]): any[] {
const messages = msgs
.filter((m) => m.role !== "system")
.map((message) => {
if (typeof message.content === "string") {
return message;
}
return {
...message,
content: message.content.map((part) => {
if (part.type === "text") {
return part;
}
return {
type: "image",
source: {
type: "base64",
media_type: "image/jpeg",
data: part.imageUrl?.url.split(",")[1],
},
};
}),
};
});
return messages;
}
protected async *_streamComplete(
prompt: string,
options: CompletionOptions,
): AsyncGenerator<string> {
const messages = [{ role: "user" as const, content: prompt }];
for await (const update of this._streamChat(messages, options)) {
yield stripImages(update.content);
}
}
protected async *_streamChat(
messages: ChatMessage[],
options: CompletionOptions,
): AsyncGenerator<ChatMessage> {
const response = await this.fetch(new URL("messages", this.apiBase), {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"anthropic-version": "2023-06-01",
"x-api-key": this.apiKey as string,
},
body: JSON.stringify({
...this._convertArgs(options),
messages: this._convertMessages(messages),
system: this.systemMessage,
}),
});
if (options.stream === false) {
const data = await response.json();
yield { role: "assistant", content: data.content[0].text };
return;
}
for await (const value of streamSse(response)) {
if (value.delta?.text) {
yield { role: "assistant", content: value.delta.text };
}
}
}
}
export default Anthropic;