langchain-ai / langchainjs

πŸ¦œπŸ”— Build context-aware reasoning applications πŸ¦œπŸ”—
https://js.langchain.com/docs/
MIT License
12.33k stars 2.09k forks source link

it could be empty when new conversation is started : Error: Field "chat_history" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. #4115

Closed RedouanAssakali closed 4 months ago

RedouanAssakali commented 8 months ago

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 };

dosubot[bot] commented 8 months ago

πŸ€–

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:

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.

RedouanAssakali commented 8 months ago

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

dosubot[bot] commented 8 months ago

πŸ€–

Based on the provided code, it seems that the chat_history field is expected to be an array of messages. Each message in the array should be a string in the format of either Human: <message> or Assistant: <message>. This is indicated by the following code:

const transformedHistory = Array.isArray(history)
    ? history.map(msg => {
        const prefix = msg.type === 'userMessage' ? 'Human:' : 'Assistant:';
        return `${prefix} ${msg.message}`;
    }).join('\n')
    : '';

In the runChatbot function, the history parameter is transformed into the transformedHistory variable, which is then passed as the chat_history field in the executor.call method. If the history parameter is an array, each message in the array is prefixed with either Human: or Assistant: depending on the type field of the message, and then all the messages are joined into a single string with newline characters in between. If the history parameter is not an array, an empty string is used as the chat_history.

Therefore, if the history parameter passed to the runChatbot function is null or undefined, the chat_history field will be an empty string, which should not cause any issues. However, if the history parameter is an array that contains objects that do not have a type field of either 'userMessage' or 'assistantMessage', or a message field that is a string, then the transformedHistory variable will not be in the expected format, which could cause issues.

If you are encountering an error with the chat_history field, please ensure that the history parameter passed to the runChatbot function is either null, undefined, or an array of objects with a type field of either 'userMessage' or 'assistantMessage', and a message field that is a string. If the issue persists, could you please provide more information about the error, such as the exact error message and the value of the history parameter that is causing the error? This will help in diagnosing the issue.

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.