Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa esercitazione si userà LangChain.js per creare un agente LangChain.js che consenta ai dipendenti dell'azienda NorthWind di porre domande correlate alle risorse umane. Usando il framework, si evita il codice boilerplate in genere necessario per gli agenti LangChain.js e l'integrazione dei servizi di Azure, consentendo di concentrarsi sulle esigenze aziendali.
In questa esercitazione, farai:
- Configurare un agente LangChain.js
- Integrare le risorse di Azure nell'agente di LangChain.js
- È possibile testare facoltativamente il vostro agente LangChain.js in LangSmith Studio.
NorthWind si basa su due origini dati: la documentazione delle risorse umane pubbliche accessibile a tutti i dipendenti e un database hr riservato contenente dati sensibili dei dipendenti. Questa esercitazione è incentrata sulla creazione di un agente LangChain.js che determina se è possibile rispondere alla domanda di un dipendente usando i documenti delle risorse umane pubbliche. In tal caso, l'agente LangChain.js fornisce direttamente la risposta.
Avvertimento
Questo articolo usa le chiavi per accedere alle risorse. In un ambiente di produzione, la miglior prassi consigliata consiste nell'usare Azure RBAC e identità gestita. Questo approccio elimina la necessità di gestire o ruotare le chiavi, migliorando la sicurezza e semplificando il controllo di accesso.
Prerequisiti
- Un account Azure attivo. Crea gratuitamente un account se non ne hai uno.
- Node.js LTS installato nel sistema.
- TypeScript per la scrittura e la compilazione di codice TypeScript.
- LangChain.js libreria per la creazione dell'agente.
- Facoltativo: LangSmith per il monitoraggio dell'utilizzo dell'intelligenza artificiale. Sono necessari il nome, la chiave e l'endpoint del progetto.
- Facoltativo: LangGraph Studio per il debug delle catene LangGraph e degli agenti LangChain.js.
- Risorsa di Ricerca intelligenza artificiale di Azure: assicurarsi di avere l'endpoint della risorsa, la chiave di amministrazione (per l'inserimento di documenti), la chiave di query (per la lettura dei documenti) e il nome dell'indice.
-
Risorsa OpenAI di Azure: sono necessari il nome dell'istanza della risorsa, la chiave e due modelli con le relative versioni dell'API:
- Modello di incorporamento come
text-embedding-ada-002. - Modello linguistico di grandi dimensioni, ad esempio
gpt-4o.
- Modello di incorporamento come
Architettura dell'agente
Il framework LangChain.js fornisce un flusso decisionale per la creazione di agenti intelligenti come LangGraph. In questa esercitazione viene creato un agente LangChain.js che si integra con Ricerca di intelligenza artificiale di Azure e Azure OpenAI per rispondere alle domande correlate alle risorse umane. L'architettura dell'agente è progettata per:
- Determinare se una domanda è rilevante per la documentazione delle risorse umane.
- Recuperare i documenti pertinenti da Ricerca di intelligenza artificiale di Azure.
- Usare Azure OpenAI per generare una risposta in base ai documenti recuperati e al modello LLM.
Componenti chiave:
Struttura del grafo: l'agente LangChain.js è rappresentato come grafico, dove:
- I nodi eseguono attività specifiche, ad esempio il processo decisionale o il recupero dei dati.
- Gli archi definiscono il flusso tra i nodi, determinando la sequenza di operazioni.
Integrazione di Ricerca AI di Azure:
- Inserisce i documenti HR nell'archivio vettoriale come incorporamenti.
- Usa un modello di incorporamento (
text-embedding-ada-002) per creare questi incorporamenti. - Recupera i documenti pertinenti in base alla richiesta dell'utente.
Integrazione di Azure OpenAI:
- Usa un modello linguistico di grandi dimensioni (
gpt-4o) per:- Determina se una domanda è rispondebile da documenti hr generali.
- Genera una risposta con prompt usando il contesto dei documenti e delle domande dell'utente.
- Usa un modello linguistico di grandi dimensioni (
La tabella seguente contiene esempi di domande utente che sono e non sono pertinenti e rispondebili dai documenti generali risorse umane:
| Domanda | Pertinenza dei documenti delle Risorse Umane |
|---|---|
Does the NorthWind Health Plus plan cover eye exams? |
Rilevante. I documenti delle risorse umane, ad esempio il manuale dei dipendenti, devono fornire una risposta. |
How much of my perks + benefits have I spent? |
Non rilevante. Questa domanda richiede l'accesso ai dati dei dipendenti riservati, che non rientrano nell'ambito di questo agente. |
Usando il framework, si evita il codice boilerplate in genere necessario per gli agenti LangChain.js e l'integrazione dei servizi di Azure, consentendo di concentrarsi sulle esigenze aziendali.
Inizializzare il progetto Node.js
In una nuova directory inizializzare il progetto Node.js per l'agente TypeScript. Eseguire i comandi seguenti:
npm init -y
npm pkg set type=module
npx tsc --init
Creare un file di ambiente
Creare un .env file per lo sviluppo locale per archiviare le variabili di ambiente per le risorse di Azure e LangGraph. Assicuratevi che il nome dell'istanza della risorsa per l'embedding e il LLM sia solo il nome della risorsa, non l'endpoint.
Facoltativo: se si usa LangSmith, impostare `LANGSMITH_TRACING` su `true` per lo sviluppo locale. Disabilitarlo (false) o rimuoverlo nell'ambiente di produzione.
Installa le dipendenze
Installare le dipendenze di Azure per Ricerca AI di Azure:
npm install @azure/search-documentsInstallare LangChain.js dipendenze per la creazione e l'uso di un agente:
npm install @langchain/community @langchain/core @langchain/langgraph @langchain/openai langchainInstallare le dipendenze di sviluppo per lo sviluppo locale:
npm install --save-dev dotenv
Creare file di configurazione delle risorse di ricerca di Intelligenza artificiale di Azure
Per gestire le varie risorse e i modelli di Azure usati in questa esercitazione, creare file di configurazione specifici per ogni risorsa. Questo approccio garantisce chiarezza e separazione delle preoccupazioni, semplificando la gestione e la manutenzione delle configurazioni.
Configurazione per caricare documenti nell'archivio vettoriale
Il file di configurazione di Ricerca intelligenza artificiale di Azure usa la chiave di amministrazione per inserire documenti nell'archivio vettoriale. Questa chiave è essenziale per gestire l'inserimento di dati in Ricerca di intelligenza artificiale di Azure.
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 astrae la necessità di definire uno schema per l'inserimento di dati in Ricerca di intelligenza artificiale di Azure, fornendo uno schema predefinito adatto per la maggior parte degli scenari. Questa astrazione semplifica il processo e riduce la necessità di definizioni di schemi personalizzate.
Configurazione per interrogare l'archivio vettoriale
Per eseguire query sull'archivio vettoriale, creare un file di configurazione separato:
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,
},
};
Quando esegui una query sull'archivio vettoriale, invece utilizza la chiave di query. Questa separazione delle chiavi garantisce l'accesso sicuro ed efficiente alla risorsa.
Creare file di configurazione delle risorse OpenAI di Azure
Per gestire i due diversi modelli, incorporamenti e LLM, creare file di configurazione separati. Questo approccio garantisce chiarezza e separazione delle preoccupazioni, semplificando la gestione e la manutenzione delle configurazioni.
Configurazione per incorporamenti per l'archivio vettoriale
Per creare incorporamenti per l'inserimento di documenti nell'archivio vettoriale di Ricerca intelligenza artificiale di Azure, creare un file di configurazione:
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,
};
Configurazione per LLM per generare risposte
Per creare risposte dal modello linguistico di grandi dimensioni, creare un file di configurazione:
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,
};
Costanti e suggerimenti
Le applicazioni di intelligenza artificiale spesso si basano su stringhe e prompt costanti. Gestire queste costanti con file separati.
Creare il prompt di sistema:
export const SYSTEM_PROMPT = `Answer the query with a complete paragraph based on the following context:`;
Creare le costanti dei nodi:
export const ANSWER_NODE = "vector_store_retrieval";
export const DECISION_NODE = "requires_hr_documents";
export const START = "__start__";
export const END = "__end__";
Esempi di query degli utenti
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?",
];
Caricare documenti in Ricerca di intelligenza artificiale di Azure
Per caricare documenti in Ricerca di intelligenza artificiale di Azure, usare LangChain.js per semplificare il processo. I documenti, archiviati come PDF, vengono convertiti in incorporamenti e inseriti nell'archivio vettoriale. Questo processo garantisce che i documenti siano pronti per il recupero efficiente e l'esecuzione di query.
Considerazioni sulle chiavi:
- LangChain.js astrazione: LangChain.js gestisce gran parte della complessità, ad esempio le definizioni dello schema e la creazione del client, rendendo il processo semplice.
- Limitazione e logica di ripetizione dei tentativi: mentre il codice di esempio include una funzione di attesa minima, le applicazioni di produzione devono implementare una logica completa per la gestione degli errori e la logica di ripetizione dei tentativi per gestire le limitazioni e gli errori temporanei.
Passaggi per caricare i documenti
Individuare i documenti PDF: i documenti vengono memorizzati nella cartella dati.
Caricare pdf in LangChain.js: usare la
loadPdfsFromDirectoryfunzione per caricare i documenti. Questa funzione utilizza il metodoPDFLoader.loaddella community LangChain.js per leggere ogni file e restituire una matriceDocument[]. Questo array è un formato documento standard LangChain.js.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); } }Inserire documenti in Ricerca di intelligenza artificiale di Azure: usare la
loadDocsIntoAiSearchVectorfunzione per inviare la matrice di documenti all'archivio vettoriale di Ricerca intelligenza artificiale di Azure. Questa funzione usa il client embeddings per elaborare i documenti e include una funzione di attesa di base per gestire la limitazione delle richieste. Per la produzione, implementare un meccanismo di retry/rinuncia affidabile.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; }
Creare il flusso di lavoro dell'agente
In LangChain.js, costruisci l'agente LangChain.js con un LangGraph. LangGraph consente di definire i nodi e i bordi:
- Nodo: dove viene eseguito il lavoro.
- Edge: definisce la connessione tra i nodi.
Componenti del flusso di lavoro
In questa applicazione i due nodi di lavoro sono:
- requiresHrResources: determina se la domanda è rilevante per la documentazione hr usando Azure OpenAI LLM.
- getAnswer: recupera la risposta. La risposta proviene da una catena di recupero LangChain.js, che utilizza gli embedding dei documenti dalla ricerca tramite intelligenza artificiale di Azure e li invia all'LLM di OpenAI di Azure. Questa è l'essenza della generazione arricchita dal recupero.
I bordi definiscono dove iniziare, terminare e la condizione necessaria per chiamare il nodo getAnswer .
Esportazione del grafico
Per usare LangGraph Studio per eseguire e fare il debug del grafo, esportarlo come proprio oggetto.
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";
Nei metodi addNode, addEdge e addConditionalEdges il primo parametro è un nome, come stringa, per identificare l'oggetto all'interno del grafico. Il secondo parametro è la funzione che deve essere chiamata in quel passaggio o il nome del nodo da chiamare.
Per il metodo addEdge , il nome è START ("start" definito nel file ./src/config/nodes.ts) e chiama sempre il DECISION_NODE. Tale nodo viene definito con i due parametri: il primo è il nome, DECISION_NODE e il secondo è la funzione denominata requiresHrResources.
Funzionalità comuni
Questa app offre funzionalità langchain comuni:
Gestione dello stato:
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: () => [], }), });Terminazione della route:
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; };
L'unica route personalizzata per questa applicazione è routeRequiresHrResources. Questa route viene usata per determinare se la risposta del nodo requiresHrResources indica che la domanda dell'utente deve continuare fino al nodo ANSWER_NODE . Poiché questa route riceve l'output di requiresHrResources, si trova nello stesso file.
Integrare le risorse OpenAI di Azure
L'integrazione di Azure OpenAI usa due modelli diversi:
- Incorporamenti: consente di inserire i documenti nell'archivio vettoriale.
- LLM: usato per rispondere alle domande eseguendo una query sull'archivio vettoriale e generando risposte.
Il client di incorporamento e il client LLM servono scopi diversi. Non ridurle a un singolo modello o client.
Modello di incorporamento
Il client di incorporamento è necessario ogni volta che i documenti vengono recuperati dall'archivio vettoriale. Include una configurazione per maxRetries per gestire gli errori temporanei.
import { AzureOpenAIEmbeddings } from "@langchain/openai";
import { EMBEDDINGS_CONFIG } from "../config/embeddings.js";
export function getEmbeddingClient(): AzureOpenAIEmbeddings {
return new AzureOpenAIEmbeddings({ ...EMBEDDINGS_CONFIG, maxRetries: 1 });
}
Modello LLM
Il modello LLM viene usato per rispondere a due tipi di domande:
- Pertinenza delle risorse umane: determina se la domanda dell'utente è rilevante per la documentazione delle risorse umane.
- Generazione di risposte: fornisce una risposta alla domanda dell'utente, aumentata con i documenti di Ricerca di intelligenza artificiale di Azure.
Il client LLM viene creato e richiamato quando è necessaria una risposta.
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,
},
],
};
};
L'agente LangChain.js usa l'LLM per decidere se la domanda è rilevante per la documentazione delle risorse umane o se il flusso di lavoro deve instradarsi alla fine del grafico.
// @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;
};
La funzione requiresHrResources imposta un messaggio nello stato aggiornato con HR resources required detected contenuto. Il router , routeRequiresHrResources, cerca il contenuto per determinare dove inviare i messaggi.
Integrare la risorsa ricerca di intelligenza artificiale di Azure per l'archivio vettoriale
L'integrazione di Ricerca Intelligenza Artificiale di Azure fornisce i documenti dell'archivio vettoriale affinché l'LLM possa migliorare la risposta per il nodo getAnswer. LangChain.js fornisce di nuovo gran parte dell'astrazione in modo che il codice richiesto sia minimo. Le funzioni sono:
- getReadOnlyVectorStore: recupera il client con la chiave di query.
- getDocsFromVectorStore: trova i documenti pertinenti alla domanda dell'utente.
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);
}
Il codice di integrazione LangChain.js rende incredibilmente semplice il recupero dei documenti pertinenti dall'archivio vettoriale.
Scrivere codice per ottenere una risposta da LLM
Ora che i componenti di integrazione vengono compilati, creare la funzione getAnswer per recuperare i documenti dell'archivio vettoriale pertinenti e generare una risposta usando 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],
};
}
Questa funzione fornisce un prompt con due segnaposto: uno per la domanda dell'utente e uno per il contesto. Il contesto comprende tutti i documenti pertinenti dall'archivio vettoriale di ricerca dell'IA. Passa il prompt e il client LLM al createStuffDocumentsChain per creare una catena LLM. Utilizzare la catena LLM con creareRetrievalChain per creare una catena che include il prompt, i documenti pertinenti e l'LLM.
Avviare i processi con retrievalChain.invoke e la domanda dell'utente come input per ricevere una risposta. Restituire la risposta nello stato dei messaggi.
Compilare il pacchetto dell'agente
Aggiungere uno script a package.json per compilare l'applicazione TypeScript:
"build": "tsc",Creare l'agente LangChain.js.
npm run build
Facoltativo: eseguire l'agente LangChain.js nello sviluppo locale con LangChain Studio
Facoltativamente, per lo sviluppo locale, usare LangChain Studio per lavorare con l'agente LangChain.js.
Creare un
langgraph.jsonfile per definire il grafico.{ "dependencies": [], "graphs": { "agent": "./src/graph.ts:hr_documents_answer_graph" }, "env": "../.env" }Installa il LangGraph CLI.
npm install @langchain/langgraph-cli --save-devCreare uno script in package.json per passare il
.envfile all'interfaccia della riga di comando di LangGraph."studio": "npx @langchain/langgraph-cli dev",L'interfaccia della riga di comando viene eseguita nel terminale e apre un browser su 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:2024Visualizza l'agente LangChain.js in LangGraph Studio.
Selezionare + Messaggio per aggiungere una domanda utente e quindi selezionare Invia.
Domanda Rilevanza per i documenti HR Does the NorthWind Health plus plan cover eye exams?Questa domanda è rilevante per le risorse umane e sufficientemente generale che i documenti delle risorse umane, ad esempio il manuale dei dipendenti, il manuale dei benefici e la libreria dei ruoli dei dipendenti dovrebbero essere in grado di rispondere. What is included in the NorthWind Health plus plan that is not included in the standard?Questa domanda è rilevante per le risorse umane e sufficientemente generale che i documenti delle risorse umane, ad esempio il manuale dei dipendenti, il manuale dei benefici e la libreria dei ruoli dei dipendenti dovrebbero essere in grado di rispondere. How much of my perks + benefit have I spentQuesta domanda non è rilevante per i documenti hr generali e impersonali. Questa domanda deve essere inviata a un agente che ha accesso ai dati dei dipendenti. Se la domanda è rilevante per la documentazione delle risorse umane, deve passare attraverso il DECISION_NODE e il ANSWER_NODE.
Guardare l'output del terminale per vedere la domanda all'LLM e la risposta dall'LLM.
Se la domanda non è rilevante per la documentazione delle Risorse Umane, il flusso passa direttamente alla fine.
Quando l'agente LangChain.js prende una decisione errata, il problema potrebbe essere:
- Modello LLM usato
- Numero di documenti dall'archivio vettoriale
- Richiesta usata nel nodo decisionale.
Eseguire l'agente LangChain.js da un'app
Per chiamare l'agente LangChain.js da un'applicazione padre, ad esempio un'API Web, è necessario fornire la chiamata dell'agente 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;
}
}
Le due funzioni sono:
- ask_agent: questa funzione restituisce lo stato in modo da consentire di aggiungere l'agente LangChain.js a un flusso di lavoro multi-agente LangChain.
- get_answer: questa funzione restituisce solo il testo della risposta. Questa funzione può essere chiamata da un'API.
Risoluzione dei problemi
- Per eventuali problemi con la procedura, segnalare un problema nel repository di codice di esempio
Pulire le risorse
Eliminare il gruppo di risorse che contiene la risorsa ricerca di intelligenza artificiale di Azure e la risorsa OpenAI di Azure.