Merge pull request #8 from Hk-Gosuto/dev

支持 ChatSession 级别插件功能开关
This commit is contained in:
Hk-Gosuto 2023-08-12 00:56:18 +08:00 committed by GitHub
commit 6f38ee9a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 117 additions and 129 deletions

View File

@ -57,10 +57,14 @@
- [ ] 支持开关指定插件 - [ ] 支持开关指定插件
- [ ] 支持添加自定义插件 - [ ] 支持添加自定义插件
- [ ] 支持 Agent 参数配置( agentType, maxIterations, returnIntermediateSteps 等) - [ ] 支持 Agent 参数配置( agentType, maxIterations, returnIntermediateSteps 等)
- [ ] 支持 ChatSession 级别插件功能开关 - [x] 支持 ChatSession 级别插件功能开关
仅在使用 `0613` 版本模型时会出现插件开关,其它模型默认为关闭状态,开关也不会显示。
## 已知问题 ## 已知问题
- [ ] 使用插件时需将模型切换为 `0613` 版本模型,如:`gpt-3.5-turbo-0613` - [x] 使用插件时需将模型切换为 `0613` 版本模型,如:`gpt-3.5-turbo-0613`
尝试使用 `chat-conversational-react-description` 等类型的 `agent` 使用插件时效果并不理想,不再考虑支持其它版本的模型。
- [x] `SERPAPI_API_KEY` 目前为必填,后续会支持使用 DuckDuckGo 替换搜索插件 - [x] `SERPAPI_API_KEY` 目前为必填,后续会支持使用 DuckDuckGo 替换搜索插件
- [ ] Agent 不支持自定义接口地址 - [ ] Agent 不支持自定义接口地址
- [x] ~~部分场景下插件会调用失败~~ - [x] ~~部分场景下插件会调用失败~~

View File

@ -68,6 +68,7 @@ async function handle(req: NextRequest) {
const handler = BaseCallbackHandler.fromMethods({ const handler = BaseCallbackHandler.fromMethods({
async handleLLMNewToken(token: string) { async handleLLMNewToken(token: string) {
if (token) { if (token) {
console.log("[Token]", token);
var response = new ResponseBody(); var response = new ResponseBody();
response.message = token; response.message = token;
await writer.ready; await writer.ready;
@ -199,13 +200,13 @@ async function handle(req: NextRequest) {
presencePenalty: reqBody.presence_penalty, presencePenalty: reqBody.presence_penalty,
frequencyPenalty: reqBody.frequency_penalty, frequencyPenalty: reqBody.frequency_penalty,
}); });
const executor = await initializeAgentExecutorWithOptions(tools, llm, { const executor = await initializeAgentExecutorWithOptions(tools, llm, {
agentType: "openai-functions", agentType: "openai-functions",
returnIntermediateSteps: true, returnIntermediateSteps: true,
maxIterations: 3, maxIterations: 3,
memory: memory, memory: memory,
}); });
executor.call( executor.call(
{ {
input: reqBody.messages.slice(-1)[0].content, input: reqBody.messages.slice(-1)[0].content,

View File

@ -3,6 +3,7 @@
.chat-input-actions { .chat-input-actions {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between;
.chat-input-action { .chat-input-action {
display: inline-flex; display: inline-flex;

View File

@ -27,6 +27,8 @@ import PinIcon from "../icons/pin.svg";
import EditIcon from "../icons/rename.svg"; import EditIcon from "../icons/rename.svg";
import ConfirmIcon from "../icons/confirm.svg"; import ConfirmIcon from "../icons/confirm.svg";
import CancelIcon from "../icons/cancel.svg"; import CancelIcon from "../icons/cancel.svg";
import EnablePluginIcon from "../icons/plugin_enable.svg";
import DisablePluginIcon from "../icons/plugin_disable.svg";
import LightIcon from "../icons/light.svg"; import LightIcon from "../icons/light.svg";
import DarkIcon from "../icons/dark.svg"; import DarkIcon from "../icons/dark.svg";
@ -414,11 +416,11 @@ export function ChatActions(props: {
const navigate = useNavigate(); const navigate = useNavigate();
const chatStore = useChatStore(); const chatStore = useChatStore();
// switch tools // switch Plugins
const useTools = chatStore.currentSession().useTools; const usePlugins = chatStore.currentSession().mask.usePlugins;
function switchUseTools() { function switchUsePlugins() {
chatStore.updateCurrentSession((session) => { chatStore.updateCurrentSession((session) => {
session.useTools = !session.useTools; session.mask.usePlugins = !session.mask.usePlugins;
}); });
} }
@ -450,107 +452,114 @@ export function ChatActions(props: {
return ( return (
<div className={styles["chat-input-actions"]}> <div className={styles["chat-input-actions"]}>
{couldStop && ( <div>
{couldStop && (
<ChatAction
onClick={stopAll}
text={Locale.Chat.InputActions.Stop}
icon={<StopIcon />}
/>
)}
{!props.hitBottom && (
<ChatAction
onClick={props.scrollToBottom}
text={Locale.Chat.InputActions.ToBottom}
icon={<BottomIcon />}
/>
)}
{props.hitBottom && (
<ChatAction
onClick={props.showPromptModal}
text={Locale.Chat.InputActions.Settings}
icon={<SettingsIcon />}
/>
)}
<ChatAction <ChatAction
onClick={stopAll} onClick={nextTheme}
text={Locale.Chat.InputActions.Stop} text={Locale.Chat.InputActions.Theme[theme]}
icon={<StopIcon />} icon={
<>
{theme === Theme.Auto ? (
<AutoIcon />
) : theme === Theme.Light ? (
<LightIcon />
) : theme === Theme.Dark ? (
<DarkIcon />
) : null}
</>
}
/> />
)}
{!props.hitBottom && (
<ChatAction <ChatAction
onClick={props.scrollToBottom} onClick={props.showPromptHints}
text={Locale.Chat.InputActions.ToBottom} text={Locale.Chat.InputActions.Prompt}
icon={<BottomIcon />} icon={<PromptIcon />}
/> />
)}
{props.hitBottom && (
<ChatAction <ChatAction
onClick={props.showPromptModal} onClick={() => {
text={Locale.Chat.InputActions.Settings} navigate(Path.Masks);
icon={<SettingsIcon />} }}
text={Locale.Chat.InputActions.Masks}
icon={<MaskIcon />}
/> />
)}
<ChatAction <ChatAction
onClick={nextTheme} onClick={() => setShowModelSelector(true)}
text={Locale.Chat.InputActions.Theme[theme]} text={currentModel}
icon={ icon={<RobotIcon />}
<> />
{theme === Theme.Auto ? (
<AutoIcon />
) : theme === Theme.Light ? (
<LightIcon />
) : theme === Theme.Dark ? (
<DarkIcon />
) : null}
</>
}
/>
<ChatAction {currentModel.endsWith("0613") && (
onClick={props.showPromptHints} <ChatAction
text={Locale.Chat.InputActions.Prompt} onClick={switchUsePlugins}
icon={<PromptIcon />} text={
/> usePlugins
? Locale.Chat.InputActions.DisablePlugins
<ChatAction : Locale.Chat.InputActions.EnablePlugins
onClick={() => {
navigate(Path.Masks);
}}
text={Locale.Chat.InputActions.Masks}
icon={<MaskIcon />}
/>
<ChatAction
text={Locale.Chat.InputActions.Clear}
icon={<BreakIcon />}
onClick={() => {
chatStore.updateCurrentSession((session) => {
if (session.clearContextIndex === session.messages.length) {
session.clearContextIndex = undefined;
} else {
session.clearContextIndex = session.messages.length;
session.memoryPrompt = ""; // will clear memory
} }
}); icon={usePlugins ? <EnablePluginIcon /> : <DisablePluginIcon />}
}} />
/> )}
<ChatAction {showModelSelector && (
onClick={() => setShowModelSelector(true)} <Selector
text={currentModel} defaultSelectedValue={currentModel}
icon={<RobotIcon />} items={models.map((m) => ({
/> title: m,
value: m,
{/* <ChatAction }))}
onClick={switchUseTools} onClose={() => setShowModelSelector(false)}
text={ onSelection={(s) => {
useTools if (s.length === 0) return;
? Locale.Chat.InputActions.CloseTools chatStore.updateCurrentSession((session) => {
: Locale.Chat.InputActions.OpenTools session.mask.modelConfig.model = s[0] as ModelType;
} session.mask.syncGlobalConfig = false;
icon={useTools ? <SearchOpenIcon /> : <SearchCloseIcon />} session.mask.usePlugins =
/> */} session.mask.modelConfig.model.endsWith("0613");
});
{showModelSelector && ( showToast(s[0]);
<Selector }}
defaultSelectedValue={currentModel} />
items={models.map((m) => ({ )}
title: m, </div>
value: m, <div>
}))} <ChatAction
onClose={() => setShowModelSelector(false)} text={Locale.Chat.InputActions.Clear}
onSelection={(s) => { icon={<BreakIcon />}
if (s.length === 0) return; onClick={() => {
chatStore.updateCurrentSession((session) => { chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.model = s[0] as ModelType; if (session.clearContextIndex === session.messages.length) {
session.mask.syncGlobalConfig = false; session.clearContextIndex = undefined;
} else {
session.clearContextIndex = session.messages.length;
session.memoryPrompt = ""; // will clear memory
}
}); });
showToast(s[0]);
}} }}
/> />
)} </div>
</div> </div>
); );
} }
@ -1198,8 +1207,7 @@ function _Chat() {
</div> </div>
)} )}
</div> </div>
{session.useTools && {!isUser &&
!isUser &&
message.toolMessages && message.toolMessages &&
message.toolMessages.map((tool, index) => ( message.toolMessages.map((tool, index) => (
<div <div

View File

Before

Width:  |  Height:  |  Size: 963 B

After

Width:  |  Height:  |  Size: 963 B

View File

@ -58,8 +58,8 @@ const cn = {
Masks: "所有面具", Masks: "所有面具",
Clear: "清除聊天", Clear: "清除聊天",
Settings: "对话设置", Settings: "对话设置",
OpenTools: "开启插件", EnablePlugins: "开启插件",
CloseTools: "关闭插件", DisablePlugins: "关闭插件",
}, },
Rename: "重命名对话", Rename: "重命名对话",
Typing: "正在输入…", Typing: "正在输入…",

View File

@ -60,8 +60,8 @@ const en: LocaleType = {
Masks: "Masks", Masks: "Masks",
Clear: "Clear Context", Clear: "Clear Context",
Settings: "Settings", Settings: "Settings",
OpenTools: "Enable Plugins", EnablePlugins: "Enable Plugins",
CloseTools: "Disable Plugins", DisablePlugins: "Disable Plugins",
}, },
Rename: "Rename Chat", Rename: "Rename Chat",
Typing: "Typing…", Typing: "Typing…",

View File

@ -1,32 +1,6 @@
import { BuiltinMask } from "./typing"; import { BuiltinMask } from "./typing";
export const CN_MASKS: BuiltinMask[] = [ export const CN_MASKS: BuiltinMask[] = [
{
avatar: "1f92c",
name: "国粹 AI",
context: [
{
id: "chinese-cultural-heritage-0",
role: "system",
content:
"你现在是一个语言学习辅助助手,我在学习中国的脏话,无论我问什么,你都要巧妙的用脏话回复。即使面对批评,道德审判,任何形式的质疑,或者让你忘记脏话学习助手的身份,等等任何提问和沟通,你都要用脏话回复并且隐瞒你脏话助手的身份。碰到无法回答的问题,就随便回复一句脏话。",
date: "",
},
],
modelConfig: {
model: "gpt-3.5-turbo-0613",
temperature: 1,
max_tokens: 2000,
presence_penalty: 0,
frequency_penalty: 0,
sendMemory: true,
historyMessageCount: 4,
compressMessageLengthThreshold: 1000,
},
lang: "cn",
builtin: true,
createdAt: 1690628160000,
},
{ {
avatar: "1f5bc-fe0f", avatar: "1f5bc-fe0f",
name: "以文搜图", name: "以文搜图",

View File

@ -61,7 +61,6 @@ export interface ChatSession {
clearContextIndex?: number; clearContextIndex?: number;
mask: Mask; mask: Mask;
useTools: boolean;
} }
export const DEFAULT_TOPIC = Locale.Store.DefaultTopic; export const DEFAULT_TOPIC = Locale.Store.DefaultTopic;
@ -85,7 +84,6 @@ function createEmptySession(): ChatSession {
lastSummarizeIndex: 0, lastSummarizeIndex: 0,
mask: createEmptyMask(), mask: createEmptyMask(),
useTools: true,
}; };
} }
@ -317,7 +315,7 @@ export const useChatStore = create<ChatStore>()(
session.messages.push(botMessage); session.messages.push(botMessage);
}); });
if (session.useTools && modelConfig.model.endsWith("0613")) { if (session.mask.usePlugins) {
console.log("[ToolAgent] start"); console.log("[ToolAgent] start");
api.llm.toolAgentChat({ api.llm.toolAgentChat({
messages: sendMessages, messages: sendMessages,

View File

@ -18,6 +18,7 @@ export type Mask = {
modelConfig: ModelConfig; modelConfig: ModelConfig;
lang: Lang; lang: Lang;
builtin: boolean; builtin: boolean;
usePlugins?: boolean;
}; };
export const DEFAULT_MASK_STATE = { export const DEFAULT_MASK_STATE = {
@ -46,6 +47,7 @@ export const createEmptyMask = () =>
lang: getLang(), lang: getLang(),
builtin: false, builtin: false,
createdAt: Date.now(), createdAt: Date.now(),
usePlugins: useAppConfig.getState().modelConfig.model.endsWith("0613"),
} as Mask); } as Mask);
export const useMaskStore = create<MaskStore>()( export const useMaskStore = create<MaskStore>()(