Вопрос или проблема
Я пытаюсь получить данные из моей коллекции векторов qdrant, но на любой мой запрос он отвечает чем-то вроде: “Предоставленный контекст не содержит информации или содержимого для обмена. Поэтому я не могу предоставить никаких деталей или ответить на ваш вопрос.”
Я действительно не уверен, что я пропускаю, но я знаю следующее:
- Подключение к нашему qdrant работает нормально
- В коллекции более 100000 точек, так что данные доступны
- Что я хочу знать, это:
Является ли RunnableSequence правильным решением здесь или лучше использовать .pipe() для запросов? Как это работает? Я был бы очень благодарен за любые примеры кода, как это заставить работать. 🙏
Вот код, который у меня сейчас есть
import { QdrantVectorStore } from "@langchain/qdrant";
import { z } from "zod";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ChatOpenAI } from "@langchain/openai";
import { embeddings } from "../clients/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { SelfQueryRetriever } from "langchain/retrievers/self_query";
import { QdrantTranslator } from "@langchain/community/structured_query/qdrant";
import type { Document } from "@langchain/core/documents";
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
const completionSchema = z.object({
response: z.string().describe("Сгенерированный ответ"),
profitSentiment: z
.enum(["positive", "negative"])
.describe(
"Строка, представляющая, был ли прибыль положительной или отрицательной по сравнению с последним отчетом."
),
profitExplanation: z
.string()
.describe(
"Объяснение прибыли по сравнению с последним отчетом."
),
source: z
.string()
.describe("Документ, использованный для генерации ответа"),
});
const attributeInfo = [
{
name: "chunk_index",
description: "индекс для блока",
type: "number",
},
{
name: "company_id",
description: "идентификатор компании",
type: "number",
},
{
name: "company_ticker",
description: "тикер акций компании",
type: "string",
},
{
name: "created_at",
description: "Когда был создан этот контент",
type: "строка даты",
},
{
name: "document_type_id",
description: "идентификатор типа документа",
type: "number",
},
{
name: "file_name",
description: "Имя файла, являвшегося источником информации",
type: "string",
},
{
name: "timespan_end",
description:
"метка времени, указывающая конец периода, когда информация является актуальной",
type: "строка даты",
},
{
name: "timespan_start",
description:
"метка времени, указывающая начало периода, когда информация является актуальной",
type: "строка даты",
},
];
export const runCompletions = async () => {
const vectorStore = await QdrantVectorStore.fromExistingCollection(
embeddings,
{
url: process.env.QDRANT_API_ENDPOINT!,
collectionName: "documents_yearly_reports",
}
);
const prompt = ChatPromptTemplate.fromTemplate(`
Ответьте на вопрос, основываясь только на предоставленном контексте.
Контекст: {context}
Вопрос: {question}
`);
const formatDocs = (docs: Document[]) => {
console.log({ docs });
return docs.map((doc) => JSON.stringify(doc)).join("\n\n");
};
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
const selfQueryRetriever = SelfQueryRetriever.fromLLM({
llm,
vectorStore,
documentContents:
"Информация о годовых отчетах торгуемых на бирже компаний в Швеции",
attributeInfo,
structuredQueryTranslator: new QdrantTranslator(),
searchParams: {
filter: {
must: [
{
key: "metadata.company_id",
match: {
value: 435,
},
},
],
},
},
});
const ragChain = RunnableSequence.from([
{
context: selfQueryRetriever.pipe(formatDocs),
question: new RunnablePassthrough(),
},
prompt,
llm,
new StringOutputParser(),
]);
const response = await ragChain.invoke("расскажи мне всё!");
console.log({ response });
};
## Используемые пакеты
"@langchain/community": "^0.3.1",
"@langchain/core": "^0.3.1",
"@langchain/openai": "^0.3.0",
"@langchain/qdrant": "^0.1.0",
"@langchain/textsplitters": "^0.1.0",
"@qdrant/js-client-rest": "^1.11.0",
"@mozilla/readability": "^0.5.0",
"langchain": "^0.3.2",
Я пытался настроить это в течение 2-3 дней. Все примеры, которые я могу найти, создают необходимые документы, а затем используют их, но у меня уже есть документы в базе данных qdrant, так что я не знаю, как их использовать.
Ответ или решение
Для создания работающей последовательности для векторов, хранящихся в Qdrant с использованием TypeScript, необходимо правильно настроить вашу цепочку (RunnableSequence) и убедиться, что вы корректно выполняете запросы к вашей базе данных. Судя по вашему коду и проблеме, с которой вы столкнулись, есть несколько мест, которые можно улучшить для успешного получения данных.
Вот обновленная версия вашего кода с разъяснениями:
import { QdrantVectorStore } from "@langchain/qdrant";
import { z } from "zod";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ChatOpenAI } from "@langchain/openai";
import { embeddings } from "../clients/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { SelfQueryRetriever } from "langchain/retrievers/self_query";
import { QdrantTranslator } from "@langchain/community/structured_query/qdrant";
import type { Document } from "@langchain/core/documents";
import {
RunnablePassthrough,
RunnableSequence,
} from "@langchain/core/runnables";
// Схема для данных ответа
const completionSchema = z.object({
response: z.string().describe("Сгенерированный ответ"),
profitSentiment: z.enum(["positive", "negative"]).describe("Позитивный или негативный показатель прибыли."),
profitExplanation: z.string().describe("Объяснение прибыли по сравнению с последним отчетом."),
source: z.string().describe("Документ, использованный для генерации ответа"),
});
// Информация об атрибутах
const attributeInfo = [
// Определите вашу информацию об атрибутах так же, как и раньше
];
export const runCompletions = async () => {
// Создание векторного магазина
const vectorStore = await QdrantVectorStore.fromExistingCollection(
embeddings,
{
url: process.env.QDRANT_API_ENDPOINT!,
collectionName: "documents_yearly_reports",
}
);
// Шаблон чата
const prompt = ChatPromptTemplate.fromTemplate(`
Ответьте на вопрос, основываясь только на предоставленном контексте.
Контекст: {context}
Вопрос: {question}
`);
// Форматирование документов
const formatDocs = (docs: Document[]) => {
return docs.map((doc) => JSON.stringify(doc)).join("\n\n");
};
// LLM модель
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
// Создание реквизита с использованием самозапроса
const selfQueryRetriever = SelfQueryRetriever.fromLLM({
llm,
vectorStore,
documentContents: "Информация о годовых отчетах о торгуемых акциях в Швеции",
attributeInfo,
structuredQueryTranslator: new QdrantTranslator(),
searchParams: {
filter: {
must: [
{
key: "metadata.company_id",
match: {
value: 435,
},
},
],
},
},
});
// Создание рабочей цепочки
const ragChain = RunnableSequence.from([
{
context: selfQueryRetriever.pipe(formatDocs),
question: new RunnablePassthrough(),
},
prompt,
llm,
new StringOutputParser(),
]);
// Вызов цепочки и получение ответа
try {
const response = await ragChain.invoke({ question: "Расскажите мне все!" });
console.log({ response });
} catch (error) {
console.error("Ошибка при вызове цепочки:", error);
}
};
Примечания:
-
Используйте
invoke
правильно: Убедитесь, что вы передаете объект с вопросом вinvoke
, а не строку. Это важно для правильного понимания вашего вопроса LLM. -
Обработка ошибок: Чтобы лучше отследить ошибки, добавьте обработку ошибок вокруг вызова
invoke
. Это поможет вам выявить, если что-то идет не так. -
Атрибуты: Убедитесь, что поля атрибутов, которые вы используете в фильтрах и выводе, точно соответствуют вашим данным в Qdrant.
- Проверка данных: Убедитесь, что в вашей коллекции действительно есть документы, которые соответствуют вашему запросу. Попробуйте временно убрать фильтры, чтобы посмотреть, получите ли вы какие-либо документы.
Этот подход должен помочь вам успешно извлекать данные из вашей базы данных Qdrant и отвечать на них с помощью LLM. Если у вас возникнут дополнительные вопросы или проблемы, пожалуйста, не стесняйтесь спрашивать!