@lobehub/chat 1.124.0 → 1.124.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -0
- package/.github/scripts/pr-comment.js +11 -2
- package/.github/workflows/desktop-pr-build.yml +86 -12
- package/.github/workflows/release-desktop-beta.yml +91 -20
- package/CHANGELOG.md +58 -0
- package/Dockerfile +2 -0
- package/Dockerfile.database +2 -0
- package/Dockerfile.pglite +2 -0
- package/apps/desktop/electron-builder.js +8 -4
- package/changelog/v1.json +21 -0
- package/docs/self-hosting/environment-variables/model-provider.mdx +18 -0
- package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +20 -0
- package/locales/ar/chat.json +2 -0
- package/locales/bg-BG/chat.json +2 -0
- package/locales/de-DE/chat.json +2 -0
- package/locales/en-US/chat.json +2 -0
- package/locales/es-ES/chat.json +2 -0
- package/locales/fa-IR/chat.json +2 -0
- package/locales/fr-FR/chat.json +2 -0
- package/locales/it-IT/chat.json +2 -0
- package/locales/ja-JP/chat.json +2 -0
- package/locales/ko-KR/chat.json +2 -0
- package/locales/nl-NL/chat.json +2 -0
- package/locales/pl-PL/chat.json +2 -0
- package/locales/pt-BR/chat.json +2 -0
- package/locales/ru-RU/chat.json +2 -0
- package/locales/tr-TR/chat.json +2 -0
- package/locales/vi-VN/chat.json +2 -0
- package/locales/zh-CN/chat.json +2 -0
- package/locales/zh-CN/modelProvider.json +1 -1
- package/locales/zh-TW/chat.json +2 -0
- package/package.json +1 -1
- package/packages/const/src/hotkeys.ts +1 -1
- package/packages/const/src/index.ts +1 -0
- package/packages/const/src/settings/hotkey.ts +3 -2
- package/packages/const/src/trace.ts +1 -1
- package/packages/const/src/user.ts +1 -2
- package/packages/database/src/client/db.test.ts +19 -13
- package/packages/electron-server-ipc/src/ipcClient.test.ts +783 -1
- package/packages/file-loaders/src/loadFile.test.ts +61 -0
- package/packages/file-loaders/src/utils/isTextReadableFile.test.ts +43 -0
- package/packages/file-loaders/src/utils/parser-utils.test.ts +155 -0
- package/packages/model-bank/src/aiModels/aihubmix.ts +38 -4
- package/packages/model-bank/src/aiModels/groq.ts +26 -8
- package/packages/model-bank/src/aiModels/hunyuan.ts +3 -3
- package/packages/model-bank/src/aiModels/modelscope.ts +13 -2
- package/packages/model-bank/src/aiModels/moonshot.ts +25 -5
- package/packages/model-bank/src/aiModels/novita.ts +40 -9
- package/packages/model-bank/src/aiModels/openrouter.ts +0 -13
- package/packages/model-bank/src/aiModels/qwen.ts +62 -1
- package/packages/model-bank/src/aiModels/siliconcloud.ts +20 -0
- package/packages/model-bank/src/aiModels/volcengine.ts +141 -15
- package/packages/model-runtime/package.json +2 -1
- package/packages/model-runtime/src/ai21/index.test.ts +2 -2
- package/packages/model-runtime/src/ai360/index.test.ts +2 -2
- package/packages/model-runtime/src/akashchat/index.test.ts +19 -0
- package/packages/model-runtime/src/anthropic/index.test.ts +1 -2
- package/packages/model-runtime/src/baichuan/index.test.ts +1 -2
- package/packages/model-runtime/src/bedrock/index.test.ts +1 -2
- package/packages/model-runtime/src/bfl/createImage.test.ts +1 -2
- package/packages/model-runtime/src/bfl/index.test.ts +1 -2
- package/packages/model-runtime/src/cloudflare/index.test.ts +1 -2
- package/packages/model-runtime/src/cohere/index.test.ts +19 -0
- package/packages/model-runtime/src/deepseek/index.test.ts +2 -2
- package/packages/model-runtime/src/fireworksai/index.test.ts +2 -2
- package/packages/model-runtime/src/giteeai/index.test.ts +2 -2
- package/packages/model-runtime/src/github/index.test.ts +2 -2
- package/packages/model-runtime/src/google/createImage.test.ts +1 -2
- package/packages/model-runtime/src/google/index.test.ts +1 -1
- package/packages/model-runtime/src/groq/index.test.ts +2 -3
- package/packages/model-runtime/src/huggingface/index.test.ts +40 -0
- package/packages/model-runtime/src/hunyuan/index.test.ts +2 -3
- package/packages/model-runtime/src/internlm/index.test.ts +2 -2
- package/packages/model-runtime/src/jina/index.test.ts +19 -0
- package/packages/model-runtime/src/lmstudio/index.test.ts +2 -2
- package/packages/model-runtime/src/minimax/index.test.ts +19 -0
- package/packages/model-runtime/src/mistral/index.test.ts +2 -3
- package/packages/model-runtime/src/modelscope/index.test.ts +19 -0
- package/packages/model-runtime/src/moonshot/index.test.ts +1 -2
- package/packages/model-runtime/src/nebius/index.test.ts +19 -0
- package/packages/model-runtime/src/newapi/index.test.ts +49 -42
- package/packages/model-runtime/src/newapi/index.ts +124 -143
- package/packages/model-runtime/src/novita/index.test.ts +3 -4
- package/packages/model-runtime/src/nvidia/index.test.ts +19 -0
- package/packages/model-runtime/src/openrouter/index.test.ts +2 -3
- package/packages/model-runtime/src/perplexity/index.test.ts +2 -3
- package/packages/model-runtime/src/ppio/index.test.ts +3 -4
- package/packages/model-runtime/src/qwen/index.test.ts +2 -2
- package/packages/model-runtime/src/sambanova/index.test.ts +19 -0
- package/packages/model-runtime/src/search1api/index.test.ts +19 -0
- package/packages/model-runtime/src/sensenova/index.test.ts +2 -2
- package/packages/model-runtime/src/spark/index.test.ts +2 -2
- package/packages/model-runtime/src/stepfun/index.test.ts +2 -2
- package/packages/model-runtime/src/taichu/index.test.ts +4 -5
- package/packages/model-runtime/src/tencentcloud/index.test.ts +1 -1
- package/packages/model-runtime/src/togetherai/index.test.ts +1 -2
- package/packages/model-runtime/src/upstage/index.test.ts +1 -2
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.test.ts +9 -7
- package/packages/model-runtime/src/utils/streams/anthropic.ts +2 -2
- package/packages/model-runtime/src/utils/streams/openai/openai.ts +20 -13
- package/packages/model-runtime/src/utils/streams/openai/responsesStream.test.ts +1 -2
- package/packages/model-runtime/src/utils/streams/openai/responsesStream.ts +2 -2
- package/packages/model-runtime/src/utils/streams/protocol.ts +2 -2
- package/packages/model-runtime/src/wenxin/index.test.ts +2 -3
- package/packages/model-runtime/src/xai/index.test.ts +2 -2
- package/packages/model-runtime/src/zeroone/index.test.ts +1 -2
- package/packages/model-runtime/src/zhipu/index.test.ts +2 -3
- package/packages/model-runtime/vitest.config.mts +0 -7
- package/packages/types/src/index.ts +2 -0
- package/packages/types/src/message/base.ts +1 -1
- package/packages/types/src/openai/chat.ts +2 -3
- package/packages/utils/package.json +2 -1
- package/packages/utils/src/_deprecated/parseModels.test.ts +1 -1
- package/packages/utils/src/_deprecated/parseModels.ts +1 -1
- package/packages/utils/src/client/topic.test.ts +1 -2
- package/packages/utils/src/client/topic.ts +1 -2
- package/packages/utils/src/electron/desktopRemoteRPCFetch.ts +1 -1
- package/packages/utils/src/fetch/fetchSSE.ts +7 -8
- package/packages/utils/src/fetch/parseError.ts +1 -3
- package/packages/utils/src/format.test.ts +1 -2
- package/packages/utils/src/index.ts +1 -0
- package/packages/utils/src/toolManifest.ts +1 -2
- package/packages/utils/src/trace.ts +1 -1
- package/packages/utils/vitest.config.mts +1 -1
- package/packages/web-crawler/src/__tests__/urlRules.test.ts +275 -0
- package/packages/web-crawler/src/crawImpl/__tests__/exa.test.ts +269 -0
- package/packages/web-crawler/src/crawImpl/__tests__/firecrawl.test.ts +284 -0
- package/packages/web-crawler/src/crawImpl/__tests__/naive.test.ts +234 -0
- package/packages/web-crawler/src/crawImpl/__tests__/tavily.test.ts +359 -0
- package/packages/web-crawler/src/utils/__tests__/errorType.test.ts +217 -0
- package/packages/web-crawler/vitest.config.mts +3 -0
- package/scripts/electronWorkflow/mergeMacReleaseFiles.ts +207 -0
- package/src/app/[variants]/(main)/settings/provider/(detail)/newapi/page.tsx +1 -1
- package/src/components/Thinking/index.tsx +2 -3
- package/src/config/llm.ts +8 -0
- package/src/features/ChatInput/Desktop/index.tsx +16 -4
- package/src/features/ChatInput/StoreUpdater.tsx +2 -0
- package/src/libs/traces/index.ts +1 -1
- package/src/locales/default/chat.ts +1 -0
- package/src/locales/default/modelProvider.ts +1 -1
- package/src/server/modules/ModelRuntime/trace.ts +1 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/cancel-functionality.test.ts +107 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +352 -7
- package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +2 -1
- package/packages/model-runtime/src/openrouter/__snapshots__/index.test.ts.snap +0 -113
@@ -0,0 +1,61 @@
|
|
1
|
+
// @vitest-environment node
|
2
|
+
import * as fsPromises from 'node:fs/promises';
|
3
|
+
import path from 'node:path';
|
4
|
+
import { describe, expect, it, vi } from 'vitest';
|
5
|
+
|
6
|
+
import { loadFile } from './loadFile';
|
7
|
+
|
8
|
+
const fixtures = path.join(__dirname, '../test/fixtures');
|
9
|
+
const fp = (name: string) => path.join(fixtures, name);
|
10
|
+
|
11
|
+
describe('loadFile', () => {
|
12
|
+
it('loads text-like files via TextLoader and aggregates', async () => {
|
13
|
+
const file = fp('test.txt');
|
14
|
+
const doc = await loadFile(file);
|
15
|
+
expect(doc.fileType).toBe('txt');
|
16
|
+
expect(doc.filename).toBe('test.txt');
|
17
|
+
expect(doc.source).toBe(file);
|
18
|
+
expect(doc.content).toContain('This is line 1.');
|
19
|
+
expect(doc.pages?.[0].metadata.lineNumberStart).toBe(1);
|
20
|
+
expect(doc.totalCharCount).toBeGreaterThan(0);
|
21
|
+
expect(doc.totalLineCount).toBeGreaterThan(0);
|
22
|
+
});
|
23
|
+
|
24
|
+
it('loads pdf files via PdfLoader and aggregates', async () => {
|
25
|
+
const file = fp('test.pdf');
|
26
|
+
const doc = await loadFile(file);
|
27
|
+
expect(doc.fileType).toBe('pdf');
|
28
|
+
expect(doc.filename).toBe('test.pdf');
|
29
|
+
expect(doc.source).toBe(file);
|
30
|
+
expect(doc.content).toContain('123');
|
31
|
+
expect(doc.pages && doc.pages.length).toBeGreaterThan(0);
|
32
|
+
});
|
33
|
+
|
34
|
+
it('returns error page when fs.stat fails', async () => {
|
35
|
+
const doc = await loadFile('/not/exists.xyz');
|
36
|
+
expect(doc.pages).toHaveLength(1);
|
37
|
+
expect(doc.pages?.[0].metadata.error).toContain('Failed to access file stats:');
|
38
|
+
expect(doc.metadata.error).toContain('Failed to access file stats:');
|
39
|
+
});
|
40
|
+
|
41
|
+
it('falls back to TextLoader for unsupported type and warns', async () => {
|
42
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
43
|
+
const doc = await loadFile(fp('test.epub')); // epub is unsupported in current mapping
|
44
|
+
expect(warn).toHaveBeenCalled();
|
45
|
+
expect(doc.content.length).toBeGreaterThanOrEqual(0);
|
46
|
+
warn.mockRestore();
|
47
|
+
});
|
48
|
+
|
49
|
+
it('allows overriding metadata via second parameter', async () => {
|
50
|
+
const file = fp('test.txt');
|
51
|
+
const override = {
|
52
|
+
source: 's3://bucket/key',
|
53
|
+
filename: 'override.txt',
|
54
|
+
fileType: 'custom',
|
55
|
+
};
|
56
|
+
const doc = await loadFile(file, override);
|
57
|
+
expect(doc.source).toBe('s3://bucket/key');
|
58
|
+
expect(doc.filename).toBe('override.txt');
|
59
|
+
expect(doc.fileType).toBe('custom');
|
60
|
+
});
|
61
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
2
|
+
|
3
|
+
import { isTextReadableFile } from './isTextReadableFile';
|
4
|
+
|
5
|
+
describe('isTextReadableFile', () => {
|
6
|
+
it('should return true for common text-readable types', () => {
|
7
|
+
const positives = [
|
8
|
+
'txt',
|
9
|
+
'md',
|
10
|
+
'mdx',
|
11
|
+
'json',
|
12
|
+
'yaml',
|
13
|
+
'yml',
|
14
|
+
'csv',
|
15
|
+
'html',
|
16
|
+
'css',
|
17
|
+
'js',
|
18
|
+
'ts',
|
19
|
+
'py',
|
20
|
+
'log',
|
21
|
+
'sql',
|
22
|
+
'patch',
|
23
|
+
'diff',
|
24
|
+
];
|
25
|
+
|
26
|
+
for (const ext of positives) {
|
27
|
+
expect(isTextReadableFile(ext)).toBe(true);
|
28
|
+
}
|
29
|
+
});
|
30
|
+
|
31
|
+
it('should be case-insensitive', () => {
|
32
|
+
expect(isTextReadableFile('Md')).toBe(true);
|
33
|
+
expect(isTextReadableFile('JSON')).toBe(true);
|
34
|
+
expect(isTextReadableFile('YML')).toBe(true);
|
35
|
+
});
|
36
|
+
|
37
|
+
it('should return false for non text-readable or binary types', () => {
|
38
|
+
const negatives = ['pdf', 'docx', 'xlsx', 'pptx', 'png', 'jpg', 'gif'];
|
39
|
+
for (const ext of negatives) {
|
40
|
+
expect(isTextReadableFile(ext)).toBe(false);
|
41
|
+
}
|
42
|
+
});
|
43
|
+
});
|
@@ -0,0 +1,155 @@
|
|
1
|
+
// @vitest-environment node
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
3
|
+
|
4
|
+
import { type ExtractedFile, extractFiles, parseString } from './parser-utils';
|
5
|
+
|
6
|
+
describe('parser-utils', () => {
|
7
|
+
describe('parseString', () => {
|
8
|
+
it('should parse valid XML string into XMLDocument', () => {
|
9
|
+
const xml = '<root><item id="1">hello</item></root>';
|
10
|
+
const doc = parseString(xml);
|
11
|
+
|
12
|
+
// The parsed document should contain the root and item node
|
13
|
+
const root = (doc as any).getElementsByTagName('root')[0];
|
14
|
+
expect(root).toBeDefined();
|
15
|
+
const item = (doc as any).getElementsByTagName('item')[0];
|
16
|
+
expect(item).toBeDefined();
|
17
|
+
expect(item.getAttribute('id')).toBe('1');
|
18
|
+
expect(item.textContent).toBe('hello');
|
19
|
+
});
|
20
|
+
});
|
21
|
+
|
22
|
+
describe('extractFiles', () => {
|
23
|
+
beforeEach(() => {
|
24
|
+
vi.resetModules();
|
25
|
+
});
|
26
|
+
|
27
|
+
it('should reject on invalid input type', async () => {
|
28
|
+
// @ts-expect-error intentional wrong type
|
29
|
+
await expect(extractFiles(123, () => true)).rejects.toThrow(
|
30
|
+
'[OfficeParser]: Invalid input type',
|
31
|
+
);
|
32
|
+
});
|
33
|
+
|
34
|
+
it('should read entries via yauzl.fromBuffer and filter matches', async () => {
|
35
|
+
// Arrange: build a fake zipfile object with two file entries and one directory
|
36
|
+
const entryHandlers: Record<string, (cb: () => void) => void> = {};
|
37
|
+
const listeners: Record<string, Function[]> = { entry: [], end: [], error: [] };
|
38
|
+
let idx = 0;
|
39
|
+
const sequence = [
|
40
|
+
{ fileName: 'folder/' },
|
41
|
+
{ fileName: 'keep.txt' },
|
42
|
+
{ fileName: 'skip.bin' },
|
43
|
+
];
|
44
|
+
|
45
|
+
const emit = (name: string, payload?: any) =>
|
46
|
+
(listeners[name] || []).forEach((fn) => fn(payload));
|
47
|
+
|
48
|
+
const fakeZipfile = {
|
49
|
+
readEntry: vi.fn().mockImplementation(() => {
|
50
|
+
queueMicrotask(() => {
|
51
|
+
if (idx < sequence.length) {
|
52
|
+
const entry = sequence[idx++];
|
53
|
+
emit('entry', entry as any);
|
54
|
+
} else {
|
55
|
+
emit('end');
|
56
|
+
}
|
57
|
+
});
|
58
|
+
}),
|
59
|
+
openReadStream: vi.fn((entry: any, cb: (err: any, stream?: any) => void) => {
|
60
|
+
if (entry.fileName === 'keep.txt') {
|
61
|
+
// Provide a minimal readable stream compatible with concat-stream
|
62
|
+
const chunks: any[] = [];
|
63
|
+
const stream = {
|
64
|
+
pipe(destination: any) {
|
65
|
+
// emulate piping to concat-stream writable
|
66
|
+
if (typeof destination.end === 'function') {
|
67
|
+
destination.end(Buffer.from('hello world'));
|
68
|
+
}
|
69
|
+
return destination;
|
70
|
+
},
|
71
|
+
on: vi.fn(),
|
72
|
+
};
|
73
|
+
cb(null, stream);
|
74
|
+
} else if (entry.fileName === 'skip.bin') {
|
75
|
+
// This entry should be skipped by filter, so not invoked
|
76
|
+
cb(null, undefined as any);
|
77
|
+
}
|
78
|
+
}),
|
79
|
+
on: vi.fn((evt: string, handler: Function) => {
|
80
|
+
listeners[evt] = listeners[evt] || [];
|
81
|
+
listeners[evt].push(handler);
|
82
|
+
}),
|
83
|
+
close: vi.fn(),
|
84
|
+
} as any;
|
85
|
+
|
86
|
+
// Mock yauzl.fromBuffer to pass back our fake zipfile
|
87
|
+
vi.doMock('yauzl', () => ({
|
88
|
+
default: {
|
89
|
+
fromBuffer: (_buf: Buffer, _opts: any, cb: (err: any, zf?: any) => void) =>
|
90
|
+
cb(null, fakeZipfile),
|
91
|
+
open: vi.fn(),
|
92
|
+
},
|
93
|
+
}));
|
94
|
+
|
95
|
+
// Re-import module to use mocked yauzl
|
96
|
+
const { extractFiles: mockedExtractFiles } = await import('./parser-utils');
|
97
|
+
|
98
|
+
const files: ExtractedFile[] = await mockedExtractFiles(Buffer.from('zip'), (name) =>
|
99
|
+
name.endsWith('.txt'),
|
100
|
+
);
|
101
|
+
expect(files).toEqual([{ path: 'keep.txt', content: 'hello world' }]);
|
102
|
+
});
|
103
|
+
|
104
|
+
it('should open zip by file path when input is string', async () => {
|
105
|
+
const listeners: Record<string, Function[]> = { entry: [], end: [], error: [] };
|
106
|
+
let idx = 0;
|
107
|
+
const entries = [{ fileName: 'keep.txt' }];
|
108
|
+
const emit2 = (name: string, payload?: any) =>
|
109
|
+
(listeners[name] || []).forEach((fn) => fn(payload));
|
110
|
+
|
111
|
+
const fakeZipfile = {
|
112
|
+
readEntry: vi.fn().mockImplementation(() => {
|
113
|
+
queueMicrotask(() => {
|
114
|
+
if (idx < entries.length) {
|
115
|
+
const entry = entries[idx++];
|
116
|
+
emit2('entry', entry as any);
|
117
|
+
} else {
|
118
|
+
emit2('end');
|
119
|
+
}
|
120
|
+
});
|
121
|
+
}),
|
122
|
+
openReadStream: vi.fn((entry: any, cb: (err: any, stream?: any) => void) => {
|
123
|
+
const stream = {
|
124
|
+
pipe(destination: any) {
|
125
|
+
if (typeof destination.end === 'function') {
|
126
|
+
destination.end(Buffer.from('A'));
|
127
|
+
}
|
128
|
+
return destination;
|
129
|
+
},
|
130
|
+
on: vi.fn(),
|
131
|
+
};
|
132
|
+
cb(null, stream);
|
133
|
+
}),
|
134
|
+
on: vi.fn((evt: string, handler: Function) => {
|
135
|
+
listeners[evt] = listeners[evt] || [];
|
136
|
+
listeners[evt].push(handler);
|
137
|
+
}),
|
138
|
+
close: vi.fn(),
|
139
|
+
} as any;
|
140
|
+
|
141
|
+
vi.doMock('yauzl', () => ({
|
142
|
+
default: {
|
143
|
+
fromBuffer: vi.fn(),
|
144
|
+
open: (_path: string, _opts: any, cb: (err: any, zf?: any) => void) =>
|
145
|
+
cb(null, fakeZipfile),
|
146
|
+
},
|
147
|
+
}));
|
148
|
+
|
149
|
+
const { extractFiles: mockedExtractFiles } = await import('./parser-utils');
|
150
|
+
|
151
|
+
const files = await mockedExtractFiles('/tmp/file.zip', (name) => name === 'keep.txt');
|
152
|
+
expect(files).toEqual([{ path: 'keep.txt', content: 'A' }]);
|
153
|
+
});
|
154
|
+
});
|
155
|
+
});
|
@@ -552,13 +552,11 @@ const aihubmixModels: AIChatModelCard[] = [
|
|
552
552
|
{
|
553
553
|
abilities: {
|
554
554
|
functionCall: true,
|
555
|
-
reasoning: true,
|
556
555
|
},
|
557
556
|
contextWindowTokens: 131_072,
|
558
557
|
description:
|
559
|
-
'DeepSeek-V3.1 是深度求索全新推出的混合推理模型,支持思考与非思考2种推理模式,较 DeepSeek-R1-0528 思考效率更高。经 Post-Training 优化,Agent 工具使用与智能体任务表现大幅提升。',
|
560
|
-
displayName: 'DeepSeek V3.1',
|
561
|
-
enabled: true,
|
558
|
+
'DeepSeek-V3.1-非思考模式;DeepSeek-V3.1 是深度求索全新推出的混合推理模型,支持思考与非思考2种推理模式,较 DeepSeek-R1-0528 思考效率更高。经 Post-Training 优化,Agent 工具使用与智能体任务表现大幅提升。',
|
559
|
+
displayName: 'DeepSeek V3.1 (non-Think)',
|
562
560
|
id: 'DeepSeek-V3.1',
|
563
561
|
pricing: {
|
564
562
|
units: [
|
@@ -568,6 +566,42 @@ const aihubmixModels: AIChatModelCard[] = [
|
|
568
566
|
},
|
569
567
|
type: 'chat',
|
570
568
|
},
|
569
|
+
{
|
570
|
+
abilities: {
|
571
|
+
functionCall: true,
|
572
|
+
reasoning: true,
|
573
|
+
},
|
574
|
+
contextWindowTokens: 131_072,
|
575
|
+
description:
|
576
|
+
'DeepSeek-V3.1-思考模式;DeepSeek-V3.1 是深度求索全新推出的混合推理模型,支持思考与非思考2种推理模式,较 DeepSeek-R1-0528 思考效率更高。经 Post-Training 优化,Agent 工具使用与智能体任务表现大幅提升。',
|
577
|
+
displayName: 'DeepSeek V3.1 (Think)',
|
578
|
+
id: 'DeepSeek-V3.1-Think',
|
579
|
+
pricing: {
|
580
|
+
units: [
|
581
|
+
{ name: 'textInput', rate: 0.56, strategy: 'fixed', unit: 'millionTokens' },
|
582
|
+
{ name: 'textOutput', rate: 1.68, strategy: 'fixed', unit: 'millionTokens' },
|
583
|
+
],
|
584
|
+
},
|
585
|
+
type: 'chat',
|
586
|
+
},
|
587
|
+
{
|
588
|
+
abilities: {
|
589
|
+
functionCall: true,
|
590
|
+
reasoning: true,
|
591
|
+
},
|
592
|
+
contextWindowTokens: 131_072,
|
593
|
+
description:
|
594
|
+
'DeepSeek V3.1 Fast 是 DeepSeek V3.1版本的高TPS极速版。 混合思考模式:通过更改聊天模板,一个模型可以同时支持思考模式和非思考模式。 更智能的工具调用:通过后训练优化,模型在工具使用和代理任务中的表现显著提升。',
|
595
|
+
displayName: 'DeepSeek V3.1 (Fast)',
|
596
|
+
id: 'DeepSeek-V3.1-Fast',
|
597
|
+
pricing: {
|
598
|
+
units: [
|
599
|
+
{ name: 'textInput', rate: 1.096, strategy: 'fixed', unit: 'millionTokens' },
|
600
|
+
{ name: 'textOutput', rate: 3.288, strategy: 'fixed', unit: 'millionTokens' },
|
601
|
+
],
|
602
|
+
},
|
603
|
+
type: 'chat',
|
604
|
+
},
|
571
605
|
{
|
572
606
|
abilities: {
|
573
607
|
functionCall: true,
|
@@ -7,19 +7,19 @@ const groqChatModels: AIChatModelCard[] = [
|
|
7
7
|
{
|
8
8
|
contextWindowTokens: 131_072,
|
9
9
|
description:
|
10
|
-
'Compound
|
11
|
-
displayName: 'Compound
|
10
|
+
'Compound 是一个复合 AI 系统,由 GroqCloud 中已经支持的多个开放可用的模型提供支持,可以智能地、有选择地使用工具来回答用户查询。',
|
11
|
+
displayName: 'Compound',
|
12
12
|
enabled: true,
|
13
|
-
id: 'compound
|
13
|
+
id: 'groq/compound',
|
14
14
|
maxOutput: 8192,
|
15
15
|
type: 'chat',
|
16
16
|
},
|
17
17
|
{
|
18
18
|
contextWindowTokens: 131_072,
|
19
19
|
description:
|
20
|
-
'Compound-
|
21
|
-
displayName: 'Compound
|
22
|
-
id: 'compound-
|
20
|
+
'Compound-mini 是一个复合 AI 系统,由 GroqCloud 中已经支持的公开可用模型提供支持,可以智能地、有选择地使用工具来回答用户查询。',
|
21
|
+
displayName: 'Compound Mini',
|
22
|
+
id: 'groq/compound-mini',
|
23
23
|
maxOutput: 8192,
|
24
24
|
type: 'chat',
|
25
25
|
},
|
@@ -63,6 +63,25 @@ const groqChatModels: AIChatModelCard[] = [
|
|
63
63
|
releasedAt: '2025-08-06',
|
64
64
|
type: 'chat',
|
65
65
|
},
|
66
|
+
{
|
67
|
+
abilities: {
|
68
|
+
functionCall: true,
|
69
|
+
},
|
70
|
+
contextWindowTokens: 262_144,
|
71
|
+
description:
|
72
|
+
'kimi-k2-0905-preview 模型上下文长度为 256k,具备更强的 Agentic Coding 能力、更突出的前端代码的美观度和实用性、以及更好的上下文理解能力。',
|
73
|
+
displayName: 'Kimi K2 0905',
|
74
|
+
enabled: true,
|
75
|
+
id: 'moonshotai/kimi-k2-instruct-0905',
|
76
|
+
pricing: {
|
77
|
+
units: [
|
78
|
+
{ name: 'textInput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },
|
79
|
+
{ name: 'textOutput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },
|
80
|
+
],
|
81
|
+
},
|
82
|
+
releasedAt: '2025-09-05',
|
83
|
+
type: 'chat',
|
84
|
+
},
|
66
85
|
{
|
67
86
|
abilities: {
|
68
87
|
functionCall: true,
|
@@ -70,8 +89,7 @@ const groqChatModels: AIChatModelCard[] = [
|
|
70
89
|
contextWindowTokens: 131_072,
|
71
90
|
description:
|
72
91
|
'kimi-k2 是一款具备超强代码和 Agent 能力的 MoE 架构基础模型,总参数 1T,激活参数 32B。在通用知识推理、编程、数学、Agent 等主要类别的基准性能测试中,K2 模型的性能超过其他主流开源模型。',
|
73
|
-
displayName: 'Kimi K2
|
74
|
-
enabled: true,
|
92
|
+
displayName: 'Kimi K2 0711',
|
75
93
|
id: 'moonshotai/kimi-k2-instruct',
|
76
94
|
maxOutput: 16_384,
|
77
95
|
pricing: {
|
@@ -26,9 +26,9 @@ const hunyuanChatModels: AIChatModelCard[] = [
|
|
26
26
|
reasoning: true,
|
27
27
|
search: true,
|
28
28
|
},
|
29
|
-
contextWindowTokens:
|
29
|
+
contextWindowTokens: 96_000,
|
30
30
|
description:
|
31
|
-
'
|
31
|
+
'大幅提升主模型慢思考模型的高难数学、复杂推理、高难代码、指令遵循、文本创作质量等能力。',
|
32
32
|
displayName: 'Hunyuan T1',
|
33
33
|
enabled: true,
|
34
34
|
id: 'hunyuan-t1-latest',
|
@@ -40,7 +40,7 @@ const hunyuanChatModels: AIChatModelCard[] = [
|
|
40
40
|
{ name: 'textOutput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },
|
41
41
|
],
|
42
42
|
},
|
43
|
-
releasedAt: '2025-
|
43
|
+
releasedAt: '2025-08-22',
|
44
44
|
settings: {
|
45
45
|
searchImpl: 'params',
|
46
46
|
},
|
@@ -1,6 +1,19 @@
|
|
1
1
|
import { AIChatModelCard } from '../types/aiModel';
|
2
2
|
|
3
3
|
const modelscopeChatModels: AIChatModelCard[] = [
|
4
|
+
{
|
5
|
+
abilities: {
|
6
|
+
functionCall: true,
|
7
|
+
},
|
8
|
+
contextWindowTokens: 262_144,
|
9
|
+
description:
|
10
|
+
'kimi-k2-0905-preview 模型上下文长度为 256k,具备更强的 Agentic Coding 能力、更突出的前端代码的美观度和实用性、以及更好的上下文理解能力。',
|
11
|
+
displayName: 'Kimi K2 0905',
|
12
|
+
enabled: true,
|
13
|
+
id: 'moonshotai/Kimi-K2-Instruct-0905',
|
14
|
+
releasedAt: '2025-09-05',
|
15
|
+
type: 'chat',
|
16
|
+
},
|
4
17
|
{
|
5
18
|
abilities: {
|
6
19
|
functionCall: true,
|
@@ -53,7 +66,6 @@ const modelscopeChatModels: AIChatModelCard[] = [
|
|
53
66
|
contextWindowTokens: 131_072,
|
54
67
|
description: 'Qwen3-235B-A22B是通义千问3代超大规模模型,提供顶级的AI能力。',
|
55
68
|
displayName: 'Qwen3-235B-A22B',
|
56
|
-
enabled: true,
|
57
69
|
id: 'Qwen/Qwen3-235B-A22B',
|
58
70
|
type: 'chat',
|
59
71
|
},
|
@@ -64,7 +76,6 @@ const modelscopeChatModels: AIChatModelCard[] = [
|
|
64
76
|
contextWindowTokens: 131_072,
|
65
77
|
description: 'Qwen3-32B是通义千问3代模型,具有强大的推理和对话能力。',
|
66
78
|
displayName: 'Qwen3-32B',
|
67
|
-
enabled: true,
|
68
79
|
id: 'Qwen/Qwen3-32B',
|
69
80
|
type: 'chat',
|
70
81
|
},
|
@@ -2,6 +2,27 @@ import { AIChatModelCard } from '../types/aiModel';
|
|
2
2
|
|
3
3
|
// https://platform.moonshot.cn/docs/pricing/chat
|
4
4
|
const moonshotChatModels: AIChatModelCard[] = [
|
5
|
+
{
|
6
|
+
abilities: {
|
7
|
+
functionCall: true,
|
8
|
+
},
|
9
|
+
contextWindowTokens: 262_144,
|
10
|
+
description:
|
11
|
+
'kimi-k2-0905-preview 模型上下文长度为 256k,具备更强的 Agentic Coding 能力、更突出的前端代码的美观度和实用性、以及更好的上下文理解能力。',
|
12
|
+
displayName: 'Kimi K2 0905',
|
13
|
+
enabled: true,
|
14
|
+
id: 'kimi-k2-0905-preview',
|
15
|
+
pricing: {
|
16
|
+
currency: 'CNY',
|
17
|
+
units: [
|
18
|
+
{ name: 'textInput_cacheRead', rate: 1, strategy: 'fixed', unit: 'millionTokens' },
|
19
|
+
{ name: 'textInput', rate: 4, strategy: 'fixed', unit: 'millionTokens' },
|
20
|
+
{ name: 'textOutput', rate: 16, strategy: 'fixed', unit: 'millionTokens' },
|
21
|
+
],
|
22
|
+
},
|
23
|
+
releasedAt: '2025-09-05',
|
24
|
+
type: 'chat',
|
25
|
+
},
|
5
26
|
{
|
6
27
|
abilities: {
|
7
28
|
functionCall: true,
|
@@ -9,8 +30,7 @@ const moonshotChatModels: AIChatModelCard[] = [
|
|
9
30
|
contextWindowTokens: 131_072,
|
10
31
|
description:
|
11
32
|
'kimi-k2 是一款具备超强代码和 Agent 能力的 MoE 架构基础模型,总参数 1T,激活参数 32B。在通用知识推理、编程、数学、Agent 等主要类别的基准性能测试中,K2 模型的性能超过其他主流开源模型。',
|
12
|
-
displayName: 'Kimi K2',
|
13
|
-
enabled: true,
|
33
|
+
displayName: 'Kimi K2 0711',
|
14
34
|
id: 'kimi-k2-0711-preview',
|
15
35
|
pricing: {
|
16
36
|
currency: 'CNY',
|
@@ -27,10 +47,10 @@ const moonshotChatModels: AIChatModelCard[] = [
|
|
27
47
|
abilities: {
|
28
48
|
functionCall: true,
|
29
49
|
},
|
30
|
-
contextWindowTokens:
|
50
|
+
contextWindowTokens: 262_144,
|
31
51
|
description:
|
32
52
|
'kimi-k2 是一款具备超强代码和 Agent 能力的 MoE 架构基础模型,总参数 1T,激活参数 32B。在通用知识推理、编程、数学、Agent 等主要类别的基准性能测试中,K2 模型的性能超过其他主流开源模型。',
|
33
|
-
displayName: 'Kimi K2 Turbo',
|
53
|
+
displayName: 'Kimi K2 0905 Turbo',
|
34
54
|
id: 'kimi-k2-turbo-preview',
|
35
55
|
pricing: {
|
36
56
|
currency: 'CNY',
|
@@ -40,7 +60,7 @@ const moonshotChatModels: AIChatModelCard[] = [
|
|
40
60
|
{ name: 'textOutput', rate: 64, strategy: 'fixed', unit: 'millionTokens' },
|
41
61
|
],
|
42
62
|
},
|
43
|
-
releasedAt: '2025-
|
63
|
+
releasedAt: '2025-09-05',
|
44
64
|
type: 'chat',
|
45
65
|
},
|
46
66
|
{
|
@@ -2,6 +2,24 @@ import { AIChatModelCard } from '../types/aiModel';
|
|
2
2
|
|
3
3
|
// https://novita.ai/pricing
|
4
4
|
const novitaChatModels: AIChatModelCard[] = [
|
5
|
+
{
|
6
|
+
abilities: {
|
7
|
+
functionCall: true,
|
8
|
+
},
|
9
|
+
contextWindowTokens: 262_144,
|
10
|
+
description:
|
11
|
+
'kimi-k2-0905-preview 模型上下文长度为 256k,具备更强的 Agentic Coding 能力、更突出的前端代码的美观度和实用性、以及更好的上下文理解能力。',
|
12
|
+
displayName: 'Kimi K2 0905',
|
13
|
+
id: 'moonshotai/kimi-k2-0905',
|
14
|
+
pricing: {
|
15
|
+
units: [
|
16
|
+
{ name: 'textInput', rate: 0.6, strategy: 'fixed', unit: 'millionTokens' },
|
17
|
+
{ name: 'textOutput', rate: 2.5, strategy: 'fixed', unit: 'millionTokens' },
|
18
|
+
],
|
19
|
+
},
|
20
|
+
releasedAt: '2025-09-05',
|
21
|
+
type: 'chat',
|
22
|
+
},
|
5
23
|
{
|
6
24
|
abilities: {
|
7
25
|
functionCall: true,
|
@@ -9,11 +27,12 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
9
27
|
},
|
10
28
|
contextWindowTokens: 163_840,
|
11
29
|
displayName: 'DeepSeek V3.1',
|
30
|
+
enabled: true,
|
12
31
|
id: 'deepseek/deepseek-v3.1',
|
13
32
|
pricing: {
|
14
33
|
units: [
|
15
|
-
{ name: 'textInput', rate: 0.
|
16
|
-
{ name: 'textOutput', rate: 1
|
34
|
+
{ name: 'textInput', rate: 0.27, strategy: 'fixed', unit: 'millionTokens' },
|
35
|
+
{ name: 'textOutput', rate: 1, strategy: 'fixed', unit: 'millionTokens' },
|
17
36
|
],
|
18
37
|
},
|
19
38
|
type: 'chat',
|
@@ -128,10 +147,10 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
128
147
|
},
|
129
148
|
{
|
130
149
|
abilities: {
|
131
|
-
|
150
|
+
functionCall: true,
|
132
151
|
},
|
133
152
|
contextWindowTokens: 131_072,
|
134
|
-
displayName: 'Kimi K2
|
153
|
+
displayName: 'Kimi K2 0711',
|
135
154
|
id: 'moonshotai/kimi-k2-instruct',
|
136
155
|
pricing: {
|
137
156
|
units: [
|
@@ -286,12 +305,12 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
286
305
|
abilities: {
|
287
306
|
reasoning: true,
|
288
307
|
},
|
289
|
-
contextWindowTokens:
|
308
|
+
contextWindowTokens: 32_768,
|
290
309
|
displayName: 'Qwen3 30B A3B FP8',
|
291
310
|
id: 'qwen/qwen3-30b-a3b-fp8',
|
292
311
|
pricing: {
|
293
312
|
units: [
|
294
|
-
{ name: 'textInput', rate: 0.
|
313
|
+
{ name: 'textInput', rate: 0.09, strategy: 'fixed', unit: 'millionTokens' },
|
295
314
|
{ name: 'textOutput', rate: 0.45, strategy: 'fixed', unit: 'millionTokens' },
|
296
315
|
],
|
297
316
|
},
|
@@ -413,7 +432,7 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
413
432
|
type: 'chat',
|
414
433
|
},
|
415
434
|
{
|
416
|
-
contextWindowTokens:
|
435
|
+
contextWindowTokens: 32_768,
|
417
436
|
description: 'Gemma 3 27B 是谷歌的一款开源语言模型,以其在效率和性能方面设立了新的标准。',
|
418
437
|
displayName: 'Gemma 3 27B',
|
419
438
|
id: 'google/gemma-3-27b-it',
|
@@ -425,6 +444,20 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
425
444
|
},
|
426
445
|
type: 'chat',
|
427
446
|
},
|
447
|
+
{
|
448
|
+
contextWindowTokens: 131_072,
|
449
|
+
description: 'Gemma 3 12B 是谷歌的一款开源语言模型,以其在效率和性能方面设立了新的标准。',
|
450
|
+
displayName: 'Gemma 3 12B',
|
451
|
+
id: 'google/gemma-3-12b-it',
|
452
|
+
maxOutput: 8192,
|
453
|
+
pricing: {
|
454
|
+
units: [
|
455
|
+
{ name: 'textInput', rate: 0.05, strategy: 'fixed', unit: 'millionTokens' },
|
456
|
+
{ name: 'textOutput', rate: 0.1, strategy: 'fixed', unit: 'millionTokens' },
|
457
|
+
],
|
458
|
+
},
|
459
|
+
type: 'chat',
|
460
|
+
},
|
428
461
|
{
|
429
462
|
contextWindowTokens: 32_768,
|
430
463
|
description: 'Gemma 3 1B 是谷歌的一款开源语言模型,以其在效率和性能方面设立了新的标准。',
|
@@ -549,7 +582,6 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
549
582
|
},
|
550
583
|
contextWindowTokens: 163_840,
|
551
584
|
displayName: 'Deepseek V3 0324',
|
552
|
-
enabled: true,
|
553
585
|
id: 'deepseek/deepseek-v3-0324',
|
554
586
|
pricing: {
|
555
587
|
units: [
|
@@ -566,7 +598,6 @@ const novitaChatModels: AIChatModelCard[] = [
|
|
566
598
|
},
|
567
599
|
contextWindowTokens: 163_840,
|
568
600
|
displayName: 'Deepseek R1 0528',
|
569
|
-
enabled: true,
|
570
601
|
id: 'deepseek/deepseek-r1-0528',
|
571
602
|
pricing: {
|
572
603
|
units: [
|
@@ -50,19 +50,6 @@ const openrouterChatModels: AIChatModelCard[] = [
|
|
50
50
|
releasedAt: '2025-08-26',
|
51
51
|
type: 'chat',
|
52
52
|
},
|
53
|
-
{
|
54
|
-
abilities: {
|
55
|
-
imageOutput: true,
|
56
|
-
vision: true,
|
57
|
-
},
|
58
|
-
contextWindowTokens: 32_768 + 8192,
|
59
|
-
description: 'Gemini 2.5 Flash 实验模型,支持图像生成',
|
60
|
-
displayName: 'Nano Banana (free)',
|
61
|
-
id: 'google/gemini-2.5-flash-image-preview:free',
|
62
|
-
maxOutput: 8192,
|
63
|
-
releasedAt: '2025-08-26',
|
64
|
-
type: 'chat',
|
65
|
-
},
|
66
53
|
{
|
67
54
|
abilities: {
|
68
55
|
functionCall: true,
|