Skip to content

Commit

Permalink
✨ feat: 完成自动添加 meta 的能力
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Jul 16, 2023
1 parent d7195d9 commit a82f35d
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 97 deletions.
14 changes: 7 additions & 7 deletions src/pages/chat/SessionList/List/SessionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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' }}>
Expand All @@ -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}
Expand Down
3 changes: 2 additions & 1 deletion src/pages/chat/[id]/Config/ReadMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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>

Expand Down
1 change: 0 additions & 1 deletion src/pages/chat/[id]/Conversation/ChatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const List = () => {
shallow,
);

console.log(data);
return (
<ChatList
data={data}
Expand Down
181 changes: 103 additions & 78 deletions src/store/session/slices/agentConfig/action.ts
Original file line number Diff line number Diff line change
@@ -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;
}

Expand All @@ -38,112 +68,107 @@ export const createAgentSlice: StateCreator<
[],
AgentAction
> = (set, get) => ({
// 使用 AI 自动补齐 Agent 元信息
autoAddAgentName: async (id) => {
const { dispatchSession, updateLoadingState } = get();
autoPickEmoji: async (id) => {
const { dispatchSession } = 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: '...' });
const emoji = await fetchPresetTaskResult({
onLoadingChange: (loading) => {
get().updateLoadingState('pickingEmojiAvatar', loading);
},
params: promptPickEmoji(systemRole),
});

let title = '';
if (emoji) {
dispatchSession({ id, key: 'avatar', type: 'updateSessionMeta', value: emoji });
}
},

await fetchPresetTaskResult({
autocompleteAgentDescription: 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 preValue = session.meta.description;

// 替换为 ...
dispatchSession({ id, key: 'description', type: 'updateSessionMeta', value: '...' });

fetchPresetTaskResult({
onError: () => {
dispatchSession({
id,
key: 'title',
key: 'description',
type: 'updateSessionMeta',
value: previousTitle || systemRole,
value: preValue,
});
},
onLoadingChange: (loading) => {
updateLoadingState('summarizingTitle', loading);
},
onMessageHandle: (text) => {
title += text;
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: title });
updateLoadingState('summarizingDescription', loading);
},
params: promptSummaryAgentName(systemRole),
onMessageHandle: internalUpdateAgentMeta(id)('description'),
params: promptSummaryDescription(chats),
});
},

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,
});
};
};
autocompleteAgentTitle: async (id) => {
const { dispatchSession, updateLoadingState, internalUpdateAgentMeta } = get();
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;

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),
});
}
},
if (chats.length <= 0) return;

autoPickEmoji: async (id) => {
const { dispatchSession } = 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: '...' });

const emoji = await fetchPresetTaskResult({
fetchPresetTaskResult({
onError: () => {
dispatchSession({ id, key: 'title', type: 'updateSessionMeta', value: previousTitle });
},
onLoadingChange: (loading) => {
get().updateLoadingState('pickingEmojiAvatar', loading);
updateLoadingState('summarizingTitle', loading);
},
params: promptPickEmoji(systemRole),
onMessageHandle: internalUpdateAgentMeta(id)('title'),
params: promptSummaryTitle(chats),
});

if (emoji) {
dispatchSession({ id, key: 'avatar', type: 'updateSessionMeta', value: emoji });
}
},
autocompleteAgentMeta: async (id) => {

autocompleteSessionAgentMeta: (id) => {
const session = sessionSelectors.getSessionById(id)(get());
if (!session) return;

// 没有title 就补充 title
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;

Expand Down
4 changes: 3 additions & 1 deletion src/store/session/slices/agentConfig/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 中间态
Expand Down
6 changes: 3 additions & 3 deletions src/store/session/slices/agentConfig/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) => {
Expand Down
7 changes: 6 additions & 1 deletion src/store/session/slices/chat/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -201,5 +201,10 @@ export const createChatSlice: StateCreator<
item.scrollIntoView({ behavior: 'smooth' });
},
});

const chats = chatSelectors.currentChats(get());
if (chats.length >= 4) {
autocompleteSessionAgentMeta(session.id);
}
},
});
4 changes: 1 addition & 3 deletions src/store/session/slices/session/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ export const createSessionSlice: StateCreator<
},
createAt: timestamp,
id: uuid(),
meta: {
title: '默认对话',
},
meta: {},
type: LobeSessionType.Agent,
updateAt: timestamp,
};
Expand Down
4 changes: 2 additions & 2 deletions src/store/session/slices/session/selectors/chat.ts
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit a82f35d

Please sign in to comment.