From 5ff2ee1c8500cd3c21674c2b5760235d05f2ae02 Mon Sep 17 00:00:00 2001 From: tbxark Date: Thu, 31 Oct 2024 15:22:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix=EF=BC=9A#299Cohere=20=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=8A=A5=E9=94=99=EF=BC=8C=E5=8D=87=E7=BA=A7=E5=85=BC=E5=AE=B9?= =?UTF-8?q?Cohere=20v2=20API=20=EF=BC=88=E6=94=BE=E5=BC=83=E6=94=AF?= =?UTF-8?q?=E6=8C=81V1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/buildinfo.json | 2 +- dist/index.js | 39 +++++++++++++++------------------------ dist/timestamp | 2 +- package.json | 2 +- src/agent/cohere.ts | 36 ++++++++++-------------------------- src/agent/index.test.ts | 2 +- src/agent/stream.ts | 2 +- src/config/config.ts | 2 +- 8 files changed, 31 insertions(+), 56 deletions(-) diff --git a/dist/buildinfo.json b/dist/buildinfo.json index 89851f0f..71cd819b 100644 --- a/dist/buildinfo.json +++ b/dist/buildinfo.json @@ -1 +1 @@ -{"sha":"2e649eb","timestamp":1730180242} \ No newline at end of file +{"sha":"7866d81","timestamp":1730359222} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index c45b9ef7..a58b054f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -106,7 +106,7 @@ class MistralConfig { } class CohereConfig { COHERE_API_KEY = null; - COHERE_API_BASE = "https://api.cohere.com/v1"; + COHERE_API_BASE = "https://api.cohere.com/v2"; COHERE_CHAT_MODEL = "command-r-plus"; } class AnthropicConfig { @@ -211,8 +211,8 @@ const ENV_KEY_MAPPER = { WORKERS_AI_MODEL: "WORKERS_CHAT_MODEL" }; class Environment extends EnvironmentConfig { - BUILD_TIMESTAMP = 1730180242 ; - BUILD_VERSION = "2e649eb" ; + BUILD_TIMESTAMP = 1730359222 ; + BUILD_VERSION = "7866d81" ; I18N = loadI18n(); PLUGINS_ENV = {}; USER_CONFIG = createAgentUserConfig(); @@ -958,7 +958,7 @@ function defaultSSEJsonParser(sse) { if (sse.data?.startsWith("[DONE]")) { return { finish: true }; } - if (sse.event === null && sse.data) { + if (sse.data) { try { return { data: JSON.parse(sse.data) }; } catch (e) { @@ -1417,10 +1417,6 @@ class AzureImageAI extends AzureBase { class Cohere { name = "cohere"; modelKey = "COHERE_CHAT_MODEL"; - static COHERE_ROLE_MAP = { - assistant: "CHATBOT", - user: "USER" - }; enable = (context) => { return !!context.COHERE_API_KEY; }; @@ -1429,13 +1425,13 @@ class Cohere { }; render = (item) => { return { - role: Cohere.COHERE_ROLE_MAP[item.role] || "USER", - content: item.content + role: item.role, + message: item.content }; }; static parser(sse) { switch (sse.event) { - case "text-generation": + case "content-delta": try { return { data: JSON.parse(sse.data || "") }; } catch (e) { @@ -1444,7 +1440,7 @@ class Cohere { } case "stream-start": return {}; - case "stream-end": + case "[DONE]": return { finish: true }; default: return {}; @@ -1459,25 +1455,20 @@ class Cohere { "Accept": onStream !== null ? "text/event-stream" : "application/json" }; const messages = [...history || [], { role: "user", content: message }]; + if (prompt) { + messages.unshift({ role: "assistant", content: prompt }); + } const body = { - message, + messages, model: context.COHERE_CHAT_MODEL, - stream: onStream != null, - preamble: prompt, - chat_history: messages.map(this.render) + stream: onStream != null }; - if (!body.preamble) { - delete body.preamble; - } const options = {}; - options.streamBuilder = function(r, c) { - return new Stream(r, c, Cohere.parser); - }; options.contentExtractor = function(data) { - return data?.text; + return data?.delta?.message?.content?.text; }; options.fullContentExtractor = function(data) { - return data?.text; + return data?.messages[0].content; }; options.errorExtractor = function(data) { return data?.message; diff --git a/dist/timestamp b/dist/timestamp index 31e68c49..d80b7055 100644 --- a/dist/timestamp +++ b/dist/timestamp @@ -1 +1 @@ -1730180242 \ No newline at end of file +1730359222 \ No newline at end of file diff --git a/package.json b/package.json index 138c319d..012f4cd0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "start:debug": "wrangler dev --local", "prepare:vercel": "tsx ./scripts/plugins/vercel/setenv.ts", "wrangler": "wrangler", - "test": "tsx ./src/config/env.test.ts" + "test": "tsx ./src/agent/index.test.ts" }, "dependencies": { "cloudflare-worker-adapter": "^1.3.3" diff --git a/src/agent/cohere.ts b/src/agent/cohere.ts index b2bddb1a..62647d17 100644 --- a/src/agent/cohere.ts +++ b/src/agent/cohere.ts @@ -9,11 +9,6 @@ export class Cohere implements ChatAgent { readonly name = 'cohere'; readonly modelKey = 'COHERE_CHAT_MODEL'; - static COHERE_ROLE_MAP: Record = { - assistant: 'CHATBOT', - user: 'USER', - }; - readonly enable = (context: AgentUserConfig): boolean => { return !!(context.COHERE_API_KEY); }; @@ -24,20 +19,14 @@ export class Cohere implements ChatAgent { private render = (item: HistoryItem): any => { return { - role: Cohere.COHERE_ROLE_MAP[item.role] || 'USER', - content: item.content, + role: item.role, + message: item.content, }; }; static parser(sse: SSEMessage): SSEParserResult { - // example: - // event: text-generation - // data: {"is_finished":false,"event_type":"text-generation","text":"?"} - // - // event: stream-end - // data: {"is_finished":true,...} switch (sse.event) { - case 'text-generation': + case 'content-delta': try { return { data: JSON.parse(sse.data || '') }; } catch (e) { @@ -46,7 +35,7 @@ export class Cohere implements ChatAgent { } case 'stream-start': return {}; - case 'stream-end': + case '[DONE]': return { finish: true }; default: return {}; @@ -63,27 +52,22 @@ export class Cohere implements ChatAgent { }; const messages = [...history || [], { role: 'user', content: message }]; + if (prompt) { + messages.unshift({ role: 'assistant', content: prompt }); + } const body = { - message, + messages, model: context.COHERE_CHAT_MODEL, stream: onStream != null, - preamble: prompt, - chat_history: messages.map(this.render), }; - if (!body.preamble) { - delete body.preamble; - } const options: SseChatCompatibleOptions = {}; - options.streamBuilder = function (r, c) { - return new Stream(r, c, Cohere.parser); - }; options.contentExtractor = function (data: any) { - return data?.text; + return data?.delta?.message?.content?.text; }; options.fullContentExtractor = function (data: any) { - return data?.text; + return data?.messages[0].content; }; options.errorExtractor = function (data: any) { return data?.message; diff --git a/src/agent/index.test.ts b/src/agent/index.test.ts index 4ed2d6b2..ffe7724f 100644 --- a/src/agent/index.test.ts +++ b/src/agent/index.test.ts @@ -6,7 +6,7 @@ import '../config/env.test'; { const agent = loadChatLLM({ ...ENV.USER_CONFIG, - AI_PROVIDER: 'anthropic', + AI_PROVIDER: 'cohere', }); const params: LLMChatParams = { prompt: 'You are a useful assistant.', diff --git a/src/agent/stream.ts b/src/agent/stream.ts index fd75a92a..43ccce66 100644 --- a/src/agent/stream.ts +++ b/src/agent/stream.ts @@ -138,7 +138,7 @@ function defaultSSEJsonParser(sse: SSEMessage): SSEParserResult { if (sse.data?.startsWith('[DONE]')) { return { finish: true }; } - if (sse.event === null && sse.data) { + if (sse.data) { try { return { data: JSON.parse(sse.data) }; } catch (e) { diff --git a/src/config/config.ts b/src/config/config.ts index 7fc98f10..041f7d63 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -169,7 +169,7 @@ export class CohereConfig { // cohere api key COHERE_API_KEY: string | null = null; // cohere api base - COHERE_API_BASE = 'https://api.cohere.com/v1'; + COHERE_API_BASE = 'https://api.cohere.com/v2'; // cohere api model COHERE_CHAT_MODEL = 'command-r-plus'; } From 62b81475633bdef970031ac3bf40777582f9120a Mon Sep 17 00:00:00 2001 From: tbxark Date: Thu, 31 Oct 2024 15:25:31 +0800 Subject: [PATCH 2/2] build: support cohere v2 api --- dist/buildinfo.json | 2 +- dist/index.js | 27 ++------------------------- dist/timestamp | 2 +- src/agent/cohere.ts | 29 +---------------------------- 4 files changed, 5 insertions(+), 55 deletions(-) diff --git a/dist/buildinfo.json b/dist/buildinfo.json index 71cd819b..8dd6e4dd 100644 --- a/dist/buildinfo.json +++ b/dist/buildinfo.json @@ -1 +1 @@ -{"sha":"7866d81","timestamp":1730359222} \ No newline at end of file +{"sha":"5ff2ee1","timestamp":1730359461} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index a58b054f..f6cea018 100644 --- a/dist/index.js +++ b/dist/index.js @@ -211,8 +211,8 @@ const ENV_KEY_MAPPER = { WORKERS_AI_MODEL: "WORKERS_CHAT_MODEL" }; class Environment extends EnvironmentConfig { - BUILD_TIMESTAMP = 1730359222 ; - BUILD_VERSION = "7866d81" ; + BUILD_TIMESTAMP = 1730359461 ; + BUILD_VERSION = "5ff2ee1" ; I18N = loadI18n(); PLUGINS_ENV = {}; USER_CONFIG = createAgentUserConfig(); @@ -1423,29 +1423,6 @@ class Cohere { model = (ctx) => { return ctx.COHERE_CHAT_MODEL; }; - render = (item) => { - return { - role: item.role, - message: item.content - }; - }; - static parser(sse) { - switch (sse.event) { - case "content-delta": - try { - return { data: JSON.parse(sse.data || "") }; - } catch (e) { - console.error(e, sse.data); - return {}; - } - case "stream-start": - return {}; - case "[DONE]": - return { finish: true }; - default: - return {}; - } - } request = async (params, context, onStream) => { const { message, prompt, history } = params; const url = `${context.COHERE_API_BASE}/chat`; diff --git a/dist/timestamp b/dist/timestamp index d80b7055..ff5f01a3 100644 --- a/dist/timestamp +++ b/dist/timestamp @@ -1 +1 @@ -1730359222 \ No newline at end of file +1730359461 \ No newline at end of file diff --git a/src/agent/cohere.ts b/src/agent/cohere.ts index 62647d17..3085c971 100644 --- a/src/agent/cohere.ts +++ b/src/agent/cohere.ts @@ -1,9 +1,7 @@ import type { AgentUserConfig } from '../config/env'; import type { SseChatCompatibleOptions } from './request'; -import type { SSEMessage, SSEParserResult } from './stream'; -import type { ChatAgent, ChatStreamTextHandler, HistoryItem, LLMChatParams } from './types'; +import type { ChatAgent, ChatStreamTextHandler, LLMChatParams } from './types'; import { requestChatCompletions } from './request'; -import { Stream } from './stream'; export class Cohere implements ChatAgent { readonly name = 'cohere'; @@ -17,31 +15,6 @@ export class Cohere implements ChatAgent { return ctx.COHERE_CHAT_MODEL; }; - private render = (item: HistoryItem): any => { - return { - role: item.role, - message: item.content, - }; - }; - - static parser(sse: SSEMessage): SSEParserResult { - switch (sse.event) { - case 'content-delta': - try { - return { data: JSON.parse(sse.data || '') }; - } catch (e) { - console.error(e, sse.data); - return {}; - } - case 'stream-start': - return {}; - case '[DONE]': - return { finish: true }; - default: - return {}; - } - } - readonly request = async (params: LLMChatParams, context: AgentUserConfig, onStream: ChatStreamTextHandler | null): Promise => { const { message, prompt, history } = params; const url = `${context.COHERE_API_BASE}/chat`;