In diesem Tutorial konzentrieren wir uns darauf, wie man mit Dewy und LangChain.js ein CLI-Tool zur Beantwortung von Fragen erstellt. Dewy ist eine Open-Source-Wissensdatenbank, die Entwicklern hilft, Informationen effizient zu organisieren und abzurufen. LangChain.js ist ein Framework, das die Integration großer Sprachmodelle (LLMs) in Anwendungen vereinfacht. Durch die Kombination der Fähigkeiten von Dewy zur Wissensverwaltung mit der LLM-Integration von LangChain.js können Sie Tools erstellen, die komplexe Anfragen mit präzisen und relevanten Informationen beantworten. Dieser Leitfaden führt Sie durch die Einrichtung Ihrer Umgebung, das Laden von Dokumenten in Dewy und die Verwendung eines LLM über LangChain.js, um Fragen basierend auf den gespeicherten Daten zu beantworten. Es richtet sich an Ingenieure, die ihre Projekte mit erweiterten Frage-Antwort-Funktionen erweitern möchten. Warum Dewy und LangChain.js? ist eine OSS-Wissensdatenbank, die entwickelt wurde, um die Art und Weise zu optimieren, wie Entwickler Informationen speichern, organisieren und abrufen. Seine Flexibilität und Benutzerfreundlichkeit machen es zu einer ausgezeichneten Wahl für Entwickler, die wissensbasierte Anwendungen erstellen möchten. Dewy hingegen ist ein leistungsstarkes Framework, das es Entwicklern ermöglicht, LLMs nahtlos in ihre Anwendungen zu integrieren. Durch die Kombination des strukturierten Wissensmanagements von Dewy mit den LLM-Funktionen von LangChain.js können Entwickler anspruchsvolle Frage-Antwort-Systeme erstellen, die komplexe Abfragen verstehen und verarbeiten können und präzise und kontextrelevante Antworten bieten. LangChain.js Das Ziel Unser Ziel ist es, ein einfaches, aber leistungsstarkes CLI-Skript zur Beantwortung von Fragen zu erstellen. Dieses Skript ermöglicht es Benutzern, Dokumente in die Dewy-Wissensdatenbank zu laden und dann über LangChain.js ein LLM zu verwenden, um Fragen basierend auf den in Dewy gespeicherten Informationen zu beantworten. Dieses Tutorial führt Sie durch den Prozess, von der Einrichtung Ihrer Umgebung bis zur Implementierung des CLI-Skripts. Sie erfahren, wie Sie mit LangChain eine einfache Anwendung zur Beantwortung von Fragen erstellen und wie Sie Dewy als Wissensquelle integrieren, sodass Ihre Anwendung Fragen auf der Grundlage spezifischer Dokumente beantworten kann, die Sie ihr bereitstellen. Voraussetzungen Bevor Sie mit dem Tutorial beginnen, stellen Sie sicher, dass die folgenden Voraussetzungen erfüllt sind: Grundkenntnisse der Typescript-Programmierung Vertrautheit mit der Entwicklung von CLI-Tools Eine Kopie von Dewy, die auf Ihrem lokalen Computer ausgeführt wird (lesen Sie von Dewy, wenn Sie hier Hilfe benötigen). die Installationsanweisungen Schritt 1: Richten Sie Ihr Projekt ein Der endgültige Code für dieses Beispiel ist verfügbar, wenn Sie weitermachen möchten. im Dewy-Repo Erstellen Sie zunächst ein Verzeichnis für das TypeScript-CLI-Projekt und wechseln Sie in das Verzeichnis mkdir dewy_qa cd dewy_qa Wenn das Verzeichnis eingerichtet ist, können Sie TypeScript installieren und das Projekt initialisieren: npm init -y npm i typescript --save-dev npx tsc --init Abhängig von Ihrer Umgebung müssen Sie möglicherweise einige Änderungen an Ihrer TypeScript-Konfiguration vornehmen. Stellen Sie sicher, dass Ihre etwa wie folgt aussieht: tsconfig.json { "compilerOptions": { "target": "ES6", "module": "CommonJS", "moduleResolution": "node", "declaration": true, "outDir": "./dist", "esModuleInterop": true, "strict": true, } Jetzt können Sie die CLI-Anwendung erstellen. Damit der Code nicht zu unübersichtlich wird, organisieren Sie ihn in mehreren Verzeichnissen mit dem folgenden Layout dewy_qa/ ├── commands/ │ └── ... ├── utils/ │ └── ... ├── index.ts ├── package.json └── tsconfig.ts Jeder Befehl wird im implementiert und gemeinsam genutzter Code wird im Verzeichnis abgelegt. Der Einstiegspunkt zur CLI-Anwendung ist die Datei . commands utils index.ts Beginnen Sie mit einer einfachen „Hallo Welt“-Version von – mit dem Ausfüllen beginnen Sie im nächsten Abschnitt index.ts #!/usr/bin/env ts-node-script console.log("hello world"); Um zu überprüfen, ob die Umgebung korrekt eingerichtet ist, versuchen Sie, den folgenden Befehl auszuführen. In der Konsole sollte „Hallo Welt“ angezeigt werden: npx ts-node index.ts Anstatt diesen sehr langen Befehl jedes Mal einzugeben, erstellen wir einen Eintrag in für den Befehl. Dies hilft uns, uns daran zu erinnern, wie die CLI aufgerufen wird, und erleichtert die Installation als Befehl: package.json { ... "bin": { "dewy_qa": "./index.ts" } ... } Jetzt können Sie Ihr Skript mit ausführen oder das Paket und es einfach als ausführen npm exec dewy_qa npm link dewy_qa Schritt 2: Implementieren Sie das Laden von Dokumenten Laden Sie Dokumente, indem Sie den Dewy-Client einrichten. Der erste Schritt besteht darin, dem Projekt einige Abhängigkeiten hinzuzufügen. Die erste ist , die Client-Bibliothek für Dewy. Der zweite ist , der uns beim Erstellen einer CLI-Anwendung mit Argumentanalyse, Unterbefehlen und mehr hilft. Abschließend können die Aufforderungen bunter gestalten. dewy-ts commander chalk npm install dewy-ts commander chalk Als nächstes implementieren Sie die Logik des Ladebefehls. Sie tun dies in einer separaten Datei mit dem Namen . Diese Datei implementiert eine Funktion namens „ , die eine URL und einige zusätzliche Optionen erwartet – dies wird in einem späteren Abschnitt mit der CLI verknüpft. commands/load.ts load Dewy macht das Laden von Dokumenten ganz einfach – richten Sie einfach den Client ein und rufen Sie mit der URL der Datei auf, die Sie laden möchten. Dewy kümmert sich darum, den Inhalt der PDF-Datei zu extrahieren, sie in Stücke aufzuteilen, die genau die richtige Größe für den Versand an ein LLM haben, und sie für die semantische Suche zu indizieren. addDocument import { Dewy } from 'dewy-ts'; import { success, error } from '../utils/colors'; export async function load(url: string, options: { collection: string, dewy_endpoint: string }): Promise<void> { console.log(success(`Loading ${url} into collection: ${options.collection}`)); try { const dewy = new Dewy({ BASE: options.dewy_endpoint }) const result = await dewy.kb.addDocument({ collection: options.collection, url }); console.log(success(`File loaded successfully`)); console.log(JSON.stringify(result, null, 2)); } catch (err: any) { console.error(error(`Failed to load file: ${err.message}`)); } } Möglicherweise ist Ihnen aufgefallen, dass einige Funktionen aus importiert wurden. Diese Datei richtet lediglich einige Hilfsprogramme zum Färben der Konsolenausgabe ein. Fügen Sie sie in ein, damit sie an anderer Stelle verwendet werden kann: ../utils/colors utils import chalk from 'chalk'; export const success = (message: string) => chalk.green(message); export const info = (message: string) => chalk.blue(message); export const error = (message: string) => chalk.red(message); Schritt 3: Implementieren Sie die Beantwortung von Fragen Mit der Möglichkeit, Dokumente in Dewy zu laden, ist es an der Zeit, LangChain.js zu integrieren, um LLMs zur Beantwortung von Fragen zu nutzen. In diesem Schritt wird LangChain.js eingerichtet, um die Dewy-Wissensdatenbank abzufragen und die Ergebnisse mithilfe eines LLM zu verarbeiten, um Antworten zu generieren. Installieren Sie zunächst einige zusätzliche Pakete – und , um die OpenAI-API als LLM zu verwenden: langchain openai npm install dewy-langchain langchain @langchain/openai openai Dieser Befehl ist ziemlich lang, daher werden wir mehrere Teile davon durchgehen, bevor wir sie am Ende kombinieren Erstellen Sie Clients für OpenAI und Dewy Das erste, was eingerichtet werden muss, ist Dewy (wie zuvor) und ein LLM. Ein Unterschied zu zuvor besteht darin, dass zum Erstellen eines verwendet wird: Dies ist ein spezieller Typ, der von LangChain zum Abrufen von Informationen als Teil einer Kette verwendet wird. Sie werden in nur einer Minute sehen, wie der Retriever verwendet wird. dewy DewyRetriever const model = new ChatOpenAI({ openAIApiKey: options.openai_api_key, }); const dewy = new Dewy({ BASE: options.dewy_endpoint }) const retriever = new DewyRetriever({ dewy, collection }); Erstellen Sie eine LangChain-Eingabeaufforderung Dabei handelt es sich um eine String-Vorlage, die dem LLM anweist, wie er sich verhalten soll, mit Platzhaltern für zusätzlichen Kontext, der beim Erstellen der „Kette“ bereitgestellt wird. In diesem Fall wird das LLM angewiesen, die Frage zu beantworten, jedoch nur unter Verwendung der von ihm bereitgestellten Informationen. Dies verringert die Tendenz des Modells, zu „halluzinieren“ oder eine Antwort zu finden, die plausibel, aber falsch ist. Die Werte und werden im nächsten Schritt bereitgestellt: context question const prompt = PromptTemplate.fromTemplate(`Answer the question based only on the following context: {context} Question: {question}`); Bauen Sie die Kette auf LangChain funktioniert durch den Aufbau von Verhaltensketten, die steuern, wie das LLM und andere Datenquellen abgefragt werden. In diesem Beispiel wird verwendet, das ein flexibleres Programmiererlebnis bietet als einige der ursprünglichen Schnittstellen von LangChain. LCEL Verwenden Sie eine , um eine LCEL-Kette zu erstellen. In dieser Kette wird beschrieben, wie die und generiert werden: Der Kontext wird mithilfe des zuvor erstellten Retrievers generiert, und die Frage wird durch Durchlaufen der Schritteingabe generiert. Die von Dewy abgerufenen Ergebnisse werden als Zeichenfolge formatiert, indem sie an die Funktion weitergeleitet werden. RunnableSequence context question formatDocumentsAsString Diese Kette bewirkt Folgendes: Es ruft Dokumente mit dem ab, ordnet sie dem zu und weist den Eingabewert der Kette zu. DewyRetriever context question Es formatiert die Eingabeaufforderungszeichenfolge mithilfe der und . context question Es übergibt die formatierte Eingabeaufforderung an den LLM, um eine Antwort zu generieren. Es formatiert die Antwort des LLM als Zeichenfolge. const chain = RunnableSequence.from([ { context: retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, prompt, model, new StringOutputParser(), ]); Führen Sie die Kette aus Nachdem die Kette nun erstellt wurde, führen Sie sie aus und geben Sie die Ergebnisse an die Konsole aus. Wie Sie sehen werden, ist ein Eingabeargument, das vom Aufrufer der Funktion bereitgestellt wird. question Wenn Sie die Kette mit ausführen, können Sie jeden Antwortblock sehen, der vom LLM zurückgegeben wird. Die Stream-Handler-Schleife ist irgendwie hässlich, aber sie filtert nur nach geeigneten Stream-Ergebnissen und schreibt sie nach (mit wären nach jedem Block neue Zeilen eingefügt worden). chain.streamLog() STDOUT console.log const stream = await chain.streamLog(question); // Write chunks of the response to STDOUT as they're received console.log("Answer:"); for await (const chunk of stream) { if (chunk.ops?.length > 0 && chunk.ops[0].op === "add") { const addOp = chunk.ops[0]; if ( addOp.path.startsWith("/logs/ChatOpenAI") && typeof addOp.value === "string" && addOp.value.length ) { process.stdout.write(addOp.value); } } } Fassen Sie alles als Befehl zusammen Nachdem Sie nun alle Teile gesehen haben, können Sie den erstellen. Dies sollte ähnlich wie der von zuvor aussehen, mit einigen zusätzlichen Importen. query load import { StringOutputParser } from "@langchain/core/output_parsers"; import { PromptTemplate } from "@langchain/core/prompts"; import { formatDocumentsAsString } from "langchain/util/document"; import { RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables"; import { ChatOpenAI } from "@langchain/openai"; import { Dewy } from 'dewy-ts'; import { DewyRetriever } from 'dewy-langchain'; import { success, error } from '../utils/colors'; export async function query(question: string, options: { collection: string, dewy_endpoint: string, openai_api_key: string }): Promise<void> { console.log(success(`Querying ${options.collection} collection for: "${question}"`)); try { const model = new ChatOpenAI({ openAIApiKey: options.openai_api_key, }); const dewy = new Dewy({ BASE: options.dewy_endpoint }) const retriever = new DewyRetriever({ dewy, collection: options.collection }); const prompt = PromptTemplate.fromTemplate(`Answer the question based only on the following context: {context} Question: {question}`); const chain = RunnableSequence.from([ { context: retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, prompt, model, new StringOutputParser(), ]); const stream = await chain.streamLog(question); // Write chunks of the response to STDOUT as they're received console.log("Answer:"); for await (const chunk of stream) { if (chunk.ops?.length > 0 && chunk.ops[0].op === "add") { const addOp = chunk.ops[0]; if ( addOp.path.startsWith("/logs/ChatOpenAI") && typeof addOp.value === "string" && addOp.value.length ) { process.stdout.write(addOp.value); } } } } catch (err: any) { console.error(error(`Failed to query: ${err.message}`)); } } Schritt 4: Erstellen der CLI Nachdem Dewy und LangChain.js integriert sind, besteht der nächste Schritt darin, die CLI-Schnittstelle zu erstellen. Verwenden Sie eine Bibliothek wie , um eine benutzerfreundliche Befehlszeilenschnittstelle zu erstellen, die Befehle zum Laden von Dokumenten in Dewy und zum Abfragen der Wissensdatenbank mithilfe von LangChain.js unterstützt. commander Schreiben Sie zunächst um, um die Unterbefehle und zu erstellen. Das Argument bestimmt, in welche Dewy-Sammlung das Dokument geladen werden soll (mit Dewy können Sie Dokumente in verschiedenen Sammlungen organisieren, ähnlich wie Dateiordner). Mit dem Argument können Sie angeben, wie eine Verbindung zu Dewy hergestellt wird. Standardmäßig wird davon ausgegangen, dass eine Instanz lokal auf Port ausgeführt wird. Schließlich konfiguriert das Argument (das standardmäßig eine Umgebungsvariable ist) die OpenAI-API: index.ts load query --collection --dewy-endpoint 8000 --openai_api_key #!/usr/bin/env ts-node-script import { Command } from 'commander'; import { load } from './commands/load'; import { query } from './commands/query'; const program = new Command(); program.name('dewy-qa').description('CLI tool for interacting with a knowledge base API').version('1.0.0'); const defaultOpenAIKey = process.env.OPENAI_API_KEY; program .command('load') .description("Load documents into Dewy from a URL") .option('--collection <collection>', 'Specify the collection name', 'main') .option('--dewy-endpoint <endpoint>', 'Specify the collection name', 'http://localhost:8000') .argument('<url>', 'URL to load into the knowledge base') .action(load); program .command('query') .description('Ask questions using an LLM and the loaded documents for answers') .option('--collection <collection>', 'Specify the collection name', 'main') .option('--dewy-endpoint <endpoint>', 'Specify the collection name', 'http://localhost:8000') .option('--openai-api-key <key>', 'Specify the collection name', defaultOpenAIKey) .argument('<question>', 'Question to ask the knowledge base') .action(query); program.parse(process.argv); OK, alles erledigt – war das nicht einfach? Sie können es ausprobieren, indem Sie den folgenden Befehl ausführen: dewy_qa load https://arxiv.org/pdf/2009.08553.pdf Sie sollten so etwas sehen wie Loading https://arxiv.org/pdf/2009.08553.pdf into collection: main File loaded successfully { "id": 18, "collection": "main", "extracted_text": null, "url": "https://arxiv.org/pdf/2009.08553.pdf", "ingest_state": "pending", "ingest_error": null } Das Extrahieren des Inhalts einer großen PDF-Datei kann ein oder zwei Minuten dauern. Daher wird häufig angezeigt, wenn Sie zum ersten Mal ein neues Dokument laden. "ingest_state": "pending" Versuchen Sie als Nächstes, einige Fragen zu stellen: dewy_qa query "tell me about RAG Sie sollten so etwas sehen wie Querying main collection for: "tell me about RAG" Answer: Based on the given context, RAG refers to the RAG proteins, which are involved in DNA binding and V(D)J recombination. The RAG1 and RAG2 proteins work together to bind specific DNA sequences known as RSS (recombination signal sequences) and facilitate the cutting and rearrangement of DNA segments during the process of V(D)J recombination... Abschluss Durch Befolgen dieser Anleitung haben Sie gelernt, wie Sie eine CLI erstellen, die Dewy zum Verwalten von Wissen und LangChain.js zum Verarbeiten von Fragen und Generieren von Antworten verwendet. Dieses Tool demonstriert die praktische Anwendung der Kombination einer strukturierten Wissensbasis mit der Analyseleistung von LLMs und ermöglicht es Entwicklern, intelligentere und reaktionsfähigere Anwendungen zu erstellen. Weiterführende Literatur und Ressourcen Dewy GitHub-Repository: https://github.com/Dewy Dewy TypeScript-Client-Repository: https://github.com/DewyKB/dewy-ts Dewy LangChain-Integrations-Repository: https://github.com/DewyKB/dewy_langchainjs LangChain.js-Dokumentation: https://js.langchain.com OpenAI-Dokumentation: https://platform.opnai.com