Compare commits

..

1 Commits

Author SHA1 Message Date
kangfenmao
ebf61b1ce9 feat: plugins 2024-12-30 23:45:47 +08:00
14 changed files with 96 additions and 59 deletions

View File

@@ -1,19 +0,0 @@
diff --git a/src/markdown-loader.js b/src/markdown-loader.js
index 8a17cb7f5a68d90d2be21682db6e95ce22a3e71c..9ee868ef9d4ff3dc914b3abc3c8006deb1e9c6c6 100644
--- a/src/markdown-loader.js
+++ b/src/markdown-loader.js
@@ -1,5 +1,4 @@
import { micromark } from 'micromark';
-import { mdxJsx } from 'micromark-extension-mdx-jsx';
import { gfmHtml, gfm } from 'micromark-extension-gfm';
import createDebugMessages from 'debug';
import fs from 'node:fs';
@@ -21,7 +20,7 @@ export class MarkdownLoader extends BaseLoader {
? (await getSafe(this.filePathOrUrl, { format: 'buffer' })).body
: await stream2buffer(fs.createReadStream(this.filePathOrUrl));
this.debug('MarkdownLoader stream created');
- const result = micromark(buffer, { extensions: [gfm(), mdxJsx()], htmlExtensions: [gfmHtml()] });
+ const result = micromark(buffer, { extensions: [gfm()], htmlExtensions: [gfmHtml()] });
this.debug('Markdown parsed...');
const webLoader = new WebLoader({
urlOrContent: result,

View File

@@ -79,8 +79,3 @@ afterSign: scripts/notarize.js
releaseInfo:
releaseNotes: |
增加 Genspark 小程序
用户消息支持编辑并重新发送
助手支持自定义请求参数 by @n2yt584v2t4nh7y
支持编辑话题总结提示词
修复 Windows 用户安装后无法打开的问题
修复知识库无法向量化MD文件的问题

View File

@@ -1,6 +1,6 @@
{
"name": "CherryStudio",
"version": "0.9.3",
"version": "0.9.2",
"private": true,
"description": "A powerful AI assistant for producer.",
"main": "./out/main/index.js",
@@ -53,7 +53,7 @@
"@llm-tools/embedjs": "patch:@llm-tools/embedjs@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.25-ec5645cf36.patch",
"@llm-tools/embedjs-libsql": "patch:@llm-tools/embedjs-libsql@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-libsql-npm-0.1.25-fad000d74c.patch",
"@llm-tools/embedjs-loader-csv": "^0.1.25",
"@llm-tools/embedjs-loader-markdown": "patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.25-d1d536d640.patch",
"@llm-tools/embedjs-loader-markdown": "^0.1.25",
"@llm-tools/embedjs-loader-msoffice": "^0.1.25",
"@llm-tools/embedjs-loader-pdf": "^0.1.25",
"@llm-tools/embedjs-loader-sitemap": "^0.1.25",
@@ -95,7 +95,7 @@
"@types/tinycolor2": "^1",
"@vitejs/plugin-react": "^4.2.1",
"antd": "^5.22.5",
"axios": "^1.7.3",
"axios": "^1.7.9",
"browser-image-compression": "^2.0.2",
"dayjs": "^1.11.11",
"dexie": "^4.0.8",

View File

@@ -1,7 +1,9 @@
import fs from 'node:fs'
import path from 'node:path'
import vm from 'node:vm'
import { Shortcut, ThemeMode } from '@types'
import axios from 'axios'
import { BrowserWindow, ipcMain, ProxyConfig, session, shell } from 'electron'
import log from 'electron-log'
@@ -154,4 +156,10 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle('knowledge-base:add', KnowledgeService.add)
ipcMain.handle('knowledge-base:remove', KnowledgeService.remove)
ipcMain.handle('knowledge-base:search', KnowledgeService.search)
// vm
ipcMain.handle('run-js', (_, code: string) => {
const context = vm.createContext(Object.assign({ fetch: fetch, URL: URL, axios: axios }, global))
return vm.runInContext(code, context)
})
}

View File

@@ -122,7 +122,7 @@ class KnowledgeService {
return await ragApplication.addLoader(new ExcelLoader({ filePathOrUrl: file.path }) as any, forceReload)
}
if (['.md'].includes(file.ext)) {
if (['.md', '.mdx'].includes(file.ext)) {
return await ragApplication.addLoader(new MarkdownLoader({ filePathOrUrl: file.path }) as any, forceReload)
}

View File

@@ -76,6 +76,9 @@ declare global {
remove: ({ uniqueId, base }: { uniqueId: string; base: KnowledgeBaseParams }) => Promise<void>
search: ({ search, base }: { search: string; base: KnowledgeBaseParams }) => Promise<ExtractChunkData[]>
}
vm: {
run: (code: string) => Promise<any>
}
}
}
}

View File

@@ -70,6 +70,9 @@ const api = {
ipcRenderer.invoke('knowledge-base:remove', { uniqueId, base }),
search: ({ search, base }: { search: string; base: KnowledgeBaseParams }) =>
ipcRenderer.invoke('knowledge-base:search', { search, base })
},
vm: {
run: (code: string) => ipcRenderer.invoke('run-js', code)
}
}

View File

@@ -62,7 +62,6 @@ const KnowledgeBaseButton: FC<Props> = ({ selectedBase, onSelect, disabled, Tool
<Popover
placement="top"
content={<KnowledgeBaseSelector selectedBase={selectedBase} onSelect={onSelect} />}
overlayStyle={{ maxWidth: 400 }}
trigger="click">
<ToolbarButton type="text" onClick={() => selectedBase && onSelect(undefined)} disabled={disabled}>
<FileSearchOutlined style={{ color: selectedBase ? 'var(--color-link)' : 'var(--color-icon)' }} />

View File

@@ -29,7 +29,7 @@ interface KnowledgeContentProps {
selectedBase: KnowledgeBase
}
const fileTypes = ['.pdf', '.docx', '.pptx', '.xlsx', '.txt', '.md']
const fileTypes = ['.pdf', '.docx', '.pptx', '.xlsx', '.txt', '.md', '.mdx']
const FlexColumn = styled.div`
display: flex;

View File

@@ -337,7 +337,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
</Button>
</SettingRow>
{customParameters.map((param, index) => (
<Row key={index} align="stretch" gutter={10} style={{ marginTop: 10 }}>
<Row key={index} align="middle" gutter={10} style={{ marginTop: 10 }}>
<Col span={6}>
<Input
placeholder={t('models.parameter_name')}
@@ -355,8 +355,8 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
<Select.Option value="boolean">{t('models.parameter_type.boolean')}</Select.Option>
</Select>
</Col>
<Col span={12}>{renderParameterValueInput(param, index)}</Col>
<Col span={2} style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Col span={11}>{renderParameterValueInput(param, index)}</Col>
<Col span={3}>
<Button icon={<DeleteOutlined />} onClick={() => onDeleteCustomParameter(index)} danger />
</Col>
</Row>

View File

@@ -4,6 +4,8 @@ import i18n from '@renderer/i18n'
import { getAssistantSettings, getDefaultModel, getTopNamingModel } from '@renderer/services/AssistantService'
import { EVENT_NAMES } from '@renderer/services/EventService'
import { filterContextMessages } from '@renderer/services/MessagesService'
import DuckDuckGoLiteSearch from '@renderer/tools/DuckDuckGoLiteSearch/function.json'
import DuckDuckGoLiteSearchCode from '@renderer/tools/DuckDuckGoLiteSearch/index.js?raw'
import { Assistant, FileTypes, Message, Model, Provider, Suggestion } from '@renderer/types'
import { removeQuotes } from '@renderer/utils'
import { last, takeRight } from 'lodash'
@@ -11,7 +13,8 @@ import OpenAI, { AzureOpenAI } from 'openai'
import {
ChatCompletionContentPart,
ChatCompletionCreateParamsNonStreaming,
ChatCompletionMessageParam
ChatCompletionMessageParam,
ChatCompletionTool
} from 'openai/resources'
import { CompletionsParams } from '.'
@@ -133,7 +136,6 @@ export default class OpenAIProvider extends BaseProvider {
}
const isOpenAIo1 = model.id.includes('o1-')
const isSupportStreamOutput = streamOutput
let time_first_token_millsec = 0
const start_time_millsec = new Date().getTime()
@@ -148,12 +150,28 @@ export default class OpenAIProvider extends BaseProvider {
top_p: assistant?.settings?.topP,
max_tokens: maxTokens,
keep_alive: this.keepAliveTime,
stream: isSupportStreamOutput,
stream: streamOutput,
tools: [DuckDuckGoLiteSearch as ChatCompletionTool],
...this.getCustomParameters(assistant)
})
if (!isSupportStreamOutput) {
if (!streamOutput) {
const time_completion_millsec = new Date().getTime() - start_time_millsec
stream.choices[0].message?.tool_calls?.forEach(async (toolCall) => {
const functionName = toolCall.function.name
const params = toolCall.function.arguments
console.log(functionName, DuckDuckGoLiteSearchCode)
const result = await window.api.vm.run(`
var params = ${params};
${DuckDuckGoLiteSearchCode}
`)
console.log(result)
})
return onChunk({
text: stream.choices[0].message?.content || '',
usage: stream.usage,

View File

@@ -0,0 +1,22 @@
{
"type": "function",
"function": {
"name": "DuckDuckGoLiteSearch",
"description": "A search engine useful for answering questions about current events.",
"parameters": {
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "Keywords for query"
},
"kl": {
"type": "string",
"description": "Language/region code (e.g., wt-wt, us-en, uk-en)",
"default": "wt-wt"
}
},
"required": ["q"]
}
}
}

View File

@@ -0,0 +1,23 @@
new Promise((resolve, reject) => {
async function makeRequest() {
try {
const response = await axios.request({
method: 'post',
maxBodyLength: Infinity,
url: 'https://google.serper.dev/search',
headers: {
'X-API-KEY': 'fa70255d0ab3402ee2ddb6455f6b317e73588fc7',
'Content-Type': 'application/json'
},
data: params
})
console.log(JSON.stringify(response.data))
resolve(response.data)
} catch (error) {
console.log(error)
reject(error.toString())
}
}
makeRequest()
})

View File

@@ -1577,7 +1577,7 @@ __metadata:
languageName: node
linkType: hard
"@llm-tools/embedjs-loader-markdown@npm:0.1.25":
"@llm-tools/embedjs-loader-markdown@npm:^0.1.25":
version: 0.1.25
resolution: "@llm-tools/embedjs-loader-markdown@npm:0.1.25"
dependencies:
@@ -1592,21 +1592,6 @@ __metadata:
languageName: node
linkType: hard
"@llm-tools/embedjs-loader-markdown@patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.25-d1d536d640.patch":
version: 0.1.25
resolution: "@llm-tools/embedjs-loader-markdown@patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.25-d1d536d640.patch::version=0.1.25&hash=3a7d12"
dependencies:
"@llm-tools/embedjs-interfaces": "npm:0.1.25"
"@llm-tools/embedjs-loader-web": "npm:0.1.25"
debug: "npm:^4.4.0"
md5: "npm:^2.3.0"
micromark: "npm:^4.0.1"
micromark-extension-gfm: "npm:^3.0.0"
micromark-extension-mdx-jsx: "npm:^3.0.1"
checksum: 10c0/8e91a1260f8c94ec516be13a5105055bf140b5c63a85fa3c7641cc8f6799a0410ddb6bce61db858e91712f7dbc2b333269eb7c3ce813c1d95416f49f4f4f31a5
languageName: node
linkType: hard
"@llm-tools/embedjs-loader-msoffice@npm:^0.1.25":
version: 0.1.25
resolution: "@llm-tools/embedjs-loader-msoffice@npm:0.1.25"
@@ -2861,7 +2846,7 @@ __metadata:
"@llm-tools/embedjs": "patch:@llm-tools/embedjs@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.25-ec5645cf36.patch"
"@llm-tools/embedjs-libsql": "patch:@llm-tools/embedjs-libsql@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-libsql-npm-0.1.25-fad000d74c.patch"
"@llm-tools/embedjs-loader-csv": "npm:^0.1.25"
"@llm-tools/embedjs-loader-markdown": "patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.25#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.25-d1d536d640.patch"
"@llm-tools/embedjs-loader-markdown": "npm:^0.1.25"
"@llm-tools/embedjs-loader-msoffice": "npm:^0.1.25"
"@llm-tools/embedjs-loader-pdf": "npm:^0.1.25"
"@llm-tools/embedjs-loader-sitemap": "npm:^0.1.25"
@@ -2882,7 +2867,7 @@ __metadata:
adm-zip: "npm:^0.5.16"
antd: "npm:^5.22.5"
apache-arrow: "npm:^18.1.0"
axios: "npm:^1.7.3"
axios: "npm:^1.7.9"
browser-image-compression: "npm:^2.0.2"
dayjs: "npm:^1.11.11"
dexie: "npm:^4.0.8"
@@ -3521,14 +3506,14 @@ __metadata:
languageName: node
linkType: hard
"axios@npm:^1.7.3":
version: 1.7.7
resolution: "axios@npm:1.7.7"
"axios@npm:^1.7.9":
version: 1.7.9
resolution: "axios@npm:1.7.9"
dependencies:
follow-redirects: "npm:^1.15.6"
form-data: "npm:^4.0.0"
proxy-from-env: "npm:^1.1.0"
checksum: 10c0/4499efc89e86b0b49ffddc018798de05fab26e3bf57913818266be73279a6418c3ce8f9e934c7d2d707ab8c095e837fc6c90608fb7715b94d357720b5f568af7
checksum: 10c0/b7a41e24b59fee5f0f26c1fc844b45b17442832eb3a0fb42dd4f1430eb4abc571fe168e67913e8a1d91c993232bd1d1ab03e20e4d1fee8c6147649b576fc1b0b
languageName: node
linkType: hard