langchain-ai / langchainjs

🦜🔗 Build context-aware reasoning applications 🦜🔗
https://js.langchain.com/docs/
MIT License
12.24k stars 2.07k forks source link

Field "chat_history" in prompt uses a MessagesPlaceholder #4117

Closed RedouanAssakali closed 4 months ago

RedouanAssakali commented 7 months ago

@dosu-bot we already had a conversation about this:

Error occurred: Error [InputFormatError]: Error: Field "chat_history" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received:

const {OpenAI} = require('langchain/llms/openai'); const {initializeAgentExecutorWithOptions} = require('langchain/agents');

const {PineconeStore} = require('langchain/vectorstores/pinecone'); const {OpenAIEmbeddings} = require('langchain/embeddings/openai'); const admin = require("firebase-admin"); const {Pinecone} = require('@pinecone-database/pinecone');

const {BufferMemory} = require('langchain/memory'); // Import BufferMemory const {FirestoreChatMessageHistory} = require('langchain/stores/message/firestore'); // Import FirestoreChatMessageHistory const {PromptTemplate} = require("langchain/prompts");

const {ChainTool} = require("langchain/tools"); const {ConversationalRetrievalQAChain} = require('langchain/chains'); const {response} = require("express"); const {ChatOpenAI} = require("@langchain/openai");

const CONDENSE_PROMPT = `Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.

Chat History: {chat_history} Follow Up Input: {question} Standalone question:

`;

const QA_PROMPT = `You are {author}. Use the following pieces of context to answer the question at the end.

{context} Question: {question} Helpful answer ALWAYS output in markdown!!!

`;

const runChatbot = async (sessionId, uid, chatbot, question,history) => { try {

const sanitizedQuestion = question.trim().replaceAll('\n', ' ');

//Retrieve the chatbot from firestore const chatbotReference = await admin.firestore().collection('chatbots').doc(chatbot).get(); const chatbotData = chatbotReference.data();

// Transform the chat history to the format expected by LangChain const transformedHistory = Array.isArray(history) ? history.map(msg => { const prefix = msg.type === 'userMessage' ? 'Human:' : 'Assistant:'; return ${prefix} ${msg.message}; }).join('\n') : '';

// Pinecone setup and initialization const pinecone = new Pinecone({ apiKey: process.env.PINECONE_API_KEY, environment: process.env.PINECONE_ENVIRONMENT, });

const index = pinecone.Index(process.env.PINECONE_INDEX_NAME);

// Create a vector store const vectorStore = await PineconeStore.fromExistingIndex( new OpenAIEmbeddings({}), { pineconeIndex: index, textKey: 'text', namespace: "marting_lings", } );

const model = new ChatOpenAI({ temperature: 0.5, modelName: chatbot.activeModel, openAIApiKey: "****"

});

// Create a config for the FirestoreChatMessageHistory const firestoreConfig = { collectionName: "chathistory", sessionId: sessionId, userId: uid, config: {projectId: "unity-352c6"}, };

// Initialize the FirestoreChatMessageHistory for chat history // Here a new sub collection for messages was made const chatHistory = new FirestoreChatMessageHistory(firestoreConfig);

// Create a BufferMemory instance with FirestoreChatMessageHistory const memory = new BufferMemory({ chatHistory, memoryKey: "chat_history", inputKey: "question", outputKey: "text", });

// Create a conversational chain const retrievalChain = ConversationalRetrievalQAChain.fromLLM( model, vectorStore.asRetriever(), { qaTemplate: QA_PROMPT.replace('{author}', chatbot.name), questionGeneratorTemplate: CONDENSE_PROMPT, returnSourceDocuments: true, memory, // Add memory to the chain }, );

const qaTool = new ChainTool({ name: Books of ${chatbot}-qa, description: Books of the ${chatbot} QA - useful for when you need to ask questions about the opinion of ${chatbot}., chain: retrievalChain, returnDirect: true, verbose: true })

const tools = [qaTool]

const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: 'openai-functions', memory, returnIntermediateSteps: true, agentArgs: { prefix: You are ${chatbot} answering questions about ${chatbot} you can use tools to read his books answer question with this information., } })

console.log(await transformedHistory)

const response = await executor.call( {

    author: chatbot,
    question: sanitizedQuestion,
    chat_history: transformedHistory
},

)

console.log(response)

} catch (error) { console.error('Error occurred:', error) // Handle the error as needed: log, throw, or respond gracefully. // Example: throw the error to propagate it to the caller throw error }

} module.exports = { runChatbot };

you response: Hi @RedouanAssakali! Good to see you again. Thanks for reaching out with another issue. Let's see what we can do to help.

The error message you're encountering, "Field 'chat_history' in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value", is indicating that the 'chat_history' field is expected to be an array of BaseMessages, but it's not receiving that.

In your code, you have defined 'chat_history' as a memory key in BufferMemory and also used it as a MessagesPlaceholder in memoryPrompts. However, it seems like 'chat_history' is not being populated with an array of BaseMessages before being used in the executor.invoke() method.

To fix this issue, you need to ensure that 'chat_history' is being populated with an array of BaseMessages before it's used. If 'chat_history' is supposed to store the history of chat messages, you might need to update it after each executor.invoke() call.

The 'chat_history' field in the langchainjs framework is expected to be an array of message objects. Each message object is either of type 'HumanMessage' or 'AIMessage'. Both types of messages have a 'content' field which contains the message text and an 'additional_kwargs' field which is an object that can contain any additional information related to the message.

Here is the expected format:

[ HumanMessage { content: 'message text', additional_kwargs: {} }, AIMessage { content: 'message text', additional_kwargs: {} } ]

The 'chat_history' field in the langchainjs framework is typically populated by using the 'addMessage', 'addUserMessage', and 'addAIChatMessage' methods of the 'BaseChatMessageHistory' and 'BaseListChatMessageHistory' classes.

For example, to add a user message to the chat history, you would use the 'addUserMessage' method, passing in the message as a string. This method creates a new 'HumanMessage' instance with the provided message and adds it to the chat history.

this.addUserMessage("Hello, world!");

Similarly, to add an AI chat message to the chat history, you would use the 'addAIChatMessage' method, passing in the message as a string. This method creates a new 'AIMessage' instance with the provided message and adds it to the chat history.

this.addAIChatMessage("Hello, user!");

The 'addMessage' method can be used to add any message (either a user message or an AI message) to the chat history, as long as the message is an instance of 'BaseMessage'.

this.addMessage(new HumanMessage("Hello, world!")); this.addMessage(new AIMessage("Hello, user!"));

You can refer to the following sources for more information:

[examples/src/agents/structured_chat_with_memory.ts](https://github.com/langchain-ai/langchainjs/blob/main/examples/src/agents/structured_chat_with_memory.ts)
[examples/src/memory/chat_messages.ts](https://github.com/langchain-ai/langchainjs/blob/main/examples/src/memory/chat_messages.ts)
[langchain-core/src/chat_history.ts](https://github.com/langchain-ai/langchainjs/blob/main/langchain-core/src/chat_history.ts)

If you need further clarification or if there's anything else you'd like to know, feel free to ask. Sources

[examples/src/agents/structured_chat_with_memory.ts](https://github.com/langchain-ai/langchainjs/blob/main/examples/src/agents/structured_chat_with_memory.ts)
[examples/src/memory/chat_messages.ts](https://github.com/langchain-ai/langchainjs/blob/main/examples/src/memory/chat_messages.ts)
[langchain-core/src/chat_history.ts](https://github.com/langchain-ai/langchainjs/blob/main/langchain-core/src/chat_history.ts)

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

What i think the problem is: @dosu-bot i think the problem is that chat_history is empty

dosubot[bot] commented 7 months ago

🤖

@RedouanAssakali, the issue you're encountering is not due to the 'chat_history' being empty. The error message "Field 'chat_history' in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value" is indicating that the 'chat_history' field is expected to be an array of BaseMessages, but it's not receiving that.

In your code, 'chat_history' is defined as a memory key in BufferMemory and also used as a MessagesPlaceholder in memoryPrompts. However, it seems like 'chat_history' is not being populated with an array of BaseMessages before being used in the executor.invoke() method.

The 'chat_history' field in the langchainjs framework is expected to be an array of message objects. Each message object is either of type 'HumanMessage' or 'AIMessage'. Both types of messages have a 'content' field which contains the message text and an 'additional_kwargs' field which is an object that can contain any additional information related to the message.

Here is the expected format:

[
  HumanMessage {
    content: 'message text',
    additional_kwargs: {}
  },
  AIMessage {
    content: 'message text',
    additional_kwargs: {}
  }
]

The 'chat_history' field in the langchainjs framework is typically populated by using the 'addMessage', 'addUserMessage', and 'addAIChatMessage' methods of the 'BaseChatMessageHistory' and 'BaseListChatMessageHistory' classes.

For example, to add a user message to the chat history, you would use the 'addUserMessage' method, passing in the message as a string. This method creates a new 'HumanMessage' instance with the provided message and adds it to the chat history.

this.addUserMessage("Hello, world!");

Similarly, to add an AI chat message to the chat history, you would use the 'addAIChatMessage' method, passing in the message as a string. This method creates a new 'AIMessage' instance with the provided message and adds it to the chat history.

this.addAIChatMessage("Hello, user!");

The 'addMessage' method can be used to add any message (either a user message or an AI message) to the chat history, as long as the message is an instance of 'BaseMessage'.

this.addMessage(new HumanMessage("Hello, world!"));
this.addMessage(new AIMessage("Hello, user!"));

You can refer to the following sources for more information:

If you need further clarification or if there's anything else you'd like to know, feel free to ask.

Sources


This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.