Skip to content

Commit 0cda803

Browse files
committed
opti: Better prompt
1 parent f1746a5 commit 0cda803

File tree

4 files changed

+51
-77
lines changed

4 files changed

+51
-77
lines changed

packages/prompts/src/prompts/groupChat/index.test.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
33
import type { ChatMessage } from '@/types/index';
44

55
import { filterMessagesForAgent } from '../chatMessages';
6-
import { buildAgentResponsePrompt, buildGroupChatSystemPrompt } from './index';
6+
import { buildGroupChatSystemPrompt } from './index';
77

88
describe('buildGroupChatSystemPrompt', () => {
99
const baseSystemRole = 'You are an expert collaborator.';
@@ -57,22 +57,42 @@ describe('buildGroupChatSystemPrompt', () => {
5757

5858
expect(result).toMatchSnapshot();
5959
});
60-
});
6160

62-
describe('buildAgentResponsePrompt', () => {
63-
it('should generate prompt for group message', () => {
64-
const result = buildAgentResponsePrompt({});
65-
expect(result).toMatchSnapshot();
61+
it('should include response instruction for group message', () => {
62+
const result = buildGroupChatSystemPrompt({
63+
agentId: 'agent-1',
64+
baseSystemRole,
65+
groupMembers: [{ id: 'agent-1', title: 'Agent One' }],
66+
messages,
67+
});
68+
69+
expect(result).toContain("Now it's your turn to respond");
70+
expect(result).toContain('the group publicly');
6671
});
6772

68-
it('should generate prompt for direct message to agent', () => {
69-
const result = buildAgentResponsePrompt({ targetId: 'agent-1' });
70-
expect(result).toMatchSnapshot();
73+
it('should include response instruction for direct message', () => {
74+
const result = buildGroupChatSystemPrompt({
75+
agentId: 'agent-1',
76+
baseSystemRole,
77+
groupMembers: [{ id: 'agent-1', title: 'Agent One' }],
78+
messages,
79+
targetId: 'user',
80+
});
81+
82+
expect(result).toContain("Now it's your turn to respond");
83+
expect(result).toContain('user');
7184
});
7285

73-
it('should generate prompt for direct message to user', () => {
74-
const result = buildAgentResponsePrompt({ targetId: 'user' });
75-
expect(result).toMatchSnapshot();
86+
it('should include supervisor instruction when provided', () => {
87+
const result = buildGroupChatSystemPrompt({
88+
agentId: 'agent-1',
89+
baseSystemRole,
90+
groupMembers: [{ id: 'agent-1', title: 'Agent One' }],
91+
messages,
92+
instruction: 'Please be concise',
93+
});
94+
95+
expect(result).toContain('SUPERVISOR INSTRUCTION: Please be concise');
7696
});
7797
});
7898

packages/prompts/src/prompts/groupChat/index.ts

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,27 @@ const buildGroupMembersTag = (members: GroupMemberInfo[]): string => {
1616
return `<group_members>\n${JSON.stringify(members, null, 2)}\n</group_members>`;
1717
};
1818

19-
const buildChatHistoryAuthorTag = (messages: ChatMessage[], members: GroupMemberInfo[]): string => {
20-
if (!messages || messages.length === 0) return '';
21-
22-
const idToTitle = new Map(members.map((m) => [m.id, m.title]));
23-
24-
const authorLines = messages
25-
.map((message, index) => {
26-
let author: string;
27-
if (message.role === 'user') {
28-
author = idToTitle.get('user') || 'User';
29-
} else if (message.agentId) {
30-
author = idToTitle.get(message.agentId) || 'Assistant';
31-
} else {
32-
author = 'Assistant';
33-
}
34-
return `${index + 1}: ${author}`;
35-
})
36-
.join('\n');
37-
38-
return `<chat_history_author>\n${authorLines}\n</chat_history_author>`;
39-
};
40-
4119
export const buildGroupChatSystemPrompt = ({
4220
baseSystemRole = '',
4321
agentId,
4422
groupMembers,
45-
messages,
23+
targetId,
24+
instruction,
4625
}: {
4726
agentId: string;
4827
baseSystemRole?: string;
4928
groupMembers: GroupMemberInfo[];
29+
instruction?: string;
5030
messages: ChatMessage[];
31+
targetId?: string;
5132
}): string => {
5233
const membersTag = buildGroupMembersTag(groupMembers);
53-
const historyTag = buildChatHistoryAuthorTag(messages, groupMembers);
5434

5535
const agentTitle = groupMembers.find((m) => m.id === agentId)?.title || 'Agent';
5636

5737
const guidelines = [
58-
`Stay in character as ${agentId}`,
38+
`Stay in character as ${agentId} (${agentTitle})`,
5939
'Be concise and natural, behave like a real person',
60-
'Engage naturally in the conversation flow',
6140
"The group supervisor will decide whether to send it privately or publicly, so you just need to say the actuall content, even it's a DM to a specific member. Do not pretend you've sent it.",
6241
"Be collaborative and build upon others' responses when appropriate",
6342
'Keep your responses concise and relevant to the ongoing discussion',
@@ -67,14 +46,17 @@ export const buildGroupChatSystemPrompt = ({
6746
'\n',
6847
);
6948

70-
const sections = [
71-
baseSystemRole,
72-
`You are participating in a group chat in real world as ${agentId} (${agentTitle}).`,
73-
guidelinesSection,
74-
];
49+
const sections = [baseSystemRole, guidelinesSection];
7550

7651
if (membersTag) sections.push(membersTag);
77-
if (historyTag) sections.push(historyTag);
52+
53+
// Add response instruction at the end
54+
const targetText = targetId ? targetId : 'the group publicly';
55+
const instructionText = instruction ? `SUPERVISOR INSTRUCTION: ${instruction}` : '';
56+
const responseInstruction =
57+
`Now it's your turn to respond. ${instructionText} You are sending message to ${targetText}. Please respond as this agent would, considering the full conversation history provided above. Directly return the message content, no other text. You do not need add author name or anything else.`.trim();
58+
59+
sections.push(responseInstruction);
7860

7961
return sections.filter(Boolean).join('\n\n').trim();
8062
};
@@ -150,6 +132,7 @@ ${todoListTag}
150132
151133
RULES:
152134
135+
- Do not forcing user to respond, only ask for information for one time before you get the information you need.
153136
- Make the group conversation feels like a real conversation.
154137
155138
WHEN ASKING AGENTS TO SPEAK:
@@ -176,28 +159,7 @@ ${
176159
return prompt.trim();
177160
};
178161

179-
/**
180-
* Build the prompt for agents to respond in group chat context
181-
* This is the most impressive prompt since it's the last message
182-
*/
183-
export const buildAgentResponsePrompt = ({
184-
targetId,
185-
instruction,
186-
}: {
187-
instruction?: string;
188-
targetId?: string;
189-
}): string => {
190-
const targetText = targetId ? targetId : 'the group publicly';
191-
const instructionText = instruction ? `SUPERVISOR INSTRUCTION: ${instruction}` : '';
192-
193-
return `
194-
${instructionText}
195-
196-
Now it's your turn to respond. You are sending message to ${targetText}. Please respond as this agent would, considering the full conversation history provided above. Directly return the message content, no other text. You do not need add author name or anything else.`.trim();
197-
};
198-
199162
export const groupChatPrompts = {
200-
buildAgentResponsePrompt,
201163
buildGroupChatSystemPrompt,
202164
buildSupervisorPrompt,
203165
};

src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Disable the auto sort key eslint rule to make the code more logic and readable
33
import {
44
GroupMemberInfo,
5-
buildAgentResponsePrompt,
65
buildGroupChatSystemPrompt,
76
filterMessagesForAgent,
87
} from '@lobechat/prompts';
@@ -646,6 +645,8 @@ export const chatAiGroupChat: StateCreator<
646645
baseSystemRole,
647646
agentId,
648647
messages,
648+
targetId,
649+
instruction,
649650
});
650651

651652
// Create agent message using real agent config
@@ -674,15 +675,6 @@ export const chatAiGroupChat: StateCreator<
674675
meta: {},
675676
};
676677

677-
const userMessage: ChatMessage = {
678-
id: 'group-user',
679-
role: 'user',
680-
content: buildAgentResponsePrompt({ targetId, instruction }),
681-
createdAt: Date.now(),
682-
updatedAt: Date.now(),
683-
meta: {},
684-
};
685-
686678
// Add author names to messages for better context
687679
const messagesWithAuthors = messages.map((msg) => {
688680
const authorInfo = agentTitleMap.find((member) =>
@@ -705,7 +697,7 @@ export const chatAiGroupChat: StateCreator<
705697
});
706698

707699
// TODO: Use context engineering
708-
const messagesForAPI = [systemMessage, ...messagesWithAuthors, userMessage];
700+
const messagesForAPI = [systemMessage, ...messagesWithAuthors];
709701

710702
if (assistantId) {
711703
const { isFunctionCall } = await internal_fetchAIChatMessage({

src/store/chat/slices/message/supervisor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class GroupChatSupervisor {
134134
},
135135
{
136136
description:
137-
'Wait for user input. Use this when the conversation has naturally concluded or agents are waiting for user input.',
137+
'Wait for user input. Use this when the conversation history looks likes fine for now, or agents are waiting for user input.',
138138
name: 'wait_for_user_input',
139139
parameters: {
140140
properties: {

0 commit comments

Comments
 (0)