paint-brush
Dewy ve LangChain.js ile Soru Yanıtlayan CLI Oluşturmaile@kerinin
494 okumalar
494 okumalar

Dewy ve LangChain.js ile Soru Yanıtlayan CLI Oluşturma

ile Ryan11m2024/02/17
Read on Terminal Reader

Çok uzun; Okumak

Bu eğitimde Dewy ve LangChain.js'yi kullanarak soru yanıtlayan bir CLI aracının nasıl oluşturulacağına odaklanıyoruz.
featured image - Dewy ve LangChain.js ile Soru Yanıtlayan CLI Oluşturma
Ryan HackerNoon profile picture
0-item
1-item
2-item

Bu eğitimde Dewy ve LangChain.js'yi kullanarak soru yanıtlayan bir CLI aracının nasıl oluşturulacağına odaklanıyoruz. Dewy, geliştiricilerin bilgileri verimli bir şekilde düzenlemesine ve almasına yardımcı olan açık kaynaklı bir bilgi tabanıdır. LangChain.js, büyük dil modellerinin (LLM'ler) uygulamalara entegrasyonunu kolaylaştıran bir çerçevedir. Dewy'nin bilgiyi yönetme yeteneklerini LangChain.js'nin LLM entegrasyonuyla birleştirerek, karmaşık sorguları kesin ve ilgili bilgilerle yanıtlayan araçlar oluşturabilirsiniz.


Bu kılavuz, ortamınızı kurma, belgeleri Dewy'ye yükleme ve depolanan verilere dayanarak soruları yanıtlamak için LangChain.js aracılığıyla bir LLM kullanma konusunda size yol gösterir. Projelerini gelişmiş soru yanıtlama işlevleriyle geliştirmek isteyen mühendisler için tasarlanmıştır.

Neden Dewy ve LangChain.js?

Dewy, geliştiricilerin bilgileri depolama, düzenleme ve alma şeklini kolaylaştırmak için tasarlanmış bir OSS bilgi tabanıdır. Esnekliği ve kullanım kolaylığı, onu bilgi odaklı uygulamalar geliştirmeyi amaçlayan geliştiriciler için mükemmel bir seçim haline getiriyor.


LangChain.js ise geliştiricilerin LLM'leri uygulamalarına sorunsuz bir şekilde entegre etmelerini sağlayan güçlü bir çerçevedir. Geliştiriciler, Dewy'nin yapılandırılmış bilgi yönetimini LangChain.js'nin LLM yetenekleriyle birleştirerek, karmaşık sorguları anlayıp işleyebilen, kesin ve bağlamsal olarak anlamlı yanıtlar sunan gelişmiş soru yanıtlama sistemleri oluşturabilir.

Amaç

Amacımız basit ama güçlü bir soru yanıtlayan CLI betiği oluşturmaktır. Bu komut dosyası, kullanıcıların belgeleri Dewy bilgi tabanına yüklemesine ve ardından LangChain.js aracılığıyla bir Yüksek Lisans kullanarak Dewy'de depolanan bilgilere dayanarak soruları yanıtlamasına olanak tanıyacak. Bu eğitim, ortamınızı kurmaktan CLI betiğini uygulamaya kadar olan süreç boyunca size rehberlik edecektir.


Basit bir soru yanıtlama uygulaması oluşturmak için LangChain'i nasıl kullanacağınızı ve uygulamanızın, sağladığınız belirli belgelere dayalı olarak soruları yanıtlamasına olanak tanıyarak Dewy'yi bir bilgi kaynağı olarak nasıl entegre edeceğinizi öğreneceksiniz.

Önkoşullar

Eğiticiye dalmadan önce aşağıdaki önkoşulların karşılandığından emin olun:

  • TypeScript programlamaya ilişkin temel bilgiler
  • CLI araçları geliştirme konusunda bilgi sahibi olmak
  • Yerel makinenizde çalışan Dewy'nin bir kopyası (yardıma ihtiyacınız olursa burada Dewy'nin kurulum talimatlarına bakın).

1. Adım: Projenizi Kurun

Devam etmek istiyorsanız bu örneğin son kodu Dewy deposunda mevcuttur.

Öncelikle TypeScript CLI projesi için bir dizin oluşturun ve dizine geçin.

 mkdir dewy_qa cd dewy_qa

Dizin kurulumuyla TypeScript'i yükleyebilir ve projeyi başlatabilirsiniz:

 npm init -y npm i typescript --save-dev npx tsc --init

Ortamınıza bağlı olarak TypeScript yapılandırmanızda bazı değişiklikler yapmanız gerekebilir. tsconfig.json dosyanızın aşağıdaki gibi göründüğünden emin olun:

 { "compilerOptions": { "target": "ES6", "module": "CommonJS", "moduleResolution": "node", "declaration": true, "outDir": "./dist", "esModuleInterop": true, "strict": true, }

Artık CLI uygulamasını oluşturmaya hazırsınız. Kodun çok dağınık olmasını önlemek için, kodu aşağıdaki düzende çeşitli dizinler halinde düzenleyin

 dewy_qa/ ├── commands/ │ └── ... ├── utils/ │ └── ... ├── index.ts ├── package.json └── tsconfig.ts

Her komut, commands dizininde uygulanacak ve paylaşılan kod, utils dizinine gidecek. CLI uygulamasının giriş noktası index.ts dosyasıdır.

index.ts basit bir "merhaba dünya" sürümüyle başlayın; bir sonraki bölümde doldurmaya başlayacaksınız

 #!/usr/bin/env ts-node-script console.log("hello world");

Ortamın doğru kurulduğunu doğrulamak için aşağıdaki komutu çalıştırmayı deneyin; konsolda "merhaba dünya" yazdığını görmelisiniz:

 npx ts-node index.ts

Bu çok uzun komutu her seferinde yazmak yerine, package.json dosyasında komut için bir girdi oluşturalım. Bu, CLI'yi nasıl çağıracağımızı hatırlamamıza yardımcı olacak ve komut olarak kurulumu kolaylaştıracaktır:

 { ... "bin": { "dewy_qa": "./index.ts" } ... }

Artık betiğinizi npm exec dewy_qa veya npm link çalıştırabilir ve sadece dewy_qa olarak çalıştırabilirsiniz.

2. Adım: Belge yüklemeyi uygulayın

Dewy istemcisini kurarak belgeleri yükleyin. İlk adım projeye bazı bağımlılıklar eklemektir. Bunlardan ilki, Dewy'nin istemci kütüphanesi olan dewy-ts . İkincisi, bağımsız değişken ayrıştırma, alt komutlar ve daha fazlasını içeren bir CLI uygulaması oluşturmamıza yardımcı olacak commander . Son olarak, chalk istemleri daha renkli hale getirin.

 npm install dewy-ts commander chalk

Daha sonra, yükleme komutunun mantığını uygulayın. Bunu commands/load.ts adlı ayrı bir dosyada yapacaksınız. Bu dosya, bir URL ve bazı ek seçenekler bekleyen load adlı bir işlevi uygular; bu, daha sonraki bir bölümde CLI ile bağlanacaktır.


Dewy, belge yüklemeyi son derece basit hale getirir; yalnızca istemciyi kurun ve yüklemek istediğiniz dosyanın URL'siyle addDocument çağırın. Dewy, PDF'nin içeriğinin çıkarılmasıyla, bunları bir Yüksek Lisans'a göndermek için tam olarak doğru boyuttaki parçalara bölmekle ve anlamsal arama için dizine eklemekle ilgilenir.

 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}`)); } }

Bazı işlevlerin ../utils/colors adresinden içe aktarıldığını fark etmiş olabilirsiniz. Bu dosya, konsol çıktısını renklendirmek için bazı yardımcılar kurar; başka bir yerde kullanılabilmesi için utils koyun:

 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);

3. Adım: Soru yanıtlamayı uygulayın

Belgeleri Dewy'ye yükleme yeteneği sayesinde, soruları yanıtlamak için LLM'leri kullanmak üzere LangChain.js'yi entegre etmenin zamanı geldi. Bu adım, LangChain.js'nin Dewy bilgi tabanını sorgulamak ve yanıtları oluşturmak için bir Yüksek Lisans kullanarak sonuçları işlemek üzere kurulmasını içerir.


Başlamak için, OpenAI API'sini LLM olarak kullanmak için bazı ek paketler ( langchain ve openai yükleyin:

 npm install dewy-langchain langchain @langchain/openai openai

Bu komut biraz uzun olduğundan, sonunda birleştirmeden önce birkaç parçasını inceleyeceğiz.

OpenAI ve Dewy için Müşteriler Oluşturun

Kurulum için ilk şey Dewy (daha önce olduğu gibi) ve bir LLM'dir. Öncekinden bir fark, dewy bir DewyRetriever oluşturmak için kullanılmasıdır: bu, LangChain tarafından bir zincirin parçası olarak bilgi almak için kullanılan özel bir türdür. Bir dakika içinde av köpeğinin nasıl kullanıldığını göreceksiniz.

 const model = new ChatOpenAI({ openAIApiKey: options.openai_api_key, }); const dewy = new Dewy({ BASE: options.dewy_endpoint }) const retriever = new DewyRetriever({ dewy, collection });

LangChain İstemi Oluşturun

Bu, "zincir" oluşturulduğunda sağlanacak olan ek bağlam için yer tutucularla birlikte LLM'ye nasıl davranması gerektiği talimatını veren bir dize şablonudur. Bu durumda, Yüksek Lisans'a soruyu yanıtlaması talimatı verilir, ancak yalnızca kendisine sağlanan bilgileri kullanarak. Bu, modelin "halüsinasyon görme" veya makul ama yanlış bir cevap uydurma eğilimini azaltır. context ve question değerleri bir sonraki adımda verilmektedir:

 const prompt = PromptTemplate.fromTemplate(`Answer the question based only on the following context: {context} Question: {question}`);

Zinciri Oluşturun

LangChain, LLM'nin ve diğer veri kaynaklarının nasıl sorgulanacağını kontrol eden davranış "zincirleri" oluşturarak çalışır. Bu örnekte, LangChain'in bazı orijinal arayüzlerinden daha esnek bir programlama deneyimi sağlayan LCEL kullanılmaktadır.


Bir LCEL zinciri oluşturmak için RunnableSequence kullanın. Bu zincir, context ve question değerlerinin nasıl oluşturulacağını açıklar: bağlam, daha önce oluşturulan alıcı kullanılarak oluşturulur ve soru, adımın girdisinden geçilerek oluşturulur. Dewy'nin aldığı sonuçlar, formatDocumentsAsString işlevine aktarılarak bir dize olarak biçimlendirilir.


Bu zincir şunları yapar:

  1. DewyRetriever kullanarak belgeleri alır ve bunları context atar ve zincirin giriş değerini question öğesine atar.
  2. context ve question değişkenlerini kullanarak bilgi istemi dizesini biçimlendirir.
  3. Bir yanıt oluşturmak için biçimlendirilmiş istemi LLM'ye iletir.
  4. LLM'nin yanıtını bir dize olarak biçimlendirir.
 const chain = RunnableSequence.from([ { context: retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, prompt, model, new StringOutputParser(), ]);

Zinciri yürüt

Artık zincir oluşturulduğuna göre, onu yürütün ve sonuçları konsola aktarın. Göreceğiniz gibi question , işlevi çağıran kişi tarafından sağlanan bir girdi argümanıdır.


Zinciri chain.streamLog() kullanarak yürütmek, LLM'den döndürülen her yanıt parçasını görmenize olanak tanır. Akış işleyici döngüsü biraz çirkin, ancak yalnızca uygun akış sonuçlarını filtreliyor ve bunları STDOUT yazıyor ( console.log kullanıldığında her parçadan sonra yeni satırlar eklenirdi).

 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); } } }

Hepsini bir komut olarak bir araya getirin

Artık tüm parçaları gördüğünüze göre query komutunu oluşturmaya hazırsınız. Bu, bazı ek içe aktarmalarla birlikte önceki load komutuna benzer görünmelidir.

 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}`)); } }

Adım 4: CLI'yi Oluşturma

Dewy ve LangChain.js entegre edildiğinde bir sonraki adım CLI arayüzünü oluşturmaktır. Belgeleri Dewy'ye yüklemeye ve LangChain.js kullanarak bilgi tabanını sorgulamaya yönelik komutları destekleyen, kullanıcı dostu bir komut satırı arayüzü oluşturmak için commander gibi bir kitaplık kullanın.


İlk olarak, load ve query alt komutlarını oluşturmak için index.ts dosyasını yeniden yazın. --collection argümanı, belgenin hangi Dewy koleksiyonuna yüklenmesi gerektiğini belirler (Dewy, belgeleri dosya klasörlerine benzer şekilde farklı koleksiyonlar halinde düzenlemenize olanak tanır). --dewy-endpoint bağımsız değişkeni, Dewy'ye nasıl bağlanacağınızı belirlemenizi sağlar; varsayılan olarak, 8000 bağlantı noktasında yerel olarak çalışan bir örneğin olduğu varsayılır. Son olarak --openai_api_key argümanı (varsayılan olarak bir ortam değişkenidir) OpenAI API'sini yapılandırır:

 #!/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);

Tamam, her şey bitti; bu kadar kolay değil miydi? Komutu çalıştırarak deneyebilirsiniz:

 dewy_qa load https://arxiv.org/pdf/2009.08553.pdf

Şöyle bir şey görmelisiniz

 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 }

Büyük bir PDF'nin içeriğini çıkarmak bir veya iki dakika sürebilir, bu nedenle yeni bir belgeyi ilk yüklediğinizde sıklıkla "ingest_state": "pending" görürsünüz.

Daha sonra bazı sorular sormayı deneyin:

 dewy_qa query "tell me about RAG

Şöyle bir şey görmelisiniz

 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...

Çözüm

Bu kılavuzu takip ederek bilgiyi yönetmek için Dewy'yi ve soruları işlemek ve yanıtlar oluşturmak için LangChain.js'yi kullanan bir CLI'nin nasıl oluşturulacağını öğrendiniz. Bu araç, yapılandırılmış bir bilgi tabanını LLM'lerin analitik gücüyle birleştirmenin pratik uygulamasını göstererek geliştiricilerin daha akıllı ve duyarlı uygulamalar oluşturmasına olanak tanır.

İlave Okumalar ve Kaynaklar