mirror of
https://github.com/n8n-io/n8n.git
synced 2024-09-20 06:47:32 -07:00
Merge cd995adfe7
into f5474ff791
This commit is contained in:
commit
0c140bf19a
|
@ -63,6 +63,46 @@ const properties: INodeProperties[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Thread',
|
||||||
|
name: 'thread',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Optional thread ID to associate with the assistant call',
|
||||||
|
placeholder: 'thread_mkSDM5vaYA8amDY9vvJTJRW8',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Vector',
|
||||||
|
name: 'vector',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Optional vector store ID to associate with the file call',
|
||||||
|
placeholder: 'vs_Z1YPXu95Cy8Ul954tejtQyrW',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'File',
|
||||||
|
name: 'file',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Optional file ID to associate with the thread call',
|
||||||
|
placeholder: 'file-NSjtwlxIpfxIi3T6f8Uh3EdD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Role',
|
||||||
|
name: 'role',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Use user or assistant',
|
||||||
|
placeholder: 'Role (user or assistant) for content input to associate with the file call',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Content',
|
||||||
|
name: 'content',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Prompt content input to associate with the file call',
|
||||||
|
placeholder: 'Describe what is in this document.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Connect your own custom n8n tools to this node on the canvas',
|
displayName: 'Connect your own custom n8n tools to this node on the canvas',
|
||||||
name: 'noticeTools',
|
name: 'noticeTools',
|
||||||
|
@ -151,6 +191,11 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
||||||
}
|
}
|
||||||
|
|
||||||
const assistantId = this.getNodeParameter('assistantId', i, '', { extractValue: true }) as string;
|
const assistantId = this.getNodeParameter('assistantId', i, '', { extractValue: true }) as string;
|
||||||
|
const threadIdInput = this.getNodeParameter('thread', i, undefined) as string | undefined;
|
||||||
|
const vectorStoreId = this.getNodeParameter('vector', i) as string | undefined;
|
||||||
|
const fileId = this.getNodeParameter('file', i) as string | undefined;
|
||||||
|
const content = this.getNodeParameter('content', i) as string | undefined;
|
||||||
|
const role = this.getNodeParameter('role', i) as string | undefined;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i, {}) as {
|
const options = this.getNodeParameter('options', i, {}) as {
|
||||||
baseURL?: string;
|
baseURL?: string;
|
||||||
|
@ -166,6 +211,27 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
||||||
baseURL: options.baseURL,
|
baseURL: options.baseURL,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let vectorStoreToUpdate = vectorStoreId;
|
||||||
|
let vectorStoreAction = 'used'; // Assume we are using an existing vector_store_id
|
||||||
|
|
||||||
|
if (fileId && !vectorStoreId) {
|
||||||
|
// Create a new vector store and add the fileId to it
|
||||||
|
const newVectorStore = await client.beta.vectorStores.create({});
|
||||||
|
await client.beta.vectorStores.files.createAndPoll(newVectorStore.id, { file_id: fileId });
|
||||||
|
vectorStoreToUpdate = newVectorStore.id;
|
||||||
|
vectorStoreAction = 'created'; // Update to indicate that vector_store_id was created
|
||||||
|
} else if (fileId && vectorStoreId) {
|
||||||
|
// Add the fileId to the existing vector store
|
||||||
|
await client.beta.vectorStores.files.createAndPoll(vectorStoreId, { file_id: fileId });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vectorStoreToUpdate) {
|
||||||
|
// Update the assistant with the vectorStoreId
|
||||||
|
await client.beta.assistants.update(assistantId, {
|
||||||
|
tool_resources: { file_search: { vector_store_ids: [vectorStoreToUpdate] } },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const agent = new OpenAIAssistantRunnable({ assistantId, client, asAgent: true });
|
const agent = new OpenAIAssistantRunnable({ assistantId, client, asAgent: true });
|
||||||
|
|
||||||
const tools = await getConnectedTools(this, nodeVersion > 1, false);
|
const tools = await getConnectedTools(this, nodeVersion > 1, false);
|
||||||
|
@ -210,32 +276,60 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
||||||
signal: this.getExecutionCancelSignal(),
|
signal: this.getExecutionCancelSignal(),
|
||||||
timeout: options.timeout ?? 10000,
|
timeout: options.timeout ?? 10000,
|
||||||
};
|
};
|
||||||
let thread: OpenAIClient.Beta.Threads.Thread;
|
|
||||||
if (memory) {
|
|
||||||
const chatMessages = await memory.chatHistory.getMessages();
|
|
||||||
|
|
||||||
// Construct a new thread from the chat history to map the memory
|
let thread: OpenAIClient.Beta.Threads.Thread | undefined;
|
||||||
if (chatMessages.length) {
|
|
||||||
const first32Messages = chatMessages.slice(0, 32);
|
|
||||||
// There is a undocumented limit of 32 messages per thread when creating a thread with messages
|
|
||||||
const mappedMessages: OpenAIClient.Beta.Threads.ThreadCreateParams.Message[] =
|
|
||||||
first32Messages.map(mapChatMessageToThreadMessage);
|
|
||||||
|
|
||||||
thread = await client.beta.threads.create({ messages: mappedMessages });
|
if (threadIdInput) {
|
||||||
const overLimitMessages = chatMessages.slice(32).map(mapChatMessageToThreadMessage);
|
chainValues.threadId = threadIdInput;
|
||||||
|
if (fileId ?? content ?? role) {
|
||||||
|
// Add message with file attachment to the existing thread
|
||||||
|
await client.beta.threads.messages.create(threadIdInput, {
|
||||||
|
role: role as 'assistant',
|
||||||
|
content: content as 'Describe what is in this document.',
|
||||||
|
attachments: [{ file_id: fileId, tools: [{ type: 'file_search' }] }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (memory) {
|
||||||
|
const chatMessages = await memory.chatHistory.getMessages();
|
||||||
|
|
||||||
// Send the remaining messages that exceed the limit of 32 sequentially
|
// Construct a new thread from the chat history to map the memory
|
||||||
for (const message of overLimitMessages) {
|
if (chatMessages.length) {
|
||||||
await client.beta.threads.messages.create(thread.id, message);
|
const first32Messages = chatMessages.slice(0, 32);
|
||||||
|
// There is a undocumented limit of 32 messages per thread when creating a thread with messages
|
||||||
|
const mappedMessages: OpenAIClient.Beta.Threads.ThreadCreateParams.Message[] =
|
||||||
|
first32Messages.map(mapChatMessageToThreadMessage);
|
||||||
|
|
||||||
|
thread = await client.beta.threads.create({ messages: mappedMessages });
|
||||||
|
const overLimitMessages = chatMessages.slice(32).map(mapChatMessageToThreadMessage);
|
||||||
|
|
||||||
|
// Send the remaining messages that exceed the limit of 32 sequentially
|
||||||
|
for (const message of overLimitMessages) {
|
||||||
|
await client.beta.threads.messages.create(thread.id, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
chainValues.threadId = thread.id;
|
||||||
|
if (fileId ?? content ?? role) {
|
||||||
|
// Include the file attachment in the newly created thread
|
||||||
|
await client.beta.threads.messages.create(thread.id, {
|
||||||
|
role: role as 'assistant',
|
||||||
|
content: content as 'Describe what is in this document.',
|
||||||
|
attachments: [{ file_id: fileId, tools: [{ type: 'file_search' }] }],
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chainValues.threadId = thread.id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let filteredResponse: IDataObject = {};
|
let filteredResponse: IDataObject = {};
|
||||||
try {
|
try {
|
||||||
const response = await agentExecutor.withConfig(getTracingConfig(this)).invoke(chainValues);
|
const response = await agentExecutor.withConfig(getTracingConfig(this)).invoke(chainValues);
|
||||||
|
|
||||||
|
// Add vector_store_id and the action performed (created/used) to the response
|
||||||
|
response.vectorStoreId = vectorStoreToUpdate;
|
||||||
|
response.vectorStoreAction = vectorStoreAction;
|
||||||
|
response.fileId = fileId;
|
||||||
|
|
||||||
if (memory) {
|
if (memory) {
|
||||||
await memory.saveContext({ input }, { output: response.output });
|
await memory.saveContext({ input }, { output: response.output });
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue