Dans ce didacticiel, nous nous concentrons sur la façon de créer un outil CLI de réponse aux questions à l'aide de Dewy et LangChain.js. Dewy est une base de connaissances open source qui aide les développeurs à organiser et à récupérer efficacement les informations. LangChain.js est un framework qui simplifie l'intégration de grands modèles de langage (LLM) dans les applications. En combinant les capacités de gestion des connaissances de Dewy avec l'intégration LLM de LangChain.js, vous pouvez créer des outils qui répondent à des requêtes complexes avec des informations précises et pertinentes. Ce guide vous guide dans la configuration de votre environnement, le chargement de documents dans Dewy et l'utilisation d'un LLM via LangChain.js pour répondre aux questions basées sur les données stockées. Il est conçu pour les ingénieurs qui cherchent à améliorer leurs projets avec des fonctionnalités avancées de réponse aux questions. Pourquoi Dewy et LangChain.js ? est une base de connaissances OSS conçue pour rationaliser la façon dont les développeurs stockent, organisent et récupèrent les informations. Sa flexibilité et sa facilité d'utilisation en font un excellent choix pour les développeurs souhaitant créer des applications basées sur la connaissance. Dewy , quant à lui, est un framework puissant qui permet aux développeurs d'intégrer de manière transparente les LLM dans leurs applications. En combinant la gestion structurée des connaissances de Dewy avec les capacités LLM de LangChain.js, les développeurs peuvent créer des systèmes de questions-réponses sophistiqués capables de comprendre et de traiter des requêtes complexes, offrant des réponses précises et contextuellement pertinentes. LangChain.js Le but Notre objectif est de créer un script CLI de réponse aux questions simple mais puissant. Ce script permettra aux utilisateurs de charger des documents dans la base de connaissances Dewy, puis d'utiliser un LLM, via LangChain.js, pour répondre à des questions basées sur les informations stockées dans Dewy. Ce didacticiel vous guidera tout au long du processus, depuis la configuration de votre environnement jusqu'à la mise en œuvre du script CLI. Vous apprendrez comment utiliser LangChain pour créer une application simple de réponse aux questions et comment intégrer Dewy en tant que source de connaissances, permettant à votre application de répondre aux questions basées sur les documents spécifiques que vous lui fournissez. Conditions préalables Avant de plonger dans le didacticiel, assurez-vous que les conditions préalables suivantes sont couvertes : Connaissance de base de la programmation Typescript Familiarité avec le développement d'outils CLI Une copie de Dewy exécutée sur votre ordinateur local (voir de Dewy si vous avez besoin d'aide ici). les instructions d'installation Étape 1 : Configurez votre projet Le code final de cet exemple est disponible si vous souhaitez aller de l'avant. dans le dépôt Dewy Tout d’abord, créez un répertoire pour le projet TypeScript CLI et accédez au répertoire mkdir dewy_qa cd dewy_qa Une fois le répertoire configuré, vous pouvez installer TypeScript et initialiser le projet : npm init -y npm i typescript --save-dev npx tsc --init En fonction de votre environnement, vous devrez peut-être apporter quelques modifications à votre configuration TypeScript. Assurez-vous que votre ressemble à ceci : tsconfig.json { "compilerOptions": { "target": "ES6", "module": "CommonJS", "moduleResolution": "node", "declaration": true, "outDir": "./dist", "esModuleInterop": true, "strict": true, } Vous êtes maintenant prêt à créer l'application CLI. Pour éviter que le code ne devienne trop compliqué, organisez-le dans plusieurs répertoires, avec la disposition suivante dewy_qa/ ├── commands/ │ └── ... ├── utils/ │ └── ... ├── index.ts ├── package.json └── tsconfig.ts Chaque commande sera implémentée dans le répertoire et le code partagé ira dans le répertoire . Le point d'entrée de l'application CLI est le fichier . commands utils index.ts Commencez par une simple version "hello world" d' - vous commencerez à la remplir dans la section suivante index.ts #!/usr/bin/env ts-node-script console.log("hello world"); Pour vérifier que l'environnement est correctement configuré, essayez d'exécuter la commande suivante : vous devriez voir "hello world" imprimé dans la console : npx ts-node index.ts Plutôt que de taper cette très longue commande à chaque fois, créons une entrée dans pour la commande. Cela nous aidera à nous rappeler comment appeler la CLI et facilitera son installation en tant que commande : package.json { ... "bin": { "dewy_qa": "./index.ts" } ... } Vous pouvez maintenant exécuter votre script avec ou le package et l'exécuter simplement comme npm exec dewy_qa npm link dewy_qa Étape 2 : Mettre en œuvre le chargement des documents Chargez des documents en configurant le client Dewy. La première étape consiste à ajouter quelques dépendances au projet. La première est , la bibliothèque client de Dewy. Le second est , qui nous aidera à créer une application CLI avec une analyse des arguments, des sous-commandes, etc. Enfin, rend les invites plus colorées. dewy-ts commander chalk npm install dewy-ts commander chalk Ensuite, implémentez la logique de la commande de chargement. Vous ferez cela dans un fichier séparé nommé . Ce fichier implémente une fonction nommée , qui attend une URL et quelques options supplémentaires - cela sera connecté à la CLI dans une section ultérieure. commands/load.ts load Dewy rend le chargement des documents très simple : il suffit de configurer le client et d'appeler avec l'URL du fichier que vous souhaitez charger. Dewy s'occupe d'extraire le contenu du PDF, de le diviser en morceaux de la bonne taille pour l'envoyer à un LLM et de les indexer pour une recherche sémantique. 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}`)); } } Vous avez peut-être remarqué que certaines fonctions ont été importées depuis . Ce fichier configure simplement quelques assistants pour colorer la sortie de la console - placez-le dans afin qu'il puisse être utilisé ailleurs : ../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); Étape 3 : Mettre en œuvre la réponse aux questions Avec la possibilité de charger des documents dans Dewy, il est temps d'intégrer LangChain.js pour utiliser les LLM pour répondre aux questions. Cette étape implique la configuration de LangChain.js pour interroger la base de connaissances Dewy et traiter les résultats à l'aide d'un LLM pour générer des réponses. Pour commencer, installez quelques packages supplémentaires - et pour utiliser l'API OpenAI comme LLM : langchain openai npm install dewy-langchain langchain @langchain/openai openai Cette commande est assez longue, nous allons donc en parcourir plusieurs éléments avant de les combiner à la fin. Créer des clients pour OpenAI et Dewy La première chose à configurer est Dewy (comme avant) et un LLM. Une différence par rapport à avant est que est utilisé pour construire un : il s'agit d'un type spécial utilisé par LangChain pour récupérer des informations dans le cadre d'une chaîne. Vous verrez comment le retriever est utilisé dans une minute. 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 }); Créer une invite LangChain Il s'agit d'un modèle de chaîne qui indique au LLM comment il doit se comporter, avec des espaces réservés pour un contexte supplémentaire qui seront fournis lors de la création de la « chaîne ». Dans ce cas, le LLM est chargé de répondre à la question, mais uniquement en utilisant les informations fournies. Cela réduit la tendance du modèle à « halluciner » ou à inventer une réponse plausible mais fausse. Les valeurs du et sont fournies à l'étape suivante : context question const prompt = PromptTemplate.fromTemplate(`Answer the question based only on the following context: {context} Question: {question}`); Construire la chaîne LangChain fonctionne en créant des « chaînes » de comportement qui contrôlent la manière d'interroger le LLM et d'autres sources de données. Cet exemple utilise , qui offre une expérience de programmation plus flexible que certaines des interfaces originales de LangChain. LCEL Utilisez un pour créer une chaîne LCEL. Cette chaîne décrit comment générer les valeurs et : le contexte est généré à l'aide du récupérateur créé précédemment et la question est générée en passant par l'entrée de l'étape. Les résultats récupérés par Dewy sont formatés sous forme de chaîne en les redirigeant vers la fonction . RunnableSequence context question formatDocumentsAsString Cette chaîne effectue les opérations suivantes : Il récupère les documents à l'aide du , les affecte au et attribue la valeur d'entrée de la chaîne à . DewyRetriever context question Il formate la chaîne d'invite à l'aide des variables et . context question Il transmet l'invite formatée au LLM pour générer une réponse. Il formate la réponse du LLM sous forme de chaîne. const chain = RunnableSequence.from([ { context: retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, prompt, model, new StringOutputParser(), ]); Exécuter la chaîne Maintenant que la chaîne a été construite, exécutez-la et affichez les résultats sur la console. Comme vous le verrez, est un argument d'entrée fourni par l'appelant de la fonction. question L'exécution de la chaîne à l'aide vous permet de voir chaque morceau de réponse tel qu'il est renvoyé par le LLM. La boucle du gestionnaire de flux est en quelque sorte moche, mais elle filtre simplement les résultats du flux appropriés et les écrit dans (en utilisant , elle aurait ajouté des nouvelles lignes après chaque morceau). 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); } } } Rassemblez tout cela comme une commande Maintenant que vous avez vu tous les éléments, vous êtes prêt à créer la commande . Cela devrait ressembler à la commande d'avant, avec quelques importations supplémentaires. 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}`)); } } Étape 4 : Création de la CLI Avec Dewy et LangChain.js intégrés, l'étape suivante consiste à créer l'interface CLI. Utilisez une bibliothèque telle que pour créer une interface de ligne de commande conviviale qui prend en charge les commandes permettant de charger des documents dans Dewy et d'interroger la base de connaissances à l'aide de LangChain.js. commander Tout d’abord, réécrivez pour créer les sous-commandes et . L'argument détermine dans quelle collection Dewy le document doit être chargé (Dewy vous permet d'organiser les documents en différentes collections, similaires aux dossiers de fichiers). L'argument vous permet de spécifier comment vous connecter à Dewy - par défaut, une instance exécutée localement sur le port est supposée. Enfin, l'argument (qui est par défaut une variable d'environnement) configure l'API OpenAI : 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, tout est terminé – n'était-ce pas facile ? Vous pouvez l'essayer en exécutant la commande : dewy_qa load https://arxiv.org/pdf/2009.08553.pdf Vous devriez voir quelque chose comme 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 } L'extraction du contenu d'un PDF volumineux peut prendre une minute ou deux, c'est pourquoi vous verrez souvent lorsque vous chargez pour la première fois un nouveau document. "ingest_state": "pending" Ensuite, essayez de poser quelques questions : dewy_qa query "tell me about RAG Vous devriez voir quelque chose comme 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... Conclusion En suivant ce guide, vous avez appris à créer une CLI qui utilise Dewy pour gérer les connaissances et LangChain.js pour traiter les questions et générer des réponses. Cet outil démontre l'application pratique de la combinaison d'une base de connaissances structurée avec la puissance analytique des LLM, permettant aux développeurs de créer des applications plus intelligentes et réactives. Lectures complémentaires et ressources Dépôt Dewy GitHub : https://github.com/Dewy Dépôt client Dewy TypeScript : https://github.com/DewyKB/dewy-ts Dépôt d'intégration Dewy LangChain : https://github.com/DewyKB/dewy_langchainjs Documentation LangChain.js : https://js.langchain.com Documentation OpenAI : https://platform.opnai.com