mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
Enhance OpenAI Assistant node with VectorStore and threading capabilities
This commit is contained in:
parent
7cfe56d727
commit
cd995adfe7
|
@ -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',
|
||||
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 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 {
|
||||
baseURL?: string;
|
||||
|
@ -166,6 +211,27 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
|||
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 tools = await getConnectedTools(this, nodeVersion > 1, false);
|
||||
|
@ -210,7 +276,20 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
|||
signal: this.getExecutionCancelSignal(),
|
||||
timeout: options.timeout ?? 10000,
|
||||
};
|
||||
let thread: OpenAIClient.Beta.Threads.Thread;
|
||||
|
||||
let thread: OpenAIClient.Beta.Threads.Thread | undefined;
|
||||
|
||||
if (threadIdInput) {
|
||||
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();
|
||||
|
||||
|
@ -230,12 +309,27 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
|
|||
}
|
||||
|
||||
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' }] }],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let filteredResponse: IDataObject = {};
|
||||
try {
|
||||
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) {
|
||||
await memory.saveContext({ input }, { output: response.output });
|
||||
|
||||
|
|
Loading…
Reference in a new issue