Merge branch 'main' into FEATURE/Vision

# Conflicts:
#	packages/server/src/index.ts
#	packages/ui/src/views/chatmessage/ChatMessage.js
This commit is contained in:
vinodkiran
2023-12-15 13:26:49 +05:30
28 changed files with 1734 additions and 45 deletions
@@ -8,6 +8,7 @@ import * as path from 'node:path'
import fetch from 'node-fetch'
import { flatten, uniqWith, isEqual } from 'lodash'
import { zodToJsonSchema } from 'zod-to-json-schema'
import { AnalyticHandler } from '../../../src/handler'
class OpenAIAssistant_Agents implements INode {
label: string
@@ -149,6 +150,11 @@ class OpenAIAssistant_Agents implements INode {
const openai = new OpenAI({ apiKey: openAIApiKey })
// Start analytics
const analyticHandlers = new AnalyticHandler(nodeData, options)
await analyticHandlers.init()
const parentIds = await analyticHandlers.onChainStart('OpenAIAssistant', input)
try {
const assistantDetails = JSON.parse(assistant.details)
const openAIAssistantId = assistantDetails.id
@@ -171,7 +177,8 @@ class OpenAIAssistant_Agents implements INode {
}
const chatmessage = await appDataSource.getRepository(databaseEntities['ChatMessage']).findOneBy({
chatId: options.chatId
chatId: options.chatId,
chatflowid: options.chatflowid
})
let threadId = ''
@@ -185,7 +192,7 @@ class OpenAIAssistant_Agents implements INode {
threadId = thread.id
}
// List all runs
// List all runs, in case existing thread is still running
if (!isNewThread) {
const promise = (threadId: string) => {
return new Promise<void>((resolve) => {
@@ -221,6 +228,7 @@ class OpenAIAssistant_Agents implements INode {
})
// Run assistant thread
const llmIds = await analyticHandlers.onLLMStart('ChatOpenAI', input, parentIds)
const runThread = await openai.beta.threads.runs.create(threadId, {
assistant_id: retrievedAssistant.id
})
@@ -253,7 +261,15 @@ class OpenAIAssistant_Agents implements INode {
for (let i = 0; i < actions.length; i += 1) {
const tool = tools.find((tool: any) => tool.name === actions[i].tool)
if (!tool) continue
// Start tool analytics
const toolIds = await analyticHandlers.onToolStart(tool.name, actions[i].toolInput, parentIds)
const toolOutput = await tool.call(actions[i].toolInput)
// End tool analytics
await analyticHandlers.onToolEnd(toolIds, toolOutput)
submitToolOutputs.push({
tool_call_id: actions[i].toolCallId,
output: toolOutput
@@ -302,7 +318,9 @@ class OpenAIAssistant_Agents implements INode {
runThreadId = newRunThread.id
state = await promise(threadId, newRunThread.id)
} else {
throw new Error(`Error processing thread: ${state}, Thread ID: ${threadId}`)
const errMsg = `Error processing thread: ${state}, Thread ID: ${threadId}`
await analyticHandlers.onChainError(parentIds, errMsg)
throw new Error(errMsg)
}
}
@@ -387,11 +405,18 @@ class OpenAIAssistant_Agents implements INode {
const bitmap = fsDefault.readFileSync(filePath)
const base64String = Buffer.from(bitmap).toString('base64')
// TODO: Use a file path and retrieve image on the fly. Storing as base64 to localStorage and database will easily hit limits
const imgHTML = `<img src="data:image/png;base64,${base64String}" width="100%" height="max-content" alt="${fileObj.filename}" /><br/>`
returnVal += imgHTML
}
}
const imageRegex = /<img[^>]*\/>/g
let llmOutput = returnVal.replace(imageRegex, '')
llmOutput = llmOutput.replace('<br/>', '')
await analyticHandlers.onLLMEnd(llmIds, llmOutput)
await analyticHandlers.onChainEnd(parentIds, messageData, true)
return {
text: returnVal,
usedTools,
@@ -399,6 +424,7 @@ class OpenAIAssistant_Agents implements INode {
assistant: { assistantId: openAIAssistantId, threadId, runId: runThreadId, messages: messageData }
}
} catch (error) {
await analyticHandlers.onChainError(parentIds, error, true)
throw new Error(error)
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ class RedisCache implements INode {
redisClient.update = async (prompt: string, llmKey: string, value: Generation[]) => {
for (let i = 0; i < value.length; i += 1) {
const key = getCacheKey(prompt, llmKey, String(i))
if (ttl !== undefined) {
if (ttl) {
await client.set(key, JSON.stringify(serializeGeneration(value[i])), 'EX', parseInt(ttl, 10))
} else {
await client.set(key, JSON.stringify(serializeGeneration(value[i])))
@@ -162,8 +162,11 @@ class S3_DocumentLoaders implements INode {
accessKeyId?: string
secretAccessKey?: string
} = {
accessKeyId,
secretAccessKey
region,
credentials: {
accessKeyId,
secretAccessKey
}
}
loader.load = async () => {
@@ -18,7 +18,7 @@ class HydeRetriever_Retrievers implements INode {
constructor() {
this.label = 'Hyde Retriever'
this.name = 'HydeRetriever'
this.version = 1.0
this.version = 2.0
this.type = 'HydeRetriever'
this.icon = 'hyderetriever.svg'
this.category = 'Retrievers'
@@ -36,41 +36,66 @@ class HydeRetriever_Retrievers implements INode {
type: 'VectorStore'
},
{
label: 'Prompt Key',
label: 'Select Defined Prompt',
name: 'promptKey',
description: 'Select a pre-defined prompt',
type: 'options',
options: [
{
label: 'websearch',
name: 'websearch'
name: 'websearch',
description: `Please write a passage to answer the question
Question: {question}
Passage:`
},
{
label: 'scifact',
name: 'scifact'
name: 'scifact',
description: `Please write a scientific paper passage to support/refute the claim
Claim: {question}
Passage:`
},
{
label: 'arguana',
name: 'arguana'
name: 'arguana',
description: `Please write a counter argument for the passage
Passage: {question}
Counter Argument:`
},
{
label: 'trec-covid',
name: 'trec-covid'
name: 'trec-covid',
description: `Please write a scientific paper passage to answer the question
Question: {question}
Passage:`
},
{
label: 'fiqa',
name: 'fiqa'
name: 'fiqa',
description: `Please write a financial article passage to answer the question
Question: {question}
Passage:`
},
{
label: 'dbpedia-entity',
name: 'dbpedia-entity'
name: 'dbpedia-entity',
description: `Please write a passage to answer the question.
Question: {question}
Passage:`
},
{
label: 'trec-news',
name: 'trec-news'
name: 'trec-news',
description: `Please write a news passage about the topic.
Topic: {question}
Passage:`
},
{
label: 'mr-tydi',
name: 'mr-tydi'
name: 'mr-tydi',
description: `Please write a passage in Swahili/Korean/Japanese/Bengali to answer the question in detail.
Question: {question}
Passage:`
}
],
default: 'websearch'
@@ -78,7 +103,7 @@ class HydeRetriever_Retrievers implements INode {
{
label: 'Custom Prompt',
name: 'customPrompt',
description: 'If custom prompt is used, this will override Prompt Key',
description: 'If custom prompt is used, this will override Defined Prompt',
placeholder: 'Please write a passage to answer the question\nQuestion: {question}\nPassage:',
type: 'string',
rows: 4,