diff --git a/bun.config.mjs b/bun.config.mjs index 7b1d84a..b4a900d 100644 --- a/bun.config.mjs +++ b/bun.config.mjs @@ -17,9 +17,29 @@ await Bun.build({ define: { ENVISION_VERSION: JSON.stringify(pkg.version), + IS_BROWSER: JSON.stringify(false), }, env: 'ENVISION_*', }); const cmd = 'dts -i src/provider/index.ts -o ai-provider.d.ts'; execSync(cmd, { stdio: 'inherit' }); +execSync('cp dist/ai-provider.d.ts dist/ai-provider-browser.d.ts', { stdio: 'inherit' }); + +// bun run src/index.ts -- +await Bun.build({ + target: 'browser', + format: 'esm', + entrypoints: [resolvePath('./src/provider/index.ts')], + outdir: resolvePath('./dist'), + naming: { + entry: 'ai-provider-browser.js', + }, + + define: { + ENVISION_VERSION: JSON.stringify(pkg.version), + IS_BROWSER: JSON.stringify(true), + }, + env: 'ENVISION_*', +}); + diff --git a/package.json b/package.json index 8011c97..125cf10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/ai", - "version": "0.0.5", + "version": "0.0.8", "description": "后面需要把ai-center的provider模块提取出去", "main": "index.js", "basename": "/root/ai-center-services", @@ -11,6 +11,7 @@ }, "files": [ "dist", + "src", "types" ], "scripts": { @@ -20,7 +21,11 @@ "clean": "rm -rf dist", "pub": "envision pack -p -u" }, - "keywords": [], + "keywords": [ + "kevisual", + "ai", + "tools" + ], "author": "abearxiong (https://www.xiongxiao.me)", "license": "MIT", "packageManager": "pnpm@10.11.0", @@ -32,11 +37,20 @@ "exports": { ".": { "import": "./dist/ai-provider.js", + "node": "./dist/ai-provider.js", + "browser": "./dist/ai-provider-browser.js", "types": "./dist/ai-provider.d.ts" }, "./ai-provider": { "import": "./dist/ai-provider.js", "types": "./dist/ai-provider.d.ts" + }, + "./browser": { + "import": "./dist/ai-provider-browser.js", + "types": "./dist/ai-provider-browser.d.ts" + }, + "./src/**/*": { + "import": "./src/**/*" } }, "devDependencies": { diff --git a/src/provider/chat-adapter/dashscope.ts b/src/provider/chat-adapter/dashscope.ts new file mode 100644 index 0000000..83534ac --- /dev/null +++ b/src/provider/chat-adapter/dashscope.ts @@ -0,0 +1,10 @@ +import { BaseChat, BaseChatOptions } from '../core/chat.ts'; + +export type BailianOptions = Partial; +export class BailianChat extends BaseChat { + static BASE_URL = 'https://bailian.aliyuncs.com/compatible-mode/v1/'; + constructor(options: BailianOptions) { + const baseURL = options.baseURL || BailianChat.BASE_URL; + super({ ...(options as BaseChatOptions), baseURL: baseURL }); + } +} diff --git a/src/provider/chat.ts b/src/provider/chat.ts index 040a420..aa6d5aa 100644 --- a/src/provider/chat.ts +++ b/src/provider/chat.ts @@ -7,6 +7,8 @@ import { Custom } from './chat-adapter/custom.ts'; import { Volces } from './chat-adapter/volces.ts'; import { DeepSeek } from './chat-adapter/deepseek.ts'; import { ModelScope } from './chat-adapter/model-scope.ts'; +import { BailianChat } from './chat-adapter/dashscope.ts'; + import { ChatMessage } from './core/type.ts'; export const OllamaProvider = Ollama; @@ -15,6 +17,7 @@ export const CustomProvider = Custom; export const VolcesProvider = Volces; export const DeepSeekProvider = DeepSeek; export const ModelScopeProvider = ModelScope; +export const BailianProvider = BailianChat; export const ChatProviderMap = { Ollama: OllamaProvider, @@ -24,6 +27,7 @@ export const ChatProviderMap = { DeepSeek: DeepSeekProvider, ModelScope: ModelScopeProvider, BaseChat: BaseChat, + Bailian: BailianProvider, }; type ProviderManagerConfig = { diff --git a/src/provider/core/chat.ts b/src/provider/core/chat.ts index 38a3f5f..181ac4f 100644 --- a/src/provider/core/chat.ts +++ b/src/provider/core/chat.ts @@ -14,7 +14,7 @@ export type BaseChatOptions> = { /** * 默认baseURL */ - baseURL: string; + baseURL?: string; /** * 默认模型 */ @@ -32,7 +32,14 @@ export type BaseChatOptions> = { */ stream?: boolean; } & T; - +export const getIsBrowser = () => { + try { + // @ts-ignore + return IS_BROWSER; + } catch (e) { + return false; + } +}; export class BaseChat implements BaseChatInterface, BaseChatUsageInterface { /** * 默认baseURL @@ -63,7 +70,9 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface { this.baseURL = options.baseURL; this.model = options.model; this.apiKey = options.apiKey; - this.isBrowser = options.isBrowser ?? false; + // @ts-ignore + const DEFAULT_IS_BROWSER = getIsBrowser(); + this.isBrowser = options.isBrowser ?? DEFAULT_IS_BROWSER; this.openai = new OpenAI({ apiKey: this.apiKey, baseURL: this.baseURL, diff --git a/src/provider/core/type.ts b/src/provider/core/type.ts index f4136a1..9aad67f 100644 --- a/src/provider/core/type.ts +++ b/src/provider/core/type.ts @@ -1,7 +1,13 @@ import OpenAI from 'openai'; export type ChatMessage = OpenAI.Chat.Completions.ChatCompletionMessageParam; -export type ChatMessageOptions = Partial; +export type ChatMessageOptions = Partial & { + /** + * 是否能够思考 + * 如果会话是千文,服务器的接口,默认为 true + */ + enable_thinking?: boolean; +}; export type ChatMessageComplete = OpenAI.Chat.Completions.ChatCompletion; export type ChatMessageStream = OpenAI.Chat.Completions.ChatCompletion; diff --git a/src/provider/knowledge-adapter/siliconflow.ts b/src/provider/knowledge-adapter/siliconflow.ts index dfa567e..393f865 100644 --- a/src/provider/knowledge-adapter/siliconflow.ts +++ b/src/provider/knowledge-adapter/siliconflow.ts @@ -1,7 +1,7 @@ import { KnowledgeBase, KnowledgeOptions } from './knowledge-base.ts'; export class SiliconFlowKnowledge extends KnowledgeBase { - static BASE_URL = 'https://api.siliconflow.com/v1'; + static BASE_URL = 'https://api.siliconflow.cn/v1'; constructor(options: KnowledgeOptions) { super({ ...options, baseURL: options?.baseURL ?? SiliconFlowKnowledge.BASE_URL }); } diff --git a/src/test/siliconflow/common.ts b/src/test/siliconflow/common.ts index 85df4ca..e6e1e98 100644 --- a/src/test/siliconflow/common.ts +++ b/src/test/siliconflow/common.ts @@ -1,5 +1,8 @@ import { SiliconFlow } from '../../../src/provider/chat-adapter/siliconflow.ts'; import { SiliconFlowKnowledge } from '../../provider/knowledge-adapter/siliconflow.ts'; +import dotenv from 'dotenv'; + +dotenv.config(); export const siliconflow = new SiliconFlow({ apiKey: process.env.SILICONFLOW_API_KEY, model: 'Qwen/Qwen2-7B-Instruct', @@ -7,7 +10,6 @@ export const siliconflow = new SiliconFlow({ export const knowledge = new SiliconFlowKnowledge({ apiKey: process.env.SILICONFLOW_API_KEY, - baseURL: SiliconFlow.BASE_URL, model: 'Qwen/Qwen2-7B-Instruct', embeddingModel: 'Pro/BAAI/bge-m3', }); diff --git a/src/test/siliconflow/rerank/fc.ts b/src/test/siliconflow/rerank/fc.ts new file mode 100644 index 0000000..f039f6b --- /dev/null +++ b/src/test/siliconflow/rerank/fc.ts @@ -0,0 +1,28 @@ +import { knowledge } from '../common.ts'; +import util from 'node:util'; + +const fc = [ + { + title: '根据描述查询对应的网页的地址', + description: '根据描述查询对应的网页的地址,并返回网页的标题和链接', + }, + { + title: '查询我的 draw 应用中的内容 ', + description: '根据搜索内容,查询我的 draw 应用中的内容,并返回对应的数据', + }, +]; + +const main = async () => { + const res = await knowledge.rerank({ + model: 'BAAI/bge-reranker-v2-m3', + query: '查询网页', + // query: '网页code-center的地址', + documents: fc.map((item) => { + return `${item.title}:${item.description}`; + }), + }); + console.log(util.inspect(res, { depth: 10, colors: true })); + // 8000 tokens 大概1w个字 2万个字符 +}; + +main(); diff --git a/src/utils/json.ts b/src/utils/json.ts new file mode 100644 index 0000000..560e572 --- /dev/null +++ b/src/utils/json.ts @@ -0,0 +1,12 @@ +/** + * 尝试从字符串中提取JSON对象 + */ +export const getJsonFromString = (str: string) => { + try { + const jsonMatch = str.match(/```json\s*([\s\S]*?)\s*```/); + if (jsonMatch && jsonMatch[1]) { + return JSON.parse(jsonMatch[1]); + } + } catch (error) {} + return null; +};