mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-28 15:27:03 +02:00
fix(ai-builder): Format user message to avoid markdown formatting errors (#21033)
This commit is contained in:
parent
8abc04eb88
commit
70523e19c8
|
|
@ -146,14 +146,37 @@ export async function* createStreamProcessor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove context tags from message content that are used for AI context
|
||||
* but shouldn't be displayed to users
|
||||
*/
|
||||
function cleanContextTags(text: string): string {
|
||||
return text.replace(/\n*<current_workflow_json>[\s\S]*?<\/current_execution_nodes_schemas>/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a HumanMessage into the expected output format
|
||||
*/
|
||||
function formatHumanMessage(msg: HumanMessage): Record<string, unknown> {
|
||||
// Handle array content (multi-part messages with text, images, etc.)
|
||||
if (Array.isArray(msg.content)) {
|
||||
const textParts = msg.content.filter(
|
||||
(c): c is { type: string; text: string } =>
|
||||
typeof c === 'object' && c !== null && 'type' in c && c.type === 'text' && 'text' in c,
|
||||
);
|
||||
const text = textParts.map((part) => cleanContextTags(part.text)).join('\n');
|
||||
return {
|
||||
role: 'user',
|
||||
type: 'message',
|
||||
text,
|
||||
};
|
||||
}
|
||||
|
||||
// Handle simple string content
|
||||
return {
|
||||
role: 'user',
|
||||
type: 'message',
|
||||
text: msg.content,
|
||||
text: cleanContextTags(msg.content),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,82 @@ describe('stream-processor', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should format HumanMessage with array content (multi-part messages)', () => {
|
||||
const messages = [
|
||||
new HumanMessage({
|
||||
content: [
|
||||
{ type: 'text', text: 'Part 1' },
|
||||
{ type: 'text', text: 'Part 2' },
|
||||
{ type: 'image_url', image_url: 'http://example.com/image.png' },
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
const result = formatMessages(messages);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual({
|
||||
role: 'user',
|
||||
type: 'message',
|
||||
text: 'Part 1\nPart 2',
|
||||
});
|
||||
});
|
||||
|
||||
it('should strip context tags from HumanMessage content', () => {
|
||||
const messageWithContext = `User question here
|
||||
<current_workflow_json>
|
||||
{"nodes": [], "connections": {}}
|
||||
</current_workflow_json>
|
||||
<current_simplified_execution_data>
|
||||
{"runData": {}}
|
||||
</current_simplified_execution_data>
|
||||
<current_execution_nodes_schemas>
|
||||
[{"nodeName": "test"}]
|
||||
</current_execution_nodes_schemas>`;
|
||||
|
||||
const messages = [new HumanMessage(messageWithContext)];
|
||||
|
||||
const result = formatMessages(messages);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual({
|
||||
role: 'user',
|
||||
type: 'message',
|
||||
text: 'User question here',
|
||||
});
|
||||
});
|
||||
|
||||
it('should strip context tags from HumanMessage array content', () => {
|
||||
const messages = [
|
||||
new HumanMessage({
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Workflow executed successfully.
|
||||
<current_workflow_json>
|
||||
{"nodes": []}
|
||||
</current_workflow_json>
|
||||
<current_simplified_execution_data>
|
||||
{"runData": {}}
|
||||
</current_simplified_execution_data>
|
||||
<current_execution_nodes_schemas>
|
||||
[{"nodeName": "Manual Trigger"}]
|
||||
</current_execution_nodes_schemas>`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
const result = formatMessages(messages);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual({
|
||||
role: 'user',
|
||||
type: 'message',
|
||||
text: 'Workflow executed successfully.',
|
||||
});
|
||||
});
|
||||
|
||||
it('should format AIMessage with text content', () => {
|
||||
const messages = [new AIMessage('Response from AI')];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user