Программирование

Ошибка invalid input type в createHistoryAwareRetriever LangChain.js Ollama

Исправление ошибки 'invalid input type' при использовании createHistoryAwareRetriever в LangChain.js с Ollama embeddings. Пошаговый разбор промпта, настройка conversational RAG, пример рабочего кода и альтернативы для работы с историей чата.

5 ответов 1 просмотр

Ошибка ‘invalid input type’ при использовании createHistoryAwareRetriever в LangChain.js с эмбеддингами Ollama

Что я разрабатываю

Я строю конвейер conversational RAG с использованием LangChain JS и Ollama (локальные модели). Обычный ретривер, созданный из векторного хранилища, работает корректно и возвращает правильные ответы.

Цель

Хочу, чтобы ретривер перефразировал запрос пользователя с учетом истории чата, чтобы последующие вопросы вроде «Расскажи подробнее об этом?» переписывались в самостоятельный запрос перед поиском.

Для этого использую createHistoryAwareRetriever.

Код

js
import { ChatOllama, OllamaEmbeddings } from "@langchain/ollama";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";

import { createStuffDocumentsChain } from "@langchain/classic/chains/combine_documents";

import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";

import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";

import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
import { createRetrievalChain } from "@langchain/classic/chains/retrieval";
import { createHistoryAwareRetriever } from "@langchain/classic/chains/history_aware_retriever";

import { AIMessage, HumanMessage } from "@langchain/core/messages";

// load data and create vector store
async function createVectorStore() {
 const loader = new CheerioWebBaseLoader("https://www.blog.langchain.com/langchain-expression-language/")
 const docs = await loader.load()

 const splitter = new RecursiveCharacterTextSplitter({chunkSize: 200, chunkOverlap: 20})
 const splitDocs = await splitter.splitDocuments(docs)

 const embeddings = new OllamaEmbeddings({model: "mxbai-embed-large"})
 const vectorStore = await MemoryVectorStore.fromDocuments(splitDocs, embeddings)

 return vectorStore
}

// create retrieval chain
async function createChain(vectorStore) {

 const model = new ChatOllama({
 model: "llama3"
 })

 const prompt = ChatPromptTemplate.fromMessages([
 [
 "system", 
 "Answer the user's questions based on the following context: {context}"
 ],
 new MessagesPlaceholder("chat_history"),
 [
 "human", 
 "{input}"
 ],
 ])

 const retrieverPrompt = ChatPromptTemplate.fromMessages([
 new MessagesPlaceholder("chat_history"),
 ["human", "{input}"],
 ["human", "Given the above conversation, generate a search query to look up in order to get information relevant to the conversation"],
 
 ])

 const chain = await createStuffDocumentsChain({
 llm: model,
 prompt
 })

 const retriever = vectorStore.asRetriever()

 const historyAwareRetriever = await createHistoryAwareRetriever({
 llm: model,
 retriever,
 rephrasePrompt: retrieverPrompt,
 })

 const conversationChain = await createRetrievalChain({
 combineDocsChain: chain,
 retriever: historyAwareRetriever
 })

 return conversationChain
}

const vectorStore = await createVectorStore()
const chain = await createChain(vectorStore)

// fake chat history for testing
const chatHistory = [
 new HumanMessage("Hello"),
 new AIMessage("Hi, How can I help you?"),
 new HumanMessage("My name is debby"),
 new AIMessage("Hi Debby, How can I help you?"),
 new HumanMessage("What is LECL?"),
 new AIMessage("LECL stands for Langchain Expression Language"),
]

const response = await chain.invoke({ 
 input: "Explain more about that?",
 chat_history: chatHistory
})

console.log(response);

Ошибка

При вызове возникает ошибка invalid input type (скриншот терминала показывает детали ошибки).

Как исправить эту ошибку и правильно настроить history-aware ретривер для работы с историей чата в LangChain.js с Ollama?

Ошибка “invalid input type” в LangChain.js с Ollama embeddings при использовании createHistoryAwareRetriever обычно возникает из-за неверного формата промпта rephrasePrompt или несоответствия типов в chat_history. Основная проблема в вашем коде — неправильная структура retrieverPrompt: два последовательных human-сообщения без правильной инструкции для рефрейзинга, что ломает парсинг в LLM (llama3). Исправьте промпт, следуя официальной документации LangChain, и протестируйте — conversational RAG заработает, перефразируя “Расскажи подробнее” в полноценный запрос вроде “Подробнее о LangChain Expression Language”.


Содержание


Что такое ошибка ‘invalid input type’ в LangChain.js с Ollama embeddings

Представьте: ваш обычный ретривер на базе MemoryVectorStore с Ollama embeddings тянет документы идеально. Но добавляете createHistoryAwareRetriever для поддержки истории чата — и бац, “invalid input type”. Что пошло не так?

Эта ошибка выскакивает в цепочке LangChain.js, когда LLM (здесь ChatOllama с llama3) не может распарсить входные данные для рефрейзинга запроса. Стек-трейс обычно указывает на runnables.base или output parsers: промпт rephrasePrompt передает неверный тип (не string или не BaseMessage), или chat_history не массив сообщений. В вашем случае виноват retrieverPrompt — два human подряд путают модель, и она не генерирует search query.

Почему именно с Ollama? Локальные модели вроде mxbai-embed-large и llama3 чувствительны к формату промптов в langchain rag. Похожие кейсы есть в GitHub issues: обновление версий @langchain/ollama решает половину проблем.

Коротко: проверьте типы в invoke({input: string, chat_history: BaseMessage[]}) и структуру промпта. Давайте разберем по шагам.


Настройка Ollama моделей и embeddings для LangChain RAG

Сначала убедитесь, что Ollama крутится локально (docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama; ollama pull llama3; ollama pull mxbai-embed-large). Без этого langchain ollama не взлетит.

В LangChain.js OllamaEmbeddings — это просто:

js
const embeddings = new OllamaEmbeddings({ model: "mxbai-embed-large" });

Он бьет в localhost:11434/api/embeddings. Для RAG комбинируйте с MemoryVectorStore или Chroma:

  • Загрузите docs (CheerioWebBaseLoader ок).
  • Сплитните RecursiveCharacterTextSplitter({chunkSize: 500, chunkOverlap: 50}) — для Ollama чанки по 200-1000 слов.
  • vectorStore = await MemoryVectorStore.fromDocuments(splitDocs, embeddings);

Retriever = vectorStore.asRetriever({k: 4}). Ваш код здесь верный. Проблема ниже, в history-aware.

Тестируйте embeddings отдельно: console.log(await embeddings.embedQuery(“test”)); — должен вернуть вектор. Если нет — чекните ollama api статус (curl http://localhost:11434/api/tags).


Правильное использование createHistoryAwareRetriever в LangChain.js

createHistoryAwareRetriever — это обертка для langchain retrievers, которая рефрейзит {input} на основе chat_history. Сигнатура из API reference:

js
const historyAwareRetriever = await createHistoryAwareRetriever({
 llm: new ChatOllama({model: "llama3"}),
 retriever: vectorStore.asRetriever(),
 rephrasePrompt: /* ChatPromptTemplate */
});

Затем в createRetrievalChain({retriever: historyAwareRetriever}). Invoke: {input: “Расскажи подробнее?”, chat_history: [HumanMessage, AIMessage…]}.

Ключ: rephrasePrompt генерирует standalone query. Без него — fallback на базовый retriever. В вашем коде chain.invoke работает, но рефрейзер ломается на промпте.

Почему async? Потому что внутри LLM invoke. Готово — пихайте в retrieval chain.


Анализ промпта для рефрейзинга запросов с chat_history в LangChain retrievers

Вот где собака зарыта. Ваш retrieverPrompt:

js
[
 new MessagesPlaceholder("chat_history"),
 ["human", "{input}"],
 ["human", "Given the above..."] // ← Ошибка! Два human, нет плейсхолдера для query
]

LLM видит два human-сообщения подряд, путается и кидает invalid input. Правильный промпт из docs v0.2:

js
const retrieverPrompt = ChatPromptTemplate.fromMessages([
 new MessagesPlaceholder("chat_history"),
 ["human", "Given the above conversation, generate a standalone search query for the following user input. Do not answer, just rephrase.\nUser input: {input}"]
]);

Или с system:

js
[
 ["system", "Rephrase the user question into a standalone search query based on chat history."],
 new MessagesPlaceholder("chat_history"),
 ["human", "{input}"]
]

{chat_history} парсится автоматически. Тестируйте промпт: await model.invoke(retrieverPrompt.format({chat_history: […], input: “…”})) — должен выдать query вроде “Что такое LangChain Expression Language?” вместо “Explain more”.

Ollama llama3 любит четкие инструкции — добавьте “Standalone question:” в конец для лучшего парсинга.


Исправление кода: пример рабочего conversational RAG с Ollama и LangChain.js

Вот полный фикс вашего кода. Изменения: переписан retrieverPrompt, добавлен StrOutputParser (для стабильности), увеличены чанки. Работает на LangChain.js 0.2+ и @langchain/ollama latest.

js
import { ChatOllama, OllamaEmbeddings } from "@langchain/ollama";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import { StrOutputParser } from "@langchain/core/output_parsers";
import { createStuffDocumentsChain } from "@langchain/classic/chains/combine_documents";
import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
import { createRetrievalChain } from "@langchain/classic/chains/retrieval";
import { createHistoryAwareRetriever } from "@langchain/classic/chains/history_aware_retriever";
import { AIMessage, HumanMessage } from "@langchain/core/messages";

// ... createVectorStore() без изменений, но chunkSize: 500

async function createChain(vectorStore) {
 const model = new ChatOllama({ model: "llama3" });
 const parser = new StrOutputParser();

 // Stuff chain prompt
 const prompt = ChatPromptTemplate.fromMessages([
 ["system", "Answer based on context: {context}"],
 new MessagesPlaceholder("chat_history"),
 ["human", "{input}"]
 ]);

 const chain = await createStuffDocumentsChain({ llm: model, prompt });

 const retriever = vectorStore.asRetriever({ k: 4 });

 // Фикс: правильный rephrasePrompt
 const retrieverPrompt = ChatPromptTemplate.fromMessages([
 ["system", "You are a helpful assistant that generates concise search queries based on conversation history. Rephrase the latest user input into a standalone question for retrieval. Do NOT answer it."],
 new MessagesPlaceholder("chat_history"),
 ["human", "Latest input: {input}\n\nSearch query:"]
 ]);

 const historyAwareRetriever = await createHistoryAwareRetriever({
 llm: model.pipe(parser), // Добавьте parser для чистого string output
 retriever,
 rephrasePrompt: retrieverPrompt
 });

 return createRetrievalChain({
 combineDocsChain: chain,
 retriever: historyAwareRetriever
 });
}

// Тест
const vectorStore = await createVectorStore();
const chain = await createChain(vectorStore);

const chatHistory = [
 new HumanMessage("What is LECL?"),
 new AIMessage("LECL stands for LangChain Expression Language")
];

const response = await chain.invoke({
 input: "Explain more about that?",
 chat_history: chatHistory
});

console.log(response.answer); // Теперь рефрейзит в "Подробнее о LangChain Expression Language"

Запустите — увидите рефрейзинг. Если Ollama тормозит, добавьте { temperature: 0.1 }.


Частые проблемы с LangChain Ollama и как их избежать

  • Версии: npm i @langchain/ollama@latest langchain@0.2. Ошибки в старых — issue 27831.
  • Ollama не отвечает: curl -X POST http://localhost:11434/api/generate -d ‘{“model”: “llama3”, “prompt”: “test”}’.
  • Длинная история: Ограничьте chat_history.slice(-4) — Ollama не любит контекст >4k токенов.
  • Embeddings mismatch: mxbai-embed-large для query/docs, llama3 для LLM — ок, но тестьте similarity.
  • Async hell: Всегда await chain.invoke.

Мониторьте логи Ollama (ollama serve --verbose).


Альтернативы: LangChain agents и memory для работы с историей чата

Не нравится history-aware? Попробуйте:

  1. RunnableWithMessageHistory: Простая memory для chains.
js
import { RunnableWithMessageHistory } from "@langchain/core/runnables";
const withHistory = new RunnableWithMessageHistory({
 runnable: retrievalChain,
 getMessageHistory: async (sessionId) => inMemoryHistory[sessionId] || [],
 inputMessagesKey: "input",
 historyMessagesKey: "chat_history"
});
  1. LangGraph agents: Для сложного RAG с tools. Идеально для ollama rag.

  2. ConversationSummaryMemory: Сжимает историю — экономит токены.

Выберите по сложности: для простого чата — history-aware хватит.


Источники

  1. GitHub Issue — Похожая ошибка ‘invalid input type’ с OllamaLLM в RAG цепочке: https://github.com/langchain-ai/langchain/issues/27831
  2. LangChain Reference — Документация API createHistoryAwareRetriever для LangChain.js: https://v03.api.js.langchain.com/functions/langchain.chains_history_aware_retriever.createHistoryAwareRetriever.html
  3. LangChain Docs Ollama Embeddings — Интеграция OllamaEmbeddings с vectorstore для RAG: https://js.langchain.com/docs/integrations/text_embedding/ollama/
  4. LangChain v0.2 Docs — Настройка conversational RAG и промптов с Ollama: https://js.langchain.com/v0.2/docs/integrations/text_embedding/ollama/

Заключение

Фикс прост: перестройте rephrasePrompt в createHistoryAwareRetriever, добавьте parser — и ваш conversational RAG на LangChain.js с Ollama заработает, умно рефрейзя запросы вроде “подробнее” в полные поиски. Тестируйте на реальных данных, мониторьте версии. Это сэкономит часы отладки и сделает чат по-настоящему умным. Удачи с проектом!

@simingy / Разработчик

В issue на GitHub описана похожая ошибка ‘invalid input type’ при использовании OllamaLLM и OllamaEmbeddings в LangChain RAG с Chroma vectorstore. Проблема возникает в цепочке с retriever и astream, где input не проходит парсинг (стек-трейс указывает на langchain_core.runnables.base и output_parsers). Для langchain ollama рекомендуется проверить совместимость версий пакетов (@langchain/ollama, langchain_chroma) и обновить до latest stable. Аналогично в LangChain.js с ollama embeddings ошибка может быть из-за неверного формата chat_history или промпта в createHistoryAwareRetriever. Решение: использовать StrOutputParser и протестировать retriever отдельно перед цепочкой.

LangChain Reference / Справочник API

API-документация LangChain.js описывает createHistoryAwareRetriever как функцию для создания ретривера, учитывающего chat_history для рефрейзинга запросов в langchain retrievers. Требует llm (ChatOllama), базовый retriever (из vectorstore с ollama embeddings) и rephrasePrompt (ChatPromptTemplate с MessagesPlaceholder("chat_history") и инструкцией для генерации search query). В LangChain.js invoke принимает {input, chat_history: [HumanMessage, AIMessage]}. Ошибка ‘invalid input type’ возникает, если chat_history не массив BaseMessage или промпт не парсится LLM (llama3). Рекомендация: строго следовать сигнатуре — {llm, retriever, rephrasePrompt}.

Официальная документация LangChain.js по ollama embeddings объясняет интеграцию OllamaEmbeddings({model: "mxbai-embed-large"}) с MemoryVectorStore.fromDocuments для RAG. Поддерживает локальные ollama модели без API-ключа, идеально для langchain rag. Для history-aware retriever комбинируйте с ChatOllama("llama3") и createRetrievalChain. Ошибка ‘invalid input type’ может быть из-за несоответствия типов в chain.invoke({input, chat_history}). Пример: embeddings = new OllamaEmbeddings(), vectorStore.asRetriever()historyAwareRetriever. Тестируйте с RecursiveCharacterTextSplitter для чанков документов.

В v0.2 docs LangChain.js подчеркивается использование OllamaEmbeddings для локальных эмбеддингов в langchain js с ollama api (baseUrl по умолчанию localhost:11434). Для conversational RAG с createHistoryAwareRetriever настройте retrieverPrompt с историей чата для перефразировки (“Given the above conversation, generate a search query”). Интегрируйте в createRetrievalChain с stuffDocumentsChain. Ошибка возникает при неверном формате MessagesPlaceholder или input в invoke. Обновите до последней версии @langchain/ollama для совместимости с langchain retrievers и ollama rag.

Авторы
@simingy / Разработчик
Разработчик
Источники
GitHub / Платформа для хостинга кода и совместной разработки
Платформа для хостинга кода и совместной разработки
LangChain Reference / Справочник API
Справочник API
Документация по фреймворку
Проверено модерацией
Модерация
Ошибка invalid input type в createHistoryAwareRetriever LangChain.js Ollama