mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: 完成自动添加 meta 的能力
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ const List = () => {
|
||||
shallow,
|
||||
);
|
||||
|
||||
console.log(data);
|
||||
return (
|
||||
<ChatList
|
||||
data={data}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 中间态
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -69,9 +69,7 @@ export const createSessionSlice: StateCreator<
|
||||
},
|
||||
createAt: timestamp,
|
||||
id: uuid(),
|
||||
meta: {
|
||||
title: '默认对话',
|
||||
},
|
||||
meta: {},
|
||||
type: LobeSessionType.Agent,
|
||||
updateAt: timestamp,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user