You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js的LangChain RetrievalQAChain中添加系统消息

解决LangChain RetrievalQA系统消息不生效问题

要让回答和问题语言保持一致,你需要自定义RetrievalQA的提示模板,将系统规则融入到LLM的输入逻辑中,而不是简单拼接问题或传入额外参数。以下是具体修改方案:

核心问题

你使用的RetrievalQAChain默认提示模板不支持直接传入系统消息,之前的方法(拼接问题、chain.call额外参数)无法让LLM识别到这条规则,导致部分场景下翻译失效。

修改步骤

1. 切换为ChatOpenAI模型

Chat模型原生支持系统消息的格式规范,比基础OpenAI模型更适合处理这类对话规则:

const { ChatOpenAI } = require("langchain/chat_models/openai");
// 替换原来的 new OpenAI({})
const model = new ChatOpenAI({});

2. 构建包含系统消息的自定义提示模板

使用ChatPromptTemplate创建包含系统消息、上下文、用户问题的完整prompt结构:

const { ChatPromptTemplate } = require("langchain/prompts");

const systemMessage = "Answer in the same language as the question";
const prompt = ChatPromptTemplate.fromMessages([
  ["system", systemMessage],
  ["human", "使用以下上下文回答问题:\n{context}\n\n问题:{question}"]
]);

3. 配置RetrievalQAChain使用自定义prompt

通过RetrievalQAChain.fromLLM的第三个参数传入自定义prompt,并指定返回格式:

const chain = RetrievalQAChain.fromLLM(model, vectorStoreRetriever, {
  prompt: prompt,
  returnSourceDocuments: false, // 根据需求设置是否返回源文档
});

4. 调用chain时传入正确参数

现在调用chain时,需要传入question参数(替换原来的query):

response = await chain.call({
  question: question,
});

完整修改后的代码

const fs = require('fs');
const fsPromises = fs.promises;
const { ChatOpenAI } = require("langchain/chat_models/openai");
const { RecursiveCharacterTextSplitter } = require("langchain/text_splitter");
const { HNSWLib } = require("langchain/vectorstores/hnswlib");
const { OpenAIEmbeddings } = require("langchain/embeddings/openai");
const { RetrievalQAChain } = require("langchain/chains");
const { ChatPromptTemplate } = require("langchain/prompts");

app.post('/faq', async (req, res) => {
    const question = req.body.question;

    let answers = {};
    try {
        const data = await fsPromises.readFile("answers.json", "utf8");
        answers = JSON.parse(data);
    } catch (error) {
        console.log('answers.json does not exist')
    }

    let response;

    if (answers[question]) {
        response = answers[question];
    } else {
        const model = new ChatOpenAI({});
        const text = fs.readFileSync("test.txt", "utf8");
        const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
        const docs = await textSplitter.createDocuments([text]);

        const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
        const vectorStoreRetriever = vectorStore.asRetriever();

        // 构建包含系统消息的自定义prompt
        const systemMessage = "Answer in the same language as the question";
        const prompt = ChatPromptTemplate.fromMessages([
            ["system", systemMessage],
            ["human", "使用以下上下文回答问题:\n{context}\n\n问题:{question}"]
        ]);

        // 配置RetrievalQAChain使用自定义prompt
        const chain = RetrievalQAChain.fromLLM(model, vectorStoreRetriever, {
            prompt: prompt,
            returnSourceDocuments: false,
        });

        response = await chain.call({
            question: question,
        });
        console.log(response);

        answers[question] = response;

        try {
            await fsPromises.writeFile("answers.json", JSON.stringify(answers, null, 2), "utf8");
        } catch (error) {
            console.log('Error writing json file.')
        }
    }
    res.status(200).json(response);
});

额外说明

  • 如果你坚持使用基础OpenAI模型而非ChatOpenAI,可以直接将系统消息拼接进prompt模板的前缀部分,比如:
    const { PromptTemplate } = require("langchain/prompts");
    const prompt = new PromptTemplate({
        template: "Answer in the same language as the question\n使用以下上下文回答问题:\n{context}\n\n问题:{question}",
        inputVariables: ["context", "question"],
    });
    
  • 确保你的API密钥配置正确,ChatOpenAI和OpenAI的初始化参数一致,只需替换类名即可。

内容的提问来源于stack exchange,提问作者Geister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:43:32