Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial ini, Anda menggunakan LangChain.js untuk membangun agen LangChain.js yang memungkinkan karyawan perusahaan NorthWind mengajukan pertanyaan terkait sumber daya manusia. Dengan menggunakan kerangka kerja, Anda menghindari kode boilerplate biasanya diperlukan untuk agen LangChain.js dan integrasi layanan Azure, memungkinkan Anda untuk fokus pada kebutuhan bisnis Anda.
Di tutorial ini, Anda akan:
- Menyiapkan agen LangChain.js
- Mengintegrasikan sumber daya Azure ke agen LangChain.js Anda
- Anda dapat menguji agen LangChain.js Anda di LangSmith Studio
NorthWind bergantung pada dua sumber data: dokumentasi SDM publik yang dapat diakses oleh semua karyawan dan database SDM rahasia yang berisi data karyawan sensitif. Tutorial ini berfokus pada pembangunan agen LangChain.js yang menentukan apakah pertanyaan karyawan dapat dijawab menggunakan dokumen SDM publik. Jika demikian, agen LangChain.js memberikan jawabannya secara langsung.
Peringatan
Artikel ini menggunakan kunci untuk mengakses sumber daya. Di lingkungan produksi, praktik terbaik yang direkomendasikan adalah menggunakan Azure RBAC dan identitas terkelola. Pendekatan ini menghilangkan kebutuhan untuk mengelola atau memutar kunci, meningkatkan keamanan dan menyederhanakan kontrol akses.
Prasyarat
- Akun Azure aktif. Buat akun secara gratis jika Anda tidak memilikinya.
- Node.js LTS terinstal pada sistem Anda.
- TypeScript untuk menulis dan mengkompilasi kode TypeScript.
- LangChain.js perpustakaan untuk membangun agen.
- Opsional: LangSmith untuk memantau penggunaan AI. Anda memerlukan nama proyek, kunci, dan titik akhir.
- Opsional: LangGraph Studio untuk debugging rantai LangGraph dan agen LangChain.js.
- Sumber daya Pencarian Azure AI: Pastikan Anda memiliki titik akhir sumber daya, kunci admin (untuk penyisipan dokumen), kunci kueri (untuk membaca dokumen), dan nama indeks.
-
Sumber daya Azure OpenAI: Anda memerlukan nama instans sumber daya, kunci, dan dua model dengan versi API mereka:
- Model penyematan seperti
text-embedding-ada-002
. - Model bahasa besar seperti
gpt-4o
.
- Model penyematan seperti
Arsitektur agen
Kerangka kerja LangChain.js menyediakan alur keputusan untuk membangun agen cerdas sebagai LangGraph. Dalam tutorial ini, Anda membuat agen LangChain.js yang terintegrasi dengan Azure AI Search dan Azure OpenAI untuk menjawab pertanyaan terkait SDM. Arsitektur dari agen ini dirancang untuk:
- Tentukan apakah pertanyaan relevan dengan dokumentasi SDM.
- Ambil dokumen yang relevan dari Azure AI Search.
- Gunakan Azure OpenAI untuk menghasilkan jawaban berdasarkan dokumen dan model LLM yang diambil.
Komponen Utama:
Struktur grafik: Agen LangChain.js diwakili sebagai grafik, di mana:
- Simpul melakukan tugas tertentu, seperti membuat keputusan atau mengambil data.
- Tepi menentukan aliran antar simpul, menentukan urutan operasi.
Integrasi Azure AI Search:
- Menyisipkan dokumen SDM ke penyimpanan vektor sebagai penyematan.
- Menggunakan model penyematan (
text-embedding-ada-002
) untuk membuat penyematan ini. - Mengambil dokumen yang relevan berdasarkan permintaan pengguna.
Integrasi Azure OpenAI:
- Menggunakan model bahasa besar (
gpt-4o
) untuk:- Menentukan apakah pertanyaan dapat dijawab dari dokumen SDM umum.
- Menghasilkan jawaban dengan perintah menggunakan konteks dari dokumen dan pertanyaan pengguna.
- Menggunakan model bahasa besar (
Tabel berikut ini memiliki contoh pertanyaan pengguna yang relevan dan dapat dijawab serta pertanyaan yang tidak relevan dari dokumen Sumber Daya Manusia umum.
Pertanyaan | Relevansi dengan Dokumen SDM |
---|---|
Does the NorthWind Health Plus plan cover eye exams? |
Relevan. Dokumen SDM, seperti buku pegangan karyawan, harus memberikan jawaban. |
How much of my perks + benefits have I spent? |
Tidak relevan. Pertanyaan ini memerlukan akses ke data karyawan rahasia, yang berada di luar cakupan agen ini. |
Dengan menggunakan kerangka kerja, Anda menghindari kode boilerplate biasanya diperlukan untuk agen LangChain.js dan integrasi layanan Azure, memungkinkan Anda untuk fokus pada kebutuhan bisnis Anda.
Menginisialisasi proyek Node.js Anda
Di direktori baru, inisialisasi proyek Node.js Anda untuk agen TypeScript Anda. Jalankan perintah berikut:
npm init -y
npm pkg set type=module
npx tsc --init
Membuat file lingkungan
Buat .env
file untuk pengembangan lokal untuk menyimpan variabel lingkungan untuk sumber daya Azure dan LangGraph. Pastikan nama instans sumber daya untuk embedding dan LLM hanya berupa nama sumber daya, bukan endpoint.
Opsional: Jika menggunakan LangSmith, atur LANGSMITH_TRACING
ke true
untuk pengembangan lokal. Nonaktifkan (false
) atau hapus di lingkungan produksi.
Pasang dependensi
Instal dependensi Azure untuk Azure AI Search:
npm install @azure/search-documents
Instal dependensi LangChain.js untuk membuat dan menggunakan agen:
npm install @langchain/community @langchain/core @langchain/langgraph @langchain/openai langchain
Pasang dependensi pengembangan untuk pengembangan lokal:
npm install --save-dev dotenv
Membuat file konfigurasi sumber daya pencarian Azure AI
Untuk mengelola berbagai sumber daya dan model Azure yang digunakan dalam tutorial ini, buat file konfigurasi tertentu untuk setiap sumber daya. Pendekatan ini memastikan kejelasan dan pemisahan kekhawatiran, sehingga lebih mudah untuk mengelola dan memelihara konfigurasi.
Konfigurasi untuk mengunggah dokumen ke penyimpanan vektor
File konfigurasi Azure AI Search menggunakan kunci admin untuk menyisipkan dokumen ke penyimpanan vektor. Kunci ini penting untuk mengelola penyerapan data ke Dalam Azure AI Search.
const endpoint = process.env.AZURE_AISEARCH_ENDPOINT;
const adminKey = process.env.AZURE_AISEARCH_ADMIN_KEY;
const indexName = process.env.AZURE_AISEARCH_INDEX_NAME;
export const VECTOR_STORE_ADMIN = {
endpoint,
key: adminKey,
indexName,
};
LangChain.js mengabstraksi kebutuhan untuk menentukan skema untuk penyerapan data ke Azure AI Search, menyediakan skema default yang cocok untuk sebagian besar skenario. Abstraksi ini menyederhanakan proses dan mengurangi kebutuhan akan definisi skema kustom.
Konfigurasi untuk mengkueri penyimpanan vektor
Untuk mengkueri penyimpanan vektor, buat file konfigurasi terpisah:
import {
AzureAISearchConfig,
AzureAISearchQueryType,
} from "@langchain/community/vectorstores/azure_aisearch";
const endpoint = process.env.AZURE_AISEARCH_ENDPOINT;
const queryKey = process.env.AZURE_AISEARCH_QUERY_KEY;
const indexName = process.env.AZURE_AISEARCH_INDEX_NAME;
export const DOC_COUNT = 3;
export const VECTOR_STORE_QUERY: AzureAISearchConfig = {
endpoint,
key: queryKey,
indexName,
search: {
type: AzureAISearchQueryType.Similarity,
},
};
Saat mengkueri penyimpanan vektor, gunakan kunci kueri sebagai gantinya. Pemisahan kunci ini memastikan akses yang aman dan efisien ke sumber daya.
Membuat file konfigurasi sumber daya Azure OpenAI
Untuk mengelola dua model yang berbeda, penyematan dan LLM, buat file konfigurasi terpisah. Pendekatan ini memastikan kejelasan dan pemisahan kekhawatiran, sehingga lebih mudah untuk mengelola dan memelihara konfigurasi.
Konfigurasi penyematan pada penyimpanan vektor
Untuk membuat penyematan untuk menyisipkan dokumen ke penyimpanan vektor Azure AI Search, buat file konfigurasi:
const key = process.env.AZURE_OPENAI_EMBEDDING_KEY;
const instance = process.env.AZURE_OPENAI_EMBEDDING_INSTANCE;
const apiVersion =
process.env.AZURE_OPENAI_EMBEDDING_API_VERSION || "2023-05-15";
const model =
process.env.AZURE_OPENAI_EMBEDDING_MODEL || "text-embedding-ada-002";
export const EMBEDDINGS_CONFIG = {
azureOpenAIApiKey: key,
azureOpenAIApiInstanceName: instance,
azureOpenAIApiEmbeddingsDeploymentName: model,
azureOpenAIApiVersion: apiVersion,
maxRetries: 1,
};
Konfigurasi untuk LLM untuk menghasilkan jawaban
Untuk membuat jawaban dari model bahasa besar, buat file konfigurasi:
const key = process.env.AZURE_OPENAI_COMPLETE_KEY;
const instance = process.env.AZURE_OPENAI_COMPLETE_INSTANCE;
const apiVersion =
process.env.AZURE_OPENAI_COMPLETE_API_VERSION || "2024-10-21";
const model = process.env.AZURE_OPENAI_COMPLETE_MODEL || "gpt-4o";
const maxTokens = process.env.AZURE_OPENAI_COMPLETE_MAX_TOKENS;
export const LLM_CONFIG = {
model,
azureOpenAIApiKey: key,
azureOpenAIApiInstanceName: instance,
azureOpenAIApiDeploymentName: model,
azureOpenAIApiVersion: apiVersion,
maxTokens: maxTokens ? parseInt(maxTokens, 10) : 100,
maxRetries: 1,
timeout: 60000,
};
Konstanta dan perintah
Aplikasi AI sering mengandalkan string dan perintah konstanta. Kelola konstanta ini dengan file terpisah.
Buat prompt sistem:
export const SYSTEM_PROMPT = `Answer the query with a complete paragraph based on the following context:`;
Buat konstanta simpul:
export const ANSWER_NODE = "vector_store_retrieval";
export const DECISION_NODE = "requires_hr_documents";
export const START = "__start__";
export const END = "__end__";
Buat contoh kueri pengguna:
export const USER_QUERIES = [
"Does the NorthWind Health plus plan cover eye exams?",
"What is included in the NorthWind Health plus plan that is not included in the standard?",
"What happens in a performance review?",
];
Memuat dokumen ke Dalam Azure AI Search
Untuk memuat dokumen ke Azure AI Search, gunakan LangChain.js untuk menyederhanakan proses. Dokumen, yang disimpan sebagai PDF, dikonversi menjadi embedding dan dimasukkan ke dalam penyimpanan vektor. Proses ini memastikan bahwa dokumen siap untuk pengambilan dan kueri yang efisien.
Pertimbangan Utama:
- abstraksiLangChain.js: LangChain.js menangani banyak kompleksitas, seperti definisi skema dan pembuatan klien, membuat prosesnya mudah.
- Logika pembatasan dan coba lagi: Meskipun kode sampel menyertakan fungsi tunggu minimal, aplikasi produksi harus menerapkan penanganan kesalahan komprehensif dan logika coba lagi untuk mengelola pembatasan dan kesalahan sementara.
Langkah-langkah untuk memuat dokumen
Temukan Dokumen PDF: Dokumen disimpan di direktori data.
Muat PDF ke LangChain.js: Gunakan
loadPdfsFromDirectory
fungsi untuk memuat dokumen. Fungsi ini menggunakan metode komunitas LangChain.jsPDFLoader.load
untuk membaca setiap file dan mengembalikan larikDocument[]
. Array ini adalah format dokumen LangChain.js standar.import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf"; import { waiter } from "../utils/waiter.js"; import { loadDocsIntoAiSearchVector } from "./load_vector_store.js"; import fs from "fs/promises"; import path from "path"; export async function loadPdfsFromDirectory( embeddings: any, dirPath: string, ): Promise<void> { try { const files = await fs.readdir(dirPath); console.log( `PDF: Loading directory ${dirPath}, ${files.length} files found`, ); for (const file of files) { if (file.toLowerCase().endsWith(".pdf")) { const fullPath = path.join(dirPath, file); console.log(`PDF: Found ${fullPath}`); const pdfLoader = new PDFLoader(fullPath); console.log(`PDF: Loading ${fullPath}`); const docs = await pdfLoader.load(); console.log(`PDF: Sending ${fullPath} to index`); const storeResult = await loadDocsIntoAiSearchVector(embeddings, docs); console.log(`PDF: Indexing result: ${JSON.stringify(storeResult)}`); await waiter(1000 * 60); // waits for 1 minute between files } } } catch (err) { console.error("Error loading PDFs:", err); } }
Menyisipkan dokumen ke dalam Azure AI Search: Gunakan
loadDocsIntoAiSearchVector
fungsi untuk mengirim array dokumen ke penyimpanan vektor Azure AI Search. Fungsi ini menggunakan klien embedding untuk memproses dokumen dan menyertakan fungsi tunggu sederhana untuk mengatasi pembatasan. Untuk produksi, terapkan mekanisme coba lagi/backoff yang kuat.import { AzureAISearchVectorStore } from "@langchain/community/vectorstores/azure_aisearch"; import type { Document } from "@langchain/core/documents"; import type { EmbeddingsInterface } from "@langchain/core/embeddings"; import { VECTOR_STORE_ADMIN } from "../config/vector_store_admin.js"; export async function loadDocsIntoAiSearchVector( embeddings: EmbeddingsInterface, documents: Document[], ): Promise<AzureAISearchVectorStore> { const vectorStore = await AzureAISearchVectorStore.fromDocuments( documents, embeddings, VECTOR_STORE_ADMIN, ); return vectorStore; }
Membuat alur kerja agen
Di LangChain.js, buat agen LangChain.js dengan LangGraph. LangGraph memungkinkan Anda menentukan simpul dan tepi:
- Nodo: tempat pekerjaan berlangsung.
- Edge: menentukan koneksi antara node.
Komponen alur kerja
Dalam aplikasi ini, dua simpul kerja adalah:
- requiresHrResources: menentukan apakah pertanyaan tersebut relevan dengan dokumentasi SDM menggunakan Azure OpenAI LLM.
- getAnswer: mengambil jawabannya. Jawabannya berasal dari rantai LangChain.js retriever, yang menggunakan embedding dokumen dari Azure AI Search dan mengirimkannya ke Azure OpenAI LLM. Ini adalah inti dari generasi berbasis pengambilan.
Batas menentukan awal, akhir, dan kondisi yang diperlukan untuk memanggil simpul getAnswer.
Mengekspor grafik
Untuk menggunakan LangGraph Studio untuk menjalankan dan men-debug graf, ekspor sebagai objek tersendiri.
import { StateGraph } from "@langchain/langgraph";
import { StateAnnotation } from "./langchain/state.js";
import { route as endRoute } from "./langchain/check_route_end.js";
import { getAnswer } from "./azure/get_answer.js";
import { START, ANSWER_NODE, DECISION_NODE } from "./config/nodes.js";
import {
requiresHrResources,
routeRequiresHrResources,
} from "./azure/requires_hr_documents.js";
const builder = new StateGraph(StateAnnotation)
.addNode(DECISION_NODE, requiresHrResources)
.addNode(ANSWER_NODE, getAnswer)
.addEdge(START, DECISION_NODE)
.addConditionalEdges(DECISION_NODE, routeRequiresHrResources)
.addConditionalEdges(ANSWER_NODE, endRoute);
export const hr_documents_answer_graph = builder.compile();
hr_documents_answer_graph.name = "Azure AI Search + Azure OpenAI";
Dalam metode addNode, addEdge, dan addConditionalEdges , parameter pertama adalah nama, sebagai string, untuk mengidentifikasi objek dalam grafik. Parameter kedua adalah fungsi yang harus dipanggil pada langkah tersebut atau nama node yang akan dipanggil.
Untuk metode addEdge , namanya adalah START ("start" yang ditentukan dalam file ./src/config/nodes.ts) dan selalu memanggil DECISION_NODE. Node tersebut didefinisikan dengan dua parameternya: yang pertama adalah namanya, DECISION_NODE, dan yang kedua adalah fungsi yang disebut requiresHrResources.
Fungsionalitas umum
Aplikasi ini menyediakan fungsionalitas LangChain umum:
Manajemen status:
import { BaseMessage, BaseMessageLike } from "@langchain/core/messages"; import { Annotation, messagesStateReducer } from "@langchain/langgraph"; export const StateAnnotation = Annotation.Root({ messages: Annotation<BaseMessage[], BaseMessageLike[]>({ reducer: messagesStateReducer, default: () => [], }), });
Penghentian rute:
import { StateAnnotation } from "./state.js"; import { END, ANSWER_NODE } from "../config/nodes.js"; export const route = ( state: typeof StateAnnotation.State, ): typeof END | typeof ANSWER_NODE => { if (state.messages.length > 0) { return END; } return ANSWER_NODE; };
Satu-satunya rute kustom untuk aplikasi ini adalah routeRequiresHrResources. Rute ini digunakan untuk menentukan apakah jawaban dari node requiresHrResources menunjukkan bahwa pertanyaan pengguna harus berlanjut ke simpul ANSWER_NODE . Karena rute ini menerima output dari requiresHrResources, rute ini berada dalam file yang sama.
Mengintegrasikan sumber daya Azure OpenAI
Integrasi Azure OpenAI menggunakan dua model berbeda:
- Penyematan: Digunakan untuk menyisipkan dokumen ke penyimpanan vektor.
- LLM: Digunakan untuk menjawab pertanyaan dengan mengkueri penyimpanan vektor dan menghasilkan respons.
Klien embedding dan klien LLM memiliki tujuan yang berbeda. Jangan menyederhanakan mereka menjadi satu model atau klien.
Model penyematan
Klien penanaman diperlukan setiap kali dokumen diambil dari penyimpanan vektor. Ini termasuk konfigurasi untuk maxRetries untuk menangani kesalahan sementara.
import { AzureOpenAIEmbeddings } from "@langchain/openai";
import { EMBEDDINGS_CONFIG } from "../config/embeddings.js";
export function getEmbeddingClient(): AzureOpenAIEmbeddings {
return new AzureOpenAIEmbeddings({ ...EMBEDDINGS_CONFIG, maxRetries: 1 });
}
Model LLM
Model LLM digunakan untuk menjawab dua jenis pertanyaan:
- Relevansi dengan SDM: Menentukan apakah pertanyaan pengguna relevan dengan dokumentasi SDM.
- Pembuatan jawaban: Memberikan jawaban atas pertanyaan pengguna, yang dilengkapi dengan dokumen dari Azure AI Search.
Klien LLM dibuat dan dipanggil ketika jawaban diperlukan.
import { RunnableConfig } from "@langchain/core/runnables";
import { StateAnnotation } from "../langchain/state.js";
import { AzureChatOpenAI } from "@langchain/openai";
import { LLM_CONFIG } from "../config/llm.js";
export const getLlmChatClient = (): AzureChatOpenAI => {
return new AzureChatOpenAI({
...LLM_CONFIG,
temperature: 0,
});
};
export const callChatCompletionModel = async (
state: typeof StateAnnotation.State,
_config: RunnableConfig,
): Promise<typeof StateAnnotation.Update> => {
const llm = new AzureChatOpenAI({
...LLM_CONFIG,
temperature: 0,
});
const completion = await llm.invoke(state.messages);
completion;
return {
messages: [
...state.messages,
{
role: "assistant",
content: completion.content,
},
],
};
};
Agen LangChain.js menggunakan LLM untuk memutuskan apakah pertanyaan relevan dengan dokumentasi SDM atau apakah alur kerja harus merutekan ke akhir grafik.
// @ts-nocheck
import { getLlmChatClient } from "./llm.js";
import { StateAnnotation } from "../langchain/state.js";
import { RunnableConfig } from "@langchain/core/runnables";
import { BaseMessage } from "@langchain/core/messages";
import { ANSWER_NODE, END } from "../config/nodes.js";
const PDF_DOCS_REQUIRED = "Answer requires HR PDF docs.";
export async function requiresHrResources(
state: typeof StateAnnotation.State,
_config: RunnableConfig,
): Promise<typeof StateAnnotation.Update> {
const lastUserMessage: BaseMessage = [...state.messages].reverse()[0];
let pdfDocsRequired = false;
if (lastUserMessage && typeof lastUserMessage.content === "string") {
const question = `Does the following question require general company policy information that could be found in HR documents like employee handbooks, benefits overviews, or company-wide policies, then answer yes. Answer no if this requires personal employee-specific information that would require access to an individual's private data, employment records, or personalized benefits details: '${lastUserMessage.content}'. Answer with only "yes" or "no".`;
const llm = getLlmChatClient();
const response = await llm.invoke(question);
const answer = response.content.toLocaleLowerCase().trim();
console.log(`LLM question (is HR PDF documents required): ${question}`);
console.log(`LLM answer (is HR PDF documents required): ${answer}`);
pdfDocsRequired = answer === "yes";
}
// If HR documents (aka vector store) are required, append an assistant message to signal this.
if (!pdfDocsRequired) {
const updatedState = {
messages: [
...state.messages,
{
role: "assistant",
content:
"Not a question for our HR PDF resources. This requires data specific to the asker.",
},
],
};
return updatedState;
} else {
const updatedState = {
messages: [
...state.messages,
{
role: "assistant",
content: `${PDF_DOCS_REQUIRED} You asked: ${lastUserMessage.content}. Let me check.`,
},
],
};
return updatedState;
}
}
export const routeRequiresHrResources = (
state: typeof StateAnnotation.State,
): typeof END | typeof ANSWER_NODE => {
const lastMessage: BaseMessage = [...state.messages].reverse()[0];
if (lastMessage && !lastMessage.content.includes(PDF_DOCS_REQUIRED)) {
console.log("go to end");
return END;
}
console.log("go to llm");
return ANSWER_NODE;
};
Fungsi requiresHrResources menetapkan pesan dengan konten HR resources required detected
dalam status yang diperbarui. Router, routeRequiresHrResources, mencari konten tersebut untuk menentukan tempat mengirim pesan.
Mengintegrasikan sumber daya Azure AI Search untuk penyimpanan vektor
Integrasi Azure AI Search menyediakan dokumen penyimpanan vektor sehingga LLM dapat menambah jawaban untuk simpul getAnswer . LangChain.js lagi menyediakan banyak abstraksi sehingga kode yang diperlukan minimal. Fungsinya adalah:
- getReadOnlyVectorStore: Mengambil klien dengan kata kunci kueri.
- getDocsFromVectorStore: Menemukan dokumen yang relevan dengan pertanyaan pengguna.
import { AzureAISearchVectorStore } from "@langchain/community/vectorstores/azure_aisearch";
import { VECTOR_STORE_QUERY, DOC_COUNT } from "../config/vector_store_query.js";
import { getEmbeddingClient } from "./embeddings.js";
export function getReadOnlyVectorStore(): AzureAISearchVectorStore {
const embeddings = getEmbeddingClient();
return new AzureAISearchVectorStore(embeddings, VECTOR_STORE_QUERY);
}
export async function getDocsFromVectorStore(
query: string,
): Promise<Document[]> {
const store = getReadOnlyVectorStore();
// @ts-ignore
//return store.similaritySearchWithScore(query, DOC_COUNT);
return store.similaritySearch(query, DOC_COUNT);
}
Kode integrasi LangChain.js membuat pengambilan dokumen yang relevan dari toko vektor sangat mudah.
Menulis kode untuk mendapatkan jawaban dari LLM
Sekarang setelah komponen integrasi dibuat, buat fungsi getAnswer untuk mengambil dokumen penyimpanan vektor yang relevan dan menghasilkan jawaban menggunakan LLM.
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { createStuffDocumentsChain } from "langchain/chains/combine_documents";
import { createRetrievalChain } from "langchain/chains/retrieval";
import { getLlmChatClient } from "./llm.js";
import { StateAnnotation } from "../langchain/state.js";
import { AIMessage } from "@langchain/core/messages";
import { getReadOnlyVectorStore } from "./vector_store.js";
const EMPTY_STATE = { messages: [] };
export async function getAnswer(
state: typeof StateAnnotation.State = EMPTY_STATE,
): Promise<typeof StateAnnotation.Update> {
const vectorStore = getReadOnlyVectorStore();
// Extract the last user message's content from the state as input
const lastMessage = state.messages[state.messages.length - 1];
const userInput =
lastMessage && typeof lastMessage.content === "string"
? lastMessage.content
: "";
const questionAnsweringPrompt = ChatPromptTemplate.fromMessages([
[
"system",
"Answer the user's questions based on the below context:\n\n{context}",
],
["human", "{input}"],
]);
const combineDocsChain = await createStuffDocumentsChain({
llm: getLlmChatClient(),
prompt: questionAnsweringPrompt,
});
const retrievalChain = await createRetrievalChain({
retriever: vectorStore.asRetriever(2),
combineDocsChain,
});
const result = await retrievalChain.invoke({ input: userInput });
const assistantMessage = new AIMessage(result.answer);
return {
messages: [...state.messages, assistantMessage],
};
}
Fungsi ini menyediakan prompt dengan dua placeholder: satu untuk pertanyaan pengguna dan satu untuk konteks. Konteksnya adalah semua dokumen yang relevan dari penyimpanan vektor Pencarian AI. Teruskan perintah dan klien LLM ke createStuffDocumentsChain untuk membuat rantai LLM. Teruskan rantai LLM ke createRetrievalChain untuk membuat rantai yang mencakup petunjuk, dokumen relevan, dan LLM.
Jalankan rantai dengan retrievalChain.invoke dan pertanyaan pengguna sebagai input untuk mendapatkan jawabannya. Kembalikan jawaban dalam status pesan.
Membangun paket agen
Tambahkan skrip ke package.json untuk membangun aplikasi TypeScript:
"build": "tsc",
Bangun agen LangChain.js.
npm run build
Opsional - jalankan agen LangChain.js dalam pengembangan lokal dengan LangChain Studio
Secara opsional, untuk pengembangan lokal, gunakan LangChain Studio untuk bekerja dengan agen LangChain.js Anda.
Buat
langgraph.json
file untuk menentukan grafik.{ "dependencies": [], "graphs": { "agent": "./src/graph.ts:hr_documents_answer_graph" }, "env": "../.env" }
Instal CLI LangGraph.
npm install @langchain/langgraph-cli --save-dev
Buat skrip di package.json untuk meneruskan
.env
file ke LangGraph CLI."studio": "npx @langchain/langgraph-cli dev",
CLI berjalan di terminal Anda dan membuka browser ke LangGraph Studio.
Welcome to ╦ ┌─┐┌┐┌┌─┐╔═╗┬─┐┌─┐┌─┐┬ ┬ ║ ├─┤││││ ┬║ ╦├┬┘├─┤├─┘├─┤ ╩═╝┴ ┴┘└┘└─┘╚═╝┴└─┴ ┴┴ ┴ ┴.js - 🚀 API: http://localhost:2024 - 🎨 Studio UI: https://smith.langchain.com/studio?baseUrl=http://localhost:2024 This in-memory server is designed for development and testing. For production use, please use LangGraph Cloud. info: ▪ Starting server... info: ▪ Initializing storage... info: ▪ Registering graphs from C:\Users\myusername\azure-typescript-langchainjs\packages\langgraph-agent info: ┏ Registering graph with id 'agent' info: ┗ [1] { graph_id: 'agent' } info: ▪ Starting 10 workers info: ▪ Server running at ::1:2024
Lihat agen LangChain.js di LangGraph Studio.
Pilih + Pesan untuk menambahkan pertanyaan pengguna lalu pilih Kirim.
Pertanyaan Relevansi dengan dokumen SDM Does the NorthWind Health plus plan cover eye exams?
Pertanyaan ini relevan dengan SDM dan cukup umum sehingga dokumen SDM seperti buku pegangan karyawan, buku pegangan manfaat, dan pustaka peran karyawan harus dapat menjawabnya. What is included in the NorthWind Health plus plan that is not included in the standard?
Pertanyaan ini relevan dengan SDM dan cukup umum sehingga dokumen SDM seperti buku pegangan karyawan, buku pegangan manfaat, dan pustaka peran karyawan harus dapat menjawabnya. How much of my perks + benefit have I spent
Pertanyaan ini tidak relevan dengan dokumen SDM umum dan impersonal. Pertanyaan ini harus dikirim ke agen yang memiliki akses ke data karyawan. Jika pertanyaan relevan dengan dokumen SDM, itu harus melewati DECISION_NODE dan seterusnya ke ANSWER_NODE.
Amati keluaran terminal untuk melihat pertanyaan kepada LLM dan jawabannya dari LLM.
Jika pertanyaan tidak relevan dengan dokumen SDM, alur akan langsung berakhir.
Ketika agen LangChain.js membuat keputusan yang salah, masalahnya mungkin:
- Model LLM yang digunakan
- Jumlah dokumen dari penyimpanan vektor
- Perintah yang digunakan dalam simpul keputusan.
Menjalankan agen LangChain.js dari aplikasi
Untuk memanggil agen LangChain.js dari aplikasi induk, seperti API web, Anda perlu memberikan pemanggilan agen LangChain.js.
import { HumanMessage } from "@langchain/core/messages";
import { hr_documents_answer_graph as app } from "./graph.js";
const AIMESSAGE = "aimessage";
export async function ask_agent(question: string) {
const initialState = { messages: [new HumanMessage(question)], iteration: 0 };
const finalState = await app.invoke(initialState);
return finalState;
}
export async function get_answer(question: string) {
try {
const answerResponse = await ask_agent(question);
const answer = answerResponse.messages
.filter(
(m: any) =>
m &&
m.constructor?.name?.toLowerCase() === AIMESSAGE.toLocaleLowerCase(),
)
.map((m: any) => m.content)
.join("\n");
return answer;
} catch (e) {
console.error("Error in get_answer:", e);
throw e;
}
}
Dua fungsi tersebut adalah:
- ask_agent: Fungsi ini mengembalikan status sehingga memungkinkan Anda menambahkan agen LangChain.js ke alur kerja multi-agen LangChain.
- get_answer: Fungsi ini hanya mengembalikan teks jawaban. Fungsi ini dapat dipanggil dari API.
Penyelesaian Masalah
- Untuk masalah apa pun dengan prosedur, buat masalah pada repositori kode sampel
Membersihkan sumber daya
Hapus grup sumber daya yang menyimpan sumber daya Azure AI Search dan sumber daya Azure OpenAI.