Skip to content

Commit 6e40877

Browse files
authored
[Agent Builder] use getAgentDescription from attachment types (elastic#243541)
## Summary We forgot to take into account instructions from attachment type (`getAgentDescription`) in the agent's description. This PR addresses the problem
1 parent 8be031a commit 6e40877

7 files changed

Lines changed: 83 additions & 16 deletions

File tree

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/default/graph.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
errorAction,
3737
handoverAction,
3838
} from './actions';
39+
import type { ProcessedConversation } from '../utils/prepare_conversation';
3940

4041
// number of successive recoverable errors we try to recover from before throwing
4142
const MAX_ERROR_COUNT = 2;
@@ -47,13 +48,15 @@ export const createAgentGraph = ({
4748
capabilities,
4849
logger,
4950
events,
51+
processedConversation,
5052
}: {
5153
chatModel: InferenceChatModel;
5254
tools: StructuredTool[];
5355
capabilities: ResolvedAgentCapabilities;
5456
configuration: ResolvedConfiguration;
5557
logger: Logger;
5658
events: AgentEventEmitter;
59+
processedConversation: ProcessedConversation;
5760
}) => {
5861
const toolNode = new ToolNode<BaseMessage[]>(tools);
5962

@@ -72,6 +75,7 @@ export const createAgentGraph = ({
7275
capabilities,
7376
initialMessages: state.initialMessages,
7477
actions: state.mainActions,
78+
attachmentTypes: processedConversation.attachmentTypes,
7579
})
7680
);
7781

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/default/prompts.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ChartType } from '@kbn/visualization-utils';
1717
import { customInstructionsBlock, formatDate } from './prompts/prompt_helpers';
1818
import type { ResearchAgentAction, AnswerAgentAction } from './actions';
1919
import { formatResearcherActionHistory, formatAnswerActionHistory } from './prompts/format_actions';
20+
import type { ProcessedAttachmentType } from '../utils/prepare_conversation';
2021

2122
const tools = {
2223
indexExplorer: sanitizeToolId(platformCoreTools.indexExplorer),
@@ -29,11 +30,13 @@ export const getActPrompt = ({
2930
capabilities,
3031
initialMessages,
3132
actions,
33+
attachmentTypes,
3234
}: {
3335
customInstructions?: string;
3436
capabilities: ResolvedAgentCapabilities;
3537
initialMessages: BaseMessageLike[];
3638
actions: ResearchAgentAction[];
39+
attachmentTypes: ProcessedAttachmentType[];
3740
}): BaseMessageLike[] => {
3841
return [
3942
[
@@ -126,6 +129,8 @@ Constraints:
126129
127130
${customInstructionsBlock(customInstructions)}
128131
132+
${renderAttachmentTypeInstructions(attachmentTypes)}
133+
129134
## ADDITIONAL INFO
130135
- Current date: ${formatDate()}
131136
@@ -243,3 +248,23 @@ function renderVisualizationPrompt() {
243248
To visualize this response as a bar chart your reply should be:
244249
<${tagName} ${attributes.toolResultId}="LiDoF1" ${attributes.chartType}="${ChartType.Bar}"/>`;
245250
}
251+
252+
const renderAttachmentTypeInstructions = (attachmentTypes: ProcessedAttachmentType[]): string => {
253+
if (attachmentTypes.length === 0) {
254+
return '';
255+
}
256+
257+
const perTypeInstructions = attachmentTypes.map(({ type, agentDescription }) => {
258+
return `### ${type} attachments
259+
260+
${agentDescription ?? 'No instructions available.'}
261+
`;
262+
});
263+
264+
return `## ATTACHMENT TYPES
265+
266+
The current conversation contains attachments. Here is the list of attachment types present in the conversation and their corresponding instructions:
267+
268+
${perTypeInstructions.join('\n\n')}
269+
`;
270+
};

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/default/run_chat_agent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const runDefaultAgentMode: RunChatAgentFn = async (
112112
tools: allTools,
113113
configuration: resolvedConfiguration,
114114
capabilities: resolvedCapabilities,
115+
processedConversation,
115116
});
116117

117118
logger.debug(`Running chat agent with graph: ${chatAgentGraphName}, runId: ${runId}`);

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/utils/prepare_conversation.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ describe('prepareConversation', () => {
8383
});
8484

8585
expect(result).toEqual({
86+
attachmentTypes: [],
8687
nextInput: {
8788
message: 'Hello',
8889
attachments: [],
@@ -145,7 +146,7 @@ describe('prepareConversation', () => {
145146
});
146147

147148
expect(mockGetToolResultId).toHaveBeenCalledTimes(1);
148-
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(1);
149+
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(2);
149150
});
150151

151152
it('should preserve existing ID for attachment with ID', async () => {
@@ -182,7 +183,7 @@ describe('prepareConversation', () => {
182183
});
183184

184185
expect(mockGetToolResultId).not.toHaveBeenCalled();
185-
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(1);
186+
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(2);
186187
});
187188

188189
it('should process multiple attachments', async () => {
@@ -371,7 +372,7 @@ describe('prepareConversation', () => {
371372
representation: mockRepresentation,
372373
});
373374

374-
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(1);
375+
expect(mockAttachmentsService.getTypeDefinition).toHaveBeenCalledTimes(2);
375376
});
376377

377378
it('should process multiple previous rounds', async () => {

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/utils/prepare_conversation.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export interface ProcessedAttachment {
1717
representation: AttachmentRepresentation;
1818
}
1919

20+
export interface ProcessedAttachmentType {
21+
type: string;
22+
agentDescription?: string;
23+
}
24+
2025
export interface ProcessedRoundInput {
2126
message: string;
2227
attachments: ProcessedAttachment[];
@@ -29,6 +34,7 @@ export type ProcessedConversationRound = Omit<ConversationRound, 'input'> & {
2934
export interface ProcessedConversation {
3035
previousRounds: ProcessedConversationRound[];
3136
nextInput: ProcessedRoundInput;
37+
attachmentTypes: ProcessedAttachmentType[];
3238
}
3339

3440
export const prepareConversation = async ({
@@ -41,13 +47,37 @@ export const prepareConversation = async ({
4147
attachmentsService: AttachmentsService;
4248
}): Promise<ProcessedConversation> => {
4349
const processedNextInput = await prepareRoundInput({ input: nextInput, attachmentsService });
50+
const processedRounds = await Promise.all(
51+
previousRounds.map((round) => {
52+
return prepareRound({ round, attachmentsService });
53+
})
54+
);
55+
56+
const attachmentTypeIds = [
57+
...new Set<string>([
58+
...processedNextInput.attachments.map((attachment) => attachment.attachment.type),
59+
...processedRounds.flatMap((round) =>
60+
round.input.attachments.map((attachment) => attachment.attachment.type)
61+
),
62+
]),
63+
];
64+
65+
const attachmentTypes = await Promise.all(
66+
attachmentTypeIds.map<Promise<ProcessedAttachmentType>>(async (type) => {
67+
const definition = attachmentsService.getTypeDefinition(type);
68+
const description = definition?.getAgentDescription?.() ?? '';
69+
70+
return {
71+
type,
72+
description,
73+
};
74+
})
75+
);
76+
4477
return {
4578
nextInput: processedNextInput,
46-
previousRounds: await Promise.all(
47-
previousRounds.map((round) => {
48-
return prepareRound({ round, attachmentsService });
49-
})
50-
),
79+
previousRounds: processedRounds,
80+
attachmentTypes,
5181
};
5282
};
5383

x-pack/platform/plugins/shared/onechat/server/services/agents/modes/utils/to_langchain_messages.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ describe('conversationLangchainMessages', () => {
9191
it('returns only the user message if no previous rounds', () => {
9292
const nextInput = makeRoundInput('hello');
9393
const result = conversationToLangchainMessages({
94-
conversation: { previousRounds: [], nextInput },
94+
conversation: { previousRounds: [], nextInput, attachmentTypes: [] },
9595
});
9696
expect(result).toHaveLength(1);
9797
expect(isHumanMessage(result[0])).toBe(true);
@@ -112,7 +112,7 @@ describe('conversationLangchainMessages', () => {
112112
];
113113
const nextInput = makeRoundInput('how are you?');
114114
const result = conversationToLangchainMessages({
115-
conversation: { previousRounds, nextInput },
115+
conversation: { previousRounds, nextInput, attachmentTypes: [] },
116116
});
117117

118118
expect(result).toHaveLength(3);
@@ -149,7 +149,7 @@ describe('conversationLangchainMessages', () => {
149149
];
150150
const nextInput = makeRoundInput('next');
151151
const result = conversationToLangchainMessages({
152-
conversation: { previousRounds, nextInput },
152+
conversation: { previousRounds, nextInput, attachmentTypes: [] },
153153
});
154154
// 1 user + 1 tool call (AI + Tool) + 1 assistant + 1 user
155155
expect(result).toHaveLength(5);
@@ -215,7 +215,7 @@ describe('conversationLangchainMessages', () => {
215215
];
216216
const nextInput = makeRoundInput('bye');
217217
const result = conversationToLangchainMessages({
218-
conversation: { previousRounds, nextInput },
218+
conversation: { previousRounds, nextInput, attachmentTypes: [] },
219219
});
220220
// 1 user + 1 assistant + 1 user + 1 tool call (AI + Tool) + 1 assistant + 1 user
221221
expect(result).toHaveLength(7);
@@ -274,7 +274,7 @@ describe('conversationLangchainMessages', () => {
274274
];
275275
const nextInput = makeRoundInput('next');
276276
const result = conversationToLangchainMessages({
277-
conversation: { previousRounds, nextInput },
277+
conversation: { previousRounds, nextInput, attachmentTypes: [] },
278278
});
279279
// 1 user + 1 tool call (AI + Tool) + 1 assistant + 1 user
280280
expect(result).toHaveLength(5);
@@ -295,7 +295,7 @@ describe('conversationLangchainMessages', () => {
295295
);
296296
const nextInput = makeRoundInput('hello with attachment', [attachment]);
297297
const result = conversationToLangchainMessages({
298-
conversation: { previousRounds: [], nextInput },
298+
conversation: { previousRounds: [], nextInput, attachmentTypes: [] },
299299
});
300300

301301
expect(result).toHaveLength(1);
@@ -326,7 +326,7 @@ describe('conversationLangchainMessages', () => {
326326
attachment2,
327327
]);
328328
const result = conversationToLangchainMessages({
329-
conversation: { previousRounds: [], nextInput },
329+
conversation: { previousRounds: [], nextInput, attachmentTypes: [] },
330330
});
331331

332332
expect(result).toHaveLength(1);
@@ -361,7 +361,7 @@ describe('conversationLangchainMessages', () => {
361361
];
362362
const nextInput = makeRoundInput('next message');
363363
const result = conversationToLangchainMessages({
364-
conversation: { previousRounds, nextInput },
364+
conversation: { previousRounds, nextInput, attachmentTypes: [] },
365365
});
366366

367367
expect(result).toHaveLength(3);

x-pack/platform/plugins/shared/onechat/server/services/attachments/definitions/esql.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { EsqlAttachmentData } from '@kbn/onechat-common/attachments';
1010
import { AttachmentType, esqlAttachmentDataSchema } from '@kbn/onechat-common/attachments';
1111
import { platformCoreTools } from '@kbn/onechat-common/tools';
1212
import type { AttachmentTypeDefinition } from '@kbn/onechat-server/attachments';
13+
import { sanitizeToolId } from '@kbn/onechat-genai-utils/langchain';
1314

1415
/**
1516
* Creates the definition for the `text` attachment type.
@@ -43,6 +44,11 @@ export const createEsqlAttachmentType = (): AttachmentTypeDefinition<
4344
},
4445
};
4546
},
47+
getAgentDescription: () => {
48+
return `${AttachmentType.esql} can be executed using the ${sanitizeToolId(
49+
platformCoreTools.executeEsql
50+
)} tool`;
51+
},
4652
getTools: () => [platformCoreTools.executeEsql, platformCoreTools.generateEsql],
4753
};
4854
};

0 commit comments

Comments
 (0)