feat: 完成自动添加 meta 的能力

This commit is contained in:
arvinxx
2023-07-16 18:56:08 +08:00
parent d7195d9ec1
commit a82f35d338
9 changed files with 136 additions and 106 deletions

View File

@@ -7,6 +7,7 @@ import { Flexbox } from 'react-layout-kit';
import { shallow } from 'zustand/shallow';
import { sessionSelectors, useSessionStore } from '@/store/session';
import { DEFAULT_TITLE } from '@/store/session/slices/agentConfig';
import { useStyles } from './style';
@@ -21,22 +22,21 @@ interface SessionItemProps {
const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading }) => {
const { t } = useTranslation('common');
const { styles, theme, cx } = useStyles();
const [title, systemRole, avatar, avatarBackground, updateAt, removeSession] = useSessionStore(
(s) => {
const [title, description, systemRole, avatar, avatarBackground, updateAt, removeSession] =
useSessionStore((s) => {
const session = sessionSelectors.getSessionById(id)(s);
const meta = session.meta;
const systemRole = session.config.systemRole;
return [
meta.title,
meta.description,
systemRole,
sessionSelectors.getAgentAvatar(meta),
meta.backgroundColor,
session?.updateAt,
s.removeSession,
];
},
shallow,
);
}, shallow);
return (
<Flexbox className={styles.container} style={{ position: 'relative' }}>
@@ -53,13 +53,13 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading })
}
classNames={{ time: cx('session-time', styles.time) }}
date={updateAt}
description={title}
description={description || systemRole}
loading={loading}
style={{
alignItems: 'center',
color: theme.colorText,
}}
title={systemRole}
title={title || DEFAULT_TITLE}
/>
<Popconfirm
arrow={false}

View File

@@ -7,6 +7,7 @@ import { Center, Flexbox } from 'react-layout-kit';
import { shallow } from 'zustand/shallow';
import { agentSelectors, sessionSelectors, useSessionStore } from '@/store/session';
import { DEFAULT_TITLE } from '@/store/session/slices/agentConfig';
import { ConfigCell, ConfigCellGroup } from './ConfigCell';
@@ -33,7 +34,7 @@ const ReadMode = memo(() => {
return (
<Center gap={12} padding={'32px 16px'} style={{ marginTop: 8 }}>
<Avatar avatar={avatar} size={100} />
<Flexbox className={styles.title}>{title || '默认对话'}</Flexbox>
<Flexbox className={styles.title}>{title || DEFAULT_TITLE}</Flexbox>
<Flexbox className={styles.model}>{model}</Flexbox>
<Flexbox className={styles.desc}>{session.meta.description}</Flexbox>

View File

@@ -12,7 +12,6 @@ const List = () => {
shallow,
);
console.log(data);
return (
<ChatList
data={data}

View File

@@ -1,34 +1,64 @@
import { StateCreator } from 'zustand/vanilla';
import { promptPickEmoji, promptSummaryAgentName } from '@/prompts/agent';
import { promptPickEmoji } from '@/prompts/agent';
import { promptSummaryDescription, promptSummaryTitle } from '@/prompts/chat';
import { SessionStore, chatSelectors, sessionSelectors } from '@/store/session';
import { MetaData } from '@/types/meta';
import { LobeAgentConfig } from '@/types/session';
import { fetchPresetTaskResult } from '@/utils/fetch';
import { SessionLoadingState } from './initialState';
/**
* 代理行为接口
*/
export interface AgentAction {
/**
* 自动添加智能体名称
* @param agentId - 智能体 ID
* 自动选择表情
* @param id - 表情的 ID
*/
autoAddAgentName: (agentId: string) => Promise<void>;
autoAddChatBasicInfo: (chatId: string) => void;
autoPickEmoji: (id: string) => void;
autocompleteAgentMeta: (agentId: string) => Promise<void>;
/**
* 自动完成代理描述
* @param id - 代理的 ID
* @returns 一个 Promise用于异步操作完成后的处理
*/
autocompleteAgentDescription: (id: string) => Promise<void>;
/**
* 自动完成代理标题
* @param id - 代理的 ID
* @returns 一个 Promise用于异步操作完成后的处理
*/
autocompleteAgentTitle: (id: string) => Promise<void>;
/**
* 自动完成会话代理元数据
* @param id - 代理的 ID
*/
autocompleteSessionAgentMeta: (id: string) => void;
/**
* 内部更新代理元数据
* @param id - 代理的 ID
* @returns 任意类型的返回值
*/
internalUpdateAgentMeta: (id: string) => any;
/**
* 切换配置
* @param showPanel - 是否显示面板
* @param showPanel - 是否显示面板,默认为 true
*/
toggleConfig: (showPanel?: boolean) => void;
/**
* 分发智能体信息
* @param payload - 智能体信息
* 更新代理配置
* @param config - 部分 LobeAgentConfig 的配置
*/
updateAgentConfig: (config: Partial<LobeAgentConfig>) => void;
/**
* 更新加载状态
* @param key - SessionLoadingState 的键
* @param value - 加载状态的值
*/
updateLoadingState: (key: keyof SessionLoadingState, value: boolean) => void;
}
@@ -38,79 +68,6 @@ export const createAgentSlice: StateCreator<
[],
AgentAction
> = (set, get) => ({
// 使用 AI 自动补齐 Agent 元信息
autoAddAgentName: async (id) => {
const { dispatchSession, updateLoadingState } = get();
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;
const previousTitle = session.meta.title;
const systemRole = session.config.systemRole;
// 替换为 ...
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: '...' });
let title = '';
await fetchPresetTaskResult({
onError: () => {
dispatchSession({
id,
key: 'title',
type: 'updateSessionMeta',
value: previousTitle || systemRole,
});
},
onLoadingChange: (loading) => {
updateLoadingState('summarizingTitle', loading);
},
onMessageHandle: (text) => {
title += text;
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: title });
},
params: promptSummaryAgentName(systemRole),
});
},
autoAddChatBasicInfo: (chatId) => {
const session = sessionSelectors.getSessionById(chatId)(get());
const updateMeta = (key: 'title' | 'description') => {
let value = '';
return (text: string) => {
value += text;
get().dispatchSession({
id: chatId,
key,
type: 'updateSessionMeta',
value,
});
};
};
const chats = chatSelectors.currentChats(get());
if (!session) return;
if (!session.meta.title) {
fetchPresetTaskResult({
onLoadingChange: (loading) => {
get().updateLoadingState('summarizingTitle', loading);
},
onMessageHandle: updateMeta('title'),
params: promptSummaryTitle(chats),
});
}
if (!session.meta.description) {
fetchPresetTaskResult({
onLoadingChange: (loading) => {
get().updateLoadingState('summarizingTitle', loading);
},
onMessageHandle: updateMeta('description'),
params: promptSummaryDescription(chats),
});
}
},
autoPickEmoji: async (id) => {
const { dispatchSession } = get();
const session = sessionSelectors.getSessionById(id)(get());
@@ -129,21 +86,89 @@ export const createAgentSlice: StateCreator<
dispatchSession({ id, key: 'avatar', type: 'updateSessionMeta', value: emoji });
}
},
autocompleteAgentMeta: async (id) => {
autocompleteAgentDescription: async (id) => {
const { dispatchSession, updateLoadingState, internalUpdateAgentMeta } = get();
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;
// 没有title 就补充 title
const chats = chatSelectors.currentChats(get());
if (chats.length <= 0) return;
const preValue = session.meta.description;
// 替换为 ...
dispatchSession({ id, key: 'description', type: 'updateSessionMeta', value: '...' });
fetchPresetTaskResult({
onError: () => {
dispatchSession({
id,
key: 'description',
type: 'updateSessionMeta',
value: preValue,
});
},
onLoadingChange: (loading) => {
updateLoadingState('summarizingDescription', loading);
},
onMessageHandle: internalUpdateAgentMeta(id)('description'),
params: promptSummaryDescription(chats),
});
},
autocompleteAgentTitle: async (id) => {
const { dispatchSession, updateLoadingState, internalUpdateAgentMeta } = get();
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;
const chats = chatSelectors.currentChats(get());
if (chats.length <= 0) return;
const previousTitle = session.meta.title;
// 替换为 ...
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: '...' });
fetchPresetTaskResult({
onError: () => {
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: previousTitle });
},
onLoadingChange: (loading) => {
updateLoadingState('summarizingTitle', loading);
},
onMessageHandle: internalUpdateAgentMeta(id)('title'),
params: promptSummaryTitle(chats),
});
},
autocompleteSessionAgentMeta: (id) => {
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;
if (!session.meta.title) {
get().autoAddAgentName(id);
get().autocompleteAgentTitle(id);
}
if (!session.meta.description) {
get().autocompleteAgentDescription(id);
}
// 没有 avatar 就自动挑选 emoji
if (!session.meta.avatar) {
get().autoPickEmoji(id);
}
},
internalUpdateAgentMeta: (id: string) => (key: keyof MetaData) => {
let value = '';
return (text: string) => {
value += text;
get().dispatchSession({ id, key, type: 'updateSessionMeta', value });
};
},
toggleConfig: (newValue) => {
const showAgentSettings = typeof newValue === 'boolean' ? newValue : !get().showAgentSettings;

View File

@@ -18,7 +18,9 @@ export const initialLobeAgentConfig: LobeAgentConfig = {
systemRole: '',
};
export const defaultAvatar = 'https://npm.elemecdn.com/@lobehub/assets-logo/assets/logo-3d.webp';
export const DEFAULT_AVATAR = 'https://npm.elemecdn.com/@lobehub/assets-logo/assets/logo-3d.webp';
export const DEFAULT_TITLE = '默认对话';
export const initialAgentConfigState: AgentConfigState = {
// // loading 中间态

View File

@@ -3,7 +3,7 @@ import { LanguageModel } from '@/types/llm';
import { LobeAgentConfig } from '@/types/session';
import { sessionSelectors } from '../session';
import { defaultAvatar, initialLobeAgentConfig } from './initialState';
import { DEFAULT_AVATAR, initialLobeAgentConfig } from './initialState';
const currentAgentTitle = (s: SessionStore) => {
const session = sessionSelectors.currentSession(s);
@@ -14,9 +14,9 @@ const currentAgentTitle = (s: SessionStore) => {
const currentAgentAvatar = (s: SessionStore) => {
const session = sessionSelectors.currentSession(s);
if (!session) return defaultAvatar;
if (!session) return DEFAULT_AVATAR;
return session.meta.avatar || defaultAvatar;
return session.meta.avatar || DEFAULT_AVATAR;
};
const currentAgentConfig = (s: SessionStore) => {

View File

@@ -157,7 +157,7 @@ export const createChatSlice: StateCreator<
},
sendMessage: async (message) => {
const { dispatchMessage, generateMessage } = get();
const { dispatchMessage, generateMessage, autocompleteSessionAgentMeta } = get();
const session = sessionSelectors.currentSession(get());
if (!session || !message) return;
@@ -201,5 +201,10 @@ export const createChatSlice: StateCreator<
item.scrollIntoView({ behavior: 'smooth' });
},
});
const chats = chatSelectors.currentChats(get());
if (chats.length >= 4) {
autocompleteSessionAgentMeta(session.id);
}
},
});

View File

@@ -69,9 +69,7 @@ export const createSessionSlice: StateCreator<
},
createAt: timestamp,
id: uuid(),
meta: {
title: '默认对话',
},
meta: {},
type: LobeSessionType.Agent,
updateAt: timestamp,
};

View File

@@ -1,4 +1,4 @@
import { defaultAvatar } from '@/store/session/slices/agentConfig';
import { DEFAULT_AVATAR } from '@/store/session/slices/agentConfig';
import { MetaData } from '@/types/meta';
export const getAgentAvatar = (s: MetaData) => s.avatar || defaultAvatar;
export const getAgentAvatar = (s: MetaData) => s.avatar || DEFAULT_AVATAR;