From 9766782648617e232fbc4e40ea96a0e567c7cc73 Mon Sep 17 00:00:00 2001 From: polwex Date: Wed, 23 Jul 2025 05:41:58 +0700 Subject: something like that. man anthropic is old --- src/claude.ts | 104 +++++++++++++++++++++++++--------------------------------- 1 file changed, 45 insertions(+), 59 deletions(-) (limited to 'src/claude.ts') diff --git a/src/claude.ts b/src/claude.ts index 2a56bc1..629f9c2 100644 --- a/src/claude.ts +++ b/src/claude.ts @@ -1,26 +1,21 @@ import Claude from "@anthropic-ai/sdk"; import { RESPONSE_LENGTH } from "./logic/constants"; -import type { - AIModelAPI, - ChatMessage, - OChoice, - OChunk, - OMessage, -} from "./types"; +import type { AIModelAPI, ChatMessage } from "./types"; import { BOOKWORM_SYS } from "./prompts"; import type { AsyncRes } from "sortug"; +import type { MessageCreateParamsStreaming } from "@anthropic-ai/sdk/resources"; type Message = Claude.Messages.MessageParam; export default class ClaudeAPI implements AIModelAPI { - private model: string = "claude-3-7-sonnet-20250219"; + private model: string = "claude-opus-4-20250514"; tokenizer: (text: string) => number; maxTokens: number; // model: string = "claude-3-5-sonnet-20241022"; constructor( + model: string, maxTokens = 200_000, tokenizer: (text: string) => number = (text) => text.length / 3, - model?: string, ) { this.maxTokens = maxTokens; this.tokenizer = tokenizer; @@ -36,30 +31,17 @@ export default class ClaudeAPI implements AIModelAPI { }); } - private mapMessagesR1(input: ChatMessage[]): Message[] { - return input.reduce((acc: Message[], m, i) => { - const prev = acc[i - 1]; - const role: any = m.author === "claude" ? "assistant" : "user"; - const msg = { role, content: m.text }; - if (prev?.role === role) acc[i - 1] = msg; - else acc = [...acc, msg]; - return acc; - }, []); - } - - public async send(sys: string, input: ChatMessage[]) { - const messages = this.mapMessages(input); + public async send(input: string | ChatMessage[], sys?: string) { + const msgs: ChatMessage[] = + typeof input === "string" + ? [{ author: "user", text: input, sent: 0 }] + : input; + const messages = this.mapMessages(msgs); const truncated = this.truncateHistory(messages); - const res = await this.apiCall(sys, truncated); + const res = await this.apiCall(truncated, sys); return res; } - public async sendR1(input: ChatMessage[]) { - const messages = this.mapMessagesR1(input); - const truncated = this.truncateHistory(messages); - const res = await this.apiCall("", truncated, true); - return res; - } public async sendDoc(data: string) { const sys = BOOKWORM_SYS; const msg: Message = { @@ -75,24 +57,22 @@ export default class ClaudeAPI implements AIModelAPI { }, ], }; - const res = await this.apiCall(sys, [msg]); + const res = await this.apiCall([msg], sys); return res; } public async stream( - sys: string, - input: ChatMessage[], + input: string | ChatMessage[], handle: (c: any) => void, + sys?: string, ) { - const messages = this.mapMessages(input); + const msgs: ChatMessage[] = + typeof input === "string" + ? [{ author: "user", text: input, sent: 0 }] + : input; + const messages = this.mapMessages(msgs); const truncated = this.truncateHistory(messages); - await this.apiCallStream(sys, truncated, handle); - } - - public async streamR1(input: ChatMessage[], handle: (c: any) => void) { - const messages = this.mapMessagesR1(input); - const truncated = this.truncateHistory(messages); - await this.apiCallStream("", truncated, handle, true); + await this.apiCallStream(truncated, handle, sys); } private truncateHistory(messages: Message[]): Message[] { @@ -108,26 +88,30 @@ export default class ClaudeAPI implements AIModelAPI { // TODO // https://docs.anthropic.com/en/api/messages-examples#putting-words-in-claudes-mouth private async apiCall( - system: string, messages: Message[], - isR1: boolean = false, - ): Promise> { + system?: string, + ): Promise> { try { const claud = new Claude(); - // const list = await claud.models.list(); - // console.log(list.data); - const res = await claud.messages.create({ + const params = { model: this.model, max_tokens: RESPONSE_LENGTH, - system, messages, - }); - return { - ok: res.content.reduce((acc: string[], item) => { - if (item.type === "tool_use") return acc; - else return [...acc, item.text]; - }, []), }; + const res = await claud.messages.create( + system ? { ...params, system } : params, + ); + const resm: string = res.content.reduce((acc: string, item) => { + if (item.type === "tool_use") return acc; + else if (item.type === "text") return `${acc}\n${item.text}`; + else return acc; + }, ""); + // const resm = res.content.reduce((acc: string[], item) => { + // if (item.type === "tool_use") return acc; + // else if (item.type === "text") return [...acc, item.text] + // else return acc; + // }, []); + return { ok: resm }; } catch (e) { console.log(e, "error in claude api"); return { error: `${e}` }; @@ -135,20 +119,22 @@ export default class ClaudeAPI implements AIModelAPI { } private async apiCallStream( - system: string, messages: Message[], handle: (c: any) => void, - isR1: boolean = false, + system?: string, ): Promise { try { const claud = new Claude(); - const stream = await claud.messages.create({ + const params = { model: this.model, max_tokens: RESPONSE_LENGTH, - system, messages, - stream: true, - }); + stream: true as true, + }; + const fparams: MessageCreateParamsStreaming = system + ? { ...params, system } + : params; + const stream = await claud.messages.create(fparams); for await (const part of stream) { if (part.type === "message_start") continue; -- cgit v1.2.3