Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Intelligens HR-asszisztens létrehozása LangChain.js és Azure-szolgáltatások használatával. Ez az ügynök segít az alkalmazottaknak a fiktív NorthWind-vállalatnál, hogy választ találjanak az emberi erőforrásokra vonatkozó kérdésekre a vállalati dokumentációban való kereséssel.
Az Azure AI Search használatával megkeresheti a releváns dokumentumokat, az Azure OpenAI pedig pontos válaszokat hozhat létre. A LangChain.js keretrendszer kezeli az ügynökök vezénylésének összetettségét, így a konkrét üzleti követelményekre összpontosíthat.
Ismertetett témák:
- Azure-erőforrások üzembe helyezése az Azure Developer CLI használatával
- Azure-szolgáltatásokkal integrálható LangChain.js ügynök létrehozása
- Lekérés-kiterjesztett generáció (RAG) megvalósítása dokumentumkereséshez
- Az ügynök tesztelése és hibakeresése helyileg és az Azure-ban
Az oktatóanyag végére egy működő REST API-val rendelkezik, amely a vállalat dokumentációjával válaszol a HR-kérdésekre.
Az architektúra áttekintése
A NorthWind két adatforrásra támaszkodik:
- A HR dokumentációja minden alkalmazott számára elérhető
- Bizalmas alkalmazotti adatokat tartalmazó HR-adatbázis.
Ez az oktatóanyag egy LangChain.js ügynök létrehozására összpontosít, amely meghatározza, hogy egy alkalmazott kérdése megválaszolható-e a nyilvános HR-dokumentumok használatával. Ha igen, a LangChain.js ügynök közvetlenül adja meg a választ.
Előfeltételek
Ha ezt a mintát a Codespace-ben vagy a helyi fejlesztési tárolóban szeretné használni, beleértve a LangChain.js-ügynök felépítését és futtatását, a következőkre van szüksége:
- Aktív Azure-fiók. Ha nincs fiókja, hozzon létre ingyenes fiókot .
Ha a mintakódot helyileg futtatja fejlesztési tároló nélkül, a következőkre is szüksége van:
- Telepítve van a rendszerén a Node.js LTS.
- TypeScript TypeScript-kód írásához és fordításához.
- Az Azure Developer CLI (azd) telepítve és konfigurálva van.
- LangChain.js könyvtár az ügynök felépítéséhez.
- Nem kötelező: LangSmith az AI-használat monitorozásához. Szüksége van a projekt nevére, kulcsára és végpontjára.
- Nem kötelező: LangGraph Studio a LangGraph-láncok és LangChain.js ügynökök hibakereséséhez.
Azure-erőforrások
A következő Azure-erőforrásokra van szükség. Ezeket ebben a cikkben az Azure Developer CLI - és Bicep-sablonok használatával hoztuk létre az Azure Verified Modules (AVM) használatával. Az erőforrások jelszó nélküli és kulcs nélküli hozzáféréssel is jönnek létre tanulási célokra. Ez az oktatóanyag a helyi fejlesztői fiókot használja jelszó nélküli hitelesítéshez:
- Felügyelt identitás az Azure-szolgáltatások jelszó nélküli hitelesítéséhez.
- Az Azure Container Registry a Node.js Fastify API-kiszolgáló Docker-lemezképének tárolásához.
- Azure Container App a Node.js Fastify API-kiszolgáló üzemeltetéséhez.
- Azure AI Search-erőforrás vektorkereséshez.
-
Azure OpenAI-erőforrás a következő modellekkel:
- Egy beágyazási modell, például
text-embedding-3-small. - Egy nagy nyelvi modell (LLM), például
'gpt-4.1-mini.
- Egy beágyazási modell, például
Ügynökarchitektúra
A LangChain.js keretrendszer döntési folyamatot biztosít az intelligens ügynökök LangGraphként való létrehozásához. Ebben az oktatóanyagban egy LangChain.js ügynököt hoz létre, amely integrálható az Azure AI Search és az Azure OpenAI szolgáltatással a HR-sel kapcsolatos kérdések megválaszolásához. Az ügynök architektúrája a következőkre lett tervezve:
- Állapítsa meg, hogy egy kérdés az összes alkalmazott számára elérhető általános HR-dokumentáció szempontjából releváns-e.
- A felhasználói lekérdezés alapján lekérheti a releváns dokumentumokat az Azure AI Searchből.
- Az Azure OpenAI használatával választ hozhat létre a lekért dokumentumok és az LLM-modell alapján.
Fő összetevők:
Gráfstruktúra: A LangChain.js ügynök gráfként jelenik meg, ahol:
- A csomópontok konkrét feladatokat hajtanak végre, például döntéshozatalt vagy adatok beolvasását.
- Az élek határozzák meg a csomópontok közötti folyamatot, meghatározva a műveletek sorrendjét.
Azure AI Search-integráció:
- Beágyazási modellt használ vektorok létrehozásához.
- HR-dokumentumokat (*.md, *.pdf) szúr be a vektortárolóba. A dokumentumok a következők:
- Céges információk
- Alkalmazotti kézikönyv
- Előnyök kézikönyv
- Alkalmazotti szerepkör-kódtár
- A felhasználói kérés alapján lekéri a releváns dokumentumokat.
-
Azure OpenAI-integráció:
- Nagy nyelvi modellt használ a következő célokra:
- Meghatározza, hogy egy kérdés megválaszolható-e személytelen HR-dokumentumokból.
- A dokumentumokból és a felhasználói kérdésekből származó környezet használatával válasz generál.
- Nagy nyelvi modellt használ a következő célokra:
Az alábbi táblázat olyan felhasználói kérdésekre mutat be példákat, amelyek általános emberierőforrás-dokumentumokból nem relevánsak és megválaszolhatók:
| Kérdés | Releváns | Explanation |
|---|---|---|
Does the NorthWind Health Plus plan cover eye exams? |
Igen | A HR-dokumentumoknak, például az alkalmazotti kézikönyvnek választ kell adniuk. |
How much of my perks + benefits have I spent? |
Nem | Ehhez a kérdéshez hozzá kell férni a bizalmas alkalmazottak adataihoz, amelyek nem tartoznak az ügynök hatókörébe. |
A LangChain.js keretrendszer használatával elkerülheti az ügynökökhöz és az Azure-szolgáltatások integrációjához általában szükséges ügynöki sablonkód nagy részét, így az üzleti igényekre összpontosíthat.
A mintakódtár klónozása
Egy új könyvtárban klónozza a mintakódtárat, és váltson az új könyvtárra:
git clone https://github.com/Azure-Samples/azure-typescript-langchainjs.git
cd azure-typescript-langchainjs
Ez a minta tartalmazza a biztonságos Azure-erőforrások létrehozásához, a LangChain.js-ügynök Azure AI Search és Az Azure OpenAI használatával való létrehozásához szükséges kódot, valamint az ügynök használatát egy Node.js Fastify API-kiszolgálóról.
Hitelesítés az Azure CLI-ben és az Azure Developer CLI-ben
Jelentkezzen be az Azure-ba az Azure Developer CLI-vel, hozza létre az Azure-erőforrásokat, és telepítse a forráskódot. Mivel az üzembe helyezési folyamat az Azure CLI-t és az Azure Developer CLI-t is használja, jelentkezzen be az Azure CLI-be, majd konfigurálja az Azure Developer CLI-t az Azure CLI-ből származó hitelesítés használatára:
az login
azd config set auth.useAzCliAuth true
Erőforrások létrehozása és kód üzembe helyezése az Azure Developer CLI-vel
A parancs futtatásával kezdje el az üzembe helyezési azd up folyamatot:
azd up
azd up A parancs során válaszoljon a következő kérdésekre:
-
Új környezetnév: adjon meg egy egyedi környezetnevet, például
langchain-agent. Ez a környezetnév az Azure-erőforráscsoport részeként használatos. - Válasszon ki egy Azure-előfizetést: válassza ki azt az előfizetést, amelyben az erőforrások létre lettek hozva.
-
Válasszon ki egy régiót: például
eastus2.
Az üzembe helyezés körülbelül 10–15 percet vesz igénybe. Az Azure Developer CLI a fájlban meghatározott fázisok és horgok használatával vezényli a azure.yaml folyamatot:
Kiépítési fázis (a következőnek felel meg azd provision):
- A következőben definiált
infra/main.bicepAzure-erőforrásokat hozza létre:- Azure Container App
- OpenAI
- AI-keresés
- Tárolóregisztrációs adatbázis
- Felügyelt identitás
-
Kiépítés utáni horog: Ellenőrzi, hogy az Azure AI Search-index
northwindmár létezik-e- Ha az index nem létezik: futtatja
npm installésnpm run load_datafeltölti a HR-dokumentumokat LangChain.js PDF-betöltő és beágyazó ügyfél használatával - Ha az index létezik: kihagyja az adatbetöltést az ismétlődések elkerülése érdekében (manuálisan újra betölthető az index törlésével vagy futtatásával
npm run load_data) Üzembe helyezési fázis (egyenértékű a következővelazd deploy):
- Ha az index nem létezik: futtatja
- A hook előzetes üzembe helyezése: Létrehozza a Docker-rendszerképet a Fastify API-kiszolgálóhoz, és leküldi az Azure Container Registrybe
- A tárolóalapú API-kiszolgáló üzembe helyezése az Azure Container Appsben
Az üzembe helyezés befejezésekor a környezeti változók és az erőforrás-információk az .env adattár gyökérkönyvtárában lévő fájlba lesznek mentve. Az erőforrásokat az Azure Portalon tekintheti meg.
Az erőforrások jelszó nélküli és kulcs nélküli hozzáféréssel is jönnek létre tanulási célokra. Ez a bevezető oktatóanyag a helyi fejlesztői fiókot használja jelszó nélküli hitelesítéshez. Éles alkalmazások esetén csak jelszó nélküli hitelesítést használjon felügyelt identitásokkal. További információ a jelszó nélküli hitelesítésről.
A mintakód helyi használata
Az Azure-erőforrások létrehozása után helyileg futtathatja a LangChain.js ügynököt.
Függőségek telepítése
Telepítse a projekthez tartozó Node.js csomagokat.
npm installEz a parancs telepíti a könyvtár két
package.jsonfájljában definiált függőségeket, többek között apackages-v1következőket:-
./packages-v1/server-api:- Fastify a webkiszolgálóhoz
-
./packages-v1/langgraph-agent:- LangChain.js az ügynök létrehozásához
- Azure SDK-ügyfélkódtár
@azure/search-documentsaz Azure AI Search-erőforrással való integrációhoz. A referenciadokumentáció itt található.
-
Hozza létre a két csomagot: az API-kiszolgálót és az AI-ügynököt.
npm run buildEz a parancs kapcsolatot hoz létre a két csomag között, hogy az API-kiszolgáló meghívhassa az AI-ügynököt.
Az API-kiszolgáló helyi futtatása
Az Azure Developer CLI létrehozta a szükséges Azure-erőforrásokat, és konfigurálta a környezeti változókat a gyökérfájlban .env . Ez a konfiguráció tartalmazott egy telepítés utáni kiváltó pontot, amely feltölti az adatokat a vektortárolóba. Most futtathatja az LangChain.js-ügynököt üzemeltető Fastify API-kiszolgálót. Indítsa el a Fastify API-kiszolgálót.
npm run dev
A kiszolgáló a 3000-s porton indul el és figyel. A kiszolgálót a böngészőben a [http://localhost:3000] elemre lépve tesztelheti. Egy üdvözlő üzenetnek kell megjelennie, amely jelzi, hogy a kiszolgáló fut.
Kérdések feltevése az API-val
Használhat olyan eszközt, mint a REST-ügyfél , vagy curl post kérést küldhet a /ask végpontnak a kérdést tartalmazó JSON-törzstel.
REST ügyfél-lekérdezések a packages-v1/server-api/http címtárban érhetők el.
Példa a curl használatára:
curl -X POST http://localhost:3000/answer -H "Content-Type: application/json" -d "{\"question\": \"Does the NorthWind Health Plus plan cover eye exams?\"}"
JSON-választ kell kapnia a LangChain.js ügynök válaszával.
{
"answer": "Yes, the NorthWind Health Plus plan covers eye exams. According to the Employee Handbook, employees enrolled in the Health Plus plan are eligible for annual eye exams as part of their vision benefits."
}
A címtárban packages-v1/server-api/http számos példakérdés érhető el. Nyissa meg a fájlokat a Visual Studio CodeREST Client segítségével, hogy gyorsan tesztelje őket.
Az alkalmazáskód ismertetése
Ez a szakasz bemutatja, hogyan integrálható az LangChain.js-ügynök az Azure-szolgáltatásokkal. Az adattár alkalmazása npm-munkaterületként van rendszerezve, két fő csomaggal:
Project Root
│
├── packages-v1/
│ │
│ ├── langgraph-agent/ # Core LangGraph agent implementation
│ │ ├── src/
│ │ │ ├── azure/ # Azure service integrations
│ │ │ │ ├── azure-credential.ts # Centralized auth with DefaultAzureCredential
│ │ │ │ ├── embeddings.ts # Azure OpenAI embeddings + PDF loading + rate limiting
│ │ │ │ ├── llm.ts # Azure OpenAI chat completion (key-based & passwordless)
│ │ │ │ └── vector_store.ts # Azure AI Search vector store + indexing + similarity search
│ │ │ │
│ │ │ ├── langchain/ # LangChain agent logic
│ │ │ │ ├── node_get_answer.ts # RAG: retrieves docs + generates answers
│ │ │ │ ├── node_requires_hr_documents.ts # Determines if HR docs needed
│ │ │ │ ├── nodes.ts # LangGraph node definitions + state management
│ │ │ │ └── prompt.ts # System prompts + conversation templates
│ │ │ │
│ │ │ └── scripts/ # Utility scripts
│ │ │ └── load_vector_store.ts # Uploads PDFs to Azure AI Search
│ │ │
│ │ └── data/ # Source documents (PDFs) for vector store
│ │
│ └── server-api/ # Fastify REST API server
│ └── src/
│ └── server.ts # HTTP server with /answer endpoint
│
├── infra/ # Infrastructure as Code
│ └── main.bicep # Azure resources: Container Apps, OpenAI, AI Search, ACR, managed identity
│
├── azure.yaml # Azure Developer CLI config + deployment hooks
├── Dockerfile # Multi-stage Docker build for containerized deployment
└── package.json # Workspace configuration + build scripts
Főbb architekturális döntések:
- Monorepo struktúra: az npm-munkaterületek lehetővé teszik a megosztott függőségeket és a csatolt csomagokat
-
Az aggodalmak elkülönítése: Az ügynöklogika (
langgraph-agent) független az API-kiszolgálótól (server-api) -
Központosított hitelesítés: A kulcsalapú és a jelszó nélküli hitelesítést és az Azure-szolgáltatásintegrációt egyaránt kezelő fájlok
./langgraph-agent/src/azure
Hitelesítés az Azure Servicesben
Az alkalmazás a környezeti változó által SET_PASSWORDLESS vezérelt kulcsalapú és jelszó nélküli hitelesítési módszereket is támogatja. Az Azure Identity-kódtárból származó DefaultAzureCredential API jelszó nélküli hitelesítésre szolgál, így az alkalmazás zökkenőmentesen futhat a helyi fejlesztési és Azure-környezetekben. Ezt a hitelesítést a következő kódrészletben tekintheti meg:
import { DefaultAzureCredential } from "@azure/identity";
export const CREDENTIAL = new DefaultAzureCredential();
export const SCOPE_OPENAI = "https://cognitiveservices.azure.com/.default";
export async function azureADTokenProvider_OpenAI() {
const tokenResponse = await CREDENTIAL.getToken(SCOPE_OPENAI);
return tokenResponse.token;
}
Ha olyan külső kódtárakat használ, mint a LangChain.js vagy az OpenAI-kódtár az Azure OpenAI eléréséhez, a hitelesítő adatok objektumának közvetlen átadása helyett jogkivonat-szolgáltatói függvényre van szüksége. Az getBearerTokenProvider Azure Identity-kódtárból származó függvény úgy oldja meg ezt a problémát, "https://cognitiveservices.azure.com/.default"hogy létrehoz egy jogkivonat-szolgáltatót, amely automatikusan lekéri és frissíti az OAuth 2.0 tulajdonosi jogkivonatokat egy adott Azure-erőforrás hatóköréhez (például). A beállítás során egyszer konfigurálja a hatókört, és a jogkivonat-szolgáltató automatikusan kezeli az összes jogkivonat-kezelést. Ez a módszer bármilyen Azure Identity-kódtár hitelesítő adataival működik, beleértve a felügyelt identitást és az Azure CLI hitelesítő adatait. Bár az Azure SDK-könyvtárak közvetlenül elfogadják a DefaultAzureCredential -t, a külső könyvtárak, például a LangChain.js, megkövetelik ezt a token szolgáltatói mintát a hitelesítési hiányosságok áthidalásához.
Azure AI Search-integráció
Az Azure AI Search-erőforrás tárolja a dokumentumbeágyazást, és lehetővé teszi a szemantikai keresést a releváns tartalmakban. Az alkalmazás a LangChain's AzureAISearchVectorStore használatával kezeli a vektortárolót anélkül, hogy definiálnia kellene az indexsémát.
A vektortároló a rendszergazdai (írási) és a lekérdezési (olvasási) műveletek konfigurációjával jön létre, így a dokumentumok betöltése és lekérdezése különböző konfigurációkat használhat. Ez fontos, függetlenül attól, hogy kulcsokat vagy jelszó nélküli hitelesítést használ-e felügyelt identitásokkal.
Az Azure Developer CLI üzembe helyezése tartalmaz egy üzembe helyezés utáni horogot, amely feltölti a dokumentumokat a vektortárolóba LangChain.js PDF-betöltővel és beágyazási ügyféllel. Ez az üzembe helyezés utáni horog az Azure AI Search-erőforrás létrehozása után a azd up parancs utolsó lépése. A dokumentumbetöltési szkript kötegelési és újrapróbálkozási logikával kezeli a szolgáltatási sebesség korlátait.
postdeploy:
posix:
sh: bash
run: |
echo "Checking if vector store data needs to be loaded..."
# Check if already loaded
INDEX_CREATED=$(azd env get-values | grep INDEX_CREATED | cut -d'=' -f2 || echo "false")
if [ "$INDEX_CREATED" = "true" ]; then
echo "Index already created. Skipping data load."
echo "Current document count: $(azd env get-values | grep INDEX_DOCUMENT_COUNT | cut -d'=' -f2)"
else
echo "Loading vector store data..."
npm install
npm run build
npm run load_data
# Get document count from the index
SEARCH_SERVICE=$(azd env get-values | grep AZURE_AISEARCH_ENDPOINT | cut -d'/' -f3 | cut -d'.' -f1)
DOC_COUNT=$(az search index show --service-name $SEARCH_SERVICE --name northwind --query "documentCount" -o tsv 2>/dev/null || echo "0")
# Mark as loaded
azd env set INDEX_CREATED true
azd env set INDEX_DOCUMENT_COUNT $DOC_COUNT
echo "Data loading complete! Indexed $DOC_COUNT documents."
fi
Az Azure Developer CLI által létrehozott .env gyökérfájlt felhasználva hitelesítheti az Azure AI Search erőforrást, és létrehozhatja az AzureAISearchVectorStore klienst.
const endpoint = process.env.AZURE_AISEARCH_ENDPOINT;
const indexName = process.env.AZURE_AISEARCH_INDEX_NAME;
const adminKey = process.env.AZURE_AISEARCH_ADMIN_KEY;
const queryKey = process.env.AZURE_AISEARCH_QUERY_KEY;
export const QUERY_DOC_COUNT = 3;
const MAX_INSERT_RETRIES = 3;
const shared_admin = {
endpoint,
indexName,
};
export const VECTOR_STORE_ADMIN_KEY: AzureAISearchConfig = {
...shared_admin,
key: adminKey,
};
export const VECTOR_STORE_ADMIN_PASSWORDLESS: AzureAISearchConfig = {
...shared_admin,
credentials: CREDENTIAL,
};
export const VECTOR_STORE_ADMIN_CONFIG: AzureAISearchConfig =
process.env.SET_PASSWORDLESS == "true"
? VECTOR_STORE_ADMIN_PASSWORDLESS
: VECTOR_STORE_ADMIN_KEY;
const shared_query = {
endpoint,
indexName,
search: {
type: AzureAISearchQueryType.Similarity,
},
};
// Key-based config
export const VECTOR_STORE_QUERY_KEY: AzureAISearchConfig = {
key: queryKey,
...shared_query,
};
export const VECTOR_STORE_QUERY_PASSWORDLESS: AzureAISearchConfig = {
credentials: CREDENTIAL,
...shared_query,
};
export const VECTOR_STORE_QUERY_CONFIG =
process.env.SET_PASSWORDLESS == "true"
? VECTOR_STORE_QUERY_PASSWORDLESS
: VECTOR_STORE_QUERY_KEY;
Lekérdezéskor a vektortároló beágyazássá alakítja a felhasználó lekérdezését, hasonló vektoros ábrázolású dokumentumokat keres, és visszaadja a legrelevánsabb adattömböket.
export function getReadOnlyVectorStore(): AzureAISearchVectorStore {
const embeddings = getEmbeddingClient();
return new AzureAISearchVectorStore(embeddings, VECTOR_STORE_QUERY_CONFIG);
}
export async function getDocsFromVectorStore(
query: string,
): Promise<Document[]> {
const store = getReadOnlyVectorStore();
// @ts-ignore
//return store.similaritySearchWithScore(query, QUERY_DOC_COUNT);
return store.similaritySearch(query, QUERY_DOC_COUNT);
}
Mivel a vektortároló a LangChain.js-re épül, elrejti a vektortárolóval való közvetlen interakció összetettségét. A LangChain.js vektortároló felületének elsajátítása után a jövőben egyszerűen válthat más vektortároló-implementációkra.
Azure OpenAI-integráció
Az alkalmazás az Azure OpenAI-t használja a beágyazásokhoz és a nagy nyelvi modellek (LLM) képességeihez is. A AzureOpenAIEmbeddings LangChain.js osztályával beágyazásokat hozhat létre dokumentumokhoz és lekérdezésekhez. Miután létrehozta a beágyazási ügyfelet, LangChain.js használja a beágyazások létrehozásához.
Azure OpenAI-integráció beágyazásokhoz
Az Azure Developer CLI által létrehozott gyökérfájl .env használatával hitelesítheti az Azure OpenAI-erőforrást, és létrehozhatja az AzureOpenAIEmbeddings-ügyfelet :
const shared = {
azureOpenAIApiInstanceName: instance,
azureOpenAIApiEmbeddingsDeploymentName: model,
azureOpenAIApiVersion: apiVersion,
azureOpenAIBasePath,
dimensions: 1536, // for text-embedding-3-small
batchSize: EMBEDDING_BATCH_SIZE,
maxRetries: 7,
timeout: 60000,
};
export const EMBEDDINGS_KEY_CONFIG = {
azureOpenAIApiKey: key,
...shared,
};
export const EMBEDDINGS_CONFIG_PASSWORDLESS = {
azureADTokenProvider: azureADTokenProvider_OpenAI,
...shared,
};
export const EMBEDDINGS_CONFIG =
process.env.SET_PASSWORDLESS == "true"
? EMBEDDINGS_CONFIG_PASSWORDLESS
: EMBEDDINGS_KEY_CONFIG;
export function getEmbeddingClient(): AzureOpenAIEmbeddings {
return new AzureOpenAIEmbeddings({ ...EMBEDDINGS_CONFIG });
}
Azure OpenAI-integráció LLM-hez
Az Azure Developer CLI által létrehozott gyökérfájl .env használatával hitelesítheti az Azure OpenAI-erőforrást, és létrehozhatja az AzureChatOpenAI-ügyfelet :
const shared = {
azureOpenAIApiInstanceName: instance,
azureOpenAIApiDeploymentName: model,
azureOpenAIApiVersion: apiVersion,
azureOpenAIBasePath,
maxTokens: maxTokens ? parseInt(maxTokens, 10) : 1000,
maxRetries: 7,
timeout: 60000,
temperature: 0,
};
export const LLM_KEY_CONFIG = {
azureOpenAIApiKey: key,
...shared,
};
export const LLM_CONFIG_PASSWORDLESS = {
azureADTokenProvider: azureADTokenProvider_OpenAI,
...shared,
};
export const LLM_CONFIG =
process.env.SET_PASSWORDLESS == "true"
? LLM_CONFIG_PASSWORDLESS
: LLM_KEY_CONFIG;
Az alkalmazás a AzureChatOpenAI LangChain.js @langchain/openai osztályát használja az Azure OpenAI-modellek használatához.
export const callChatCompletionModel = async (
state: typeof StateAnnotation.State,
_config: RunnableConfig,
): Promise<typeof StateAnnotation.Update> => {
const llm = new AzureChatOpenAI({
...LLM_CONFIG,
});
const completion = await llm.invoke(state.messages);
completion;
return {
messages: [
...state.messages,
{
role: "assistant",
content: completion.content,
},
],
};
};
LangGraph-ügynök munkafolyamata
Az ügynök a LangGraph használatával határoz meg egy döntési munkafolyamatot, amely meghatározza, hogy egy kérdés megválaszolható-e HR-dokumentumokkal.
Gráfstruktúra:
import { StateGraph } from "@langchain/langgraph";
import {
START,
ANSWER_NODE,
DECISION_NODE,
route as endRoute,
StateAnnotation,
} from "./langchain/nodes.js";
import { getAnswer } from "./langchain/node_get_answer.js";
import {
requiresHrResources,
routeRequiresHrResources,
} from "./langchain/node_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";
A munkafolyamat a következő lépésekből áll:
- Kezdés: A felhasználó elküld egy kérdést.
- requires_hr_documents csomópont: Az LLM meghatározza, hogy a kérdés megválaszolható-e az általános HR-dokumentumokból.
-
Feltételes útválasztás:
- Ha igen, akkor továbblép a csomópontra
get_answer. - Ha nem, akkor azt az üzenetet adja vissza, amely a kérdéshez személyes HR-adatokat igényel.
- Ha igen, akkor továbblép a csomópontra
- get_answer csomópont: Lekéri a dokumentumokat, és választ hoz létre.
- Vége: Válasz a felhasználónak.
Ez a relevanciaellenőrzés azért fontos, mert nem minden HR-kérdésre lehet általános dokumentumokból válaszolni. Az olyan személyes kérdések, mint például a "Mennyi személyi erőforrással rendelkezem?", hozzáférést igényelnek az egyes alkalmazottak adatait tartalmazó alkalmazotti adatbázisokhoz. A relevancia első ellenőrzésével az ügynök elkerüli a hallucinált válaszokat azokra a kérdésekre, amelyekhez olyan személyes adatokra van szüksége, amelyekhez nem fér hozzá.
Döntse el, hogy a kérdéshez HR-dokumentumokra van-e szükség
A requires_hr_documents csomópont egy LLM használatával állapítja meg, hogy a felhasználó kérdése megválaszolható-e általános HR-dokumentumok használatával. Egy prompt sablont használ, amely arra utasítja a modellt, hogy a kérdés relevanciája alapján válaszoljon YES vagy NO. Egy strukturált üzenetben adja vissza a választ, amely a munkafolyamat mentén továbbítható. A következő csomópont ezt a választ használja a munkafolyamat útvonalának meghatározására, hogy vagy a END-hoz, vagy a ANSWER_NODE-hoz vezessen.
// @ts-nocheck
import { getLlmChatClient } from "../azure/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 "./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;
};
A szükséges HR-dokumentumok lekérése
Miután kiderült, hogy a kérdéshez HR-dokumentumok szükségesek, a munkafolyamat a megfelelő dokumentumok vektortárolóból való lekérésére, a parancssor getAnswer való hozzáadására és a teljes kérésnek az LLM-nek való átadására használja.
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { getLlmChatClient } from "../azure/llm.js";
import { StateAnnotation } from "./nodes.js";
import { AIMessage } from "@langchain/core/messages";
import { getReadOnlyVectorStore } from "../azure/vector_store.js";
const EMPTY_STATE = { messages: [] };
export async function getAnswer(
state: typeof StateAnnotation.State = EMPTY_STATE,
): Promise<typeof StateAnnotation.Update> {
const vectorStore = getReadOnlyVectorStore();
const llm = getLlmChatClient();
// 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 docs = await vectorStore.similaritySearch(userInput, 3);
if (docs.length === 0) {
const noDocMessage = new AIMessage(
"I'm sorry, I couldn't find any relevant information to answer your question.",
);
return {
messages: [...state.messages, noDocMessage],
};
}
const formattedDocs = docs.map((doc) => doc.pageContent).join("\n\n");
const prompt = ChatPromptTemplate.fromTemplate(`
Use the following context to answer the question:
{context}
Question: {question}
`);
const ragChain = prompt.pipe(llm);
const result = await ragChain.invoke({
context: formattedDocs,
question: userInput,
});
const assistantMessage = new AIMessage(result.text);
return {
messages: [...state.messages, assistantMessage],
};
}
Ha nem találhatók releváns dokumentumok, az ügynök egy üzenetet ad vissza, amely jelzi, hogy nem talált választ a HR-dokumentumokban.
Hibaelhárítás
Az eljárással kapcsolatos problémák esetén hozzon létre egy hibát a mintakódtárban
Erőforrások tisztítása
Törölheti az Azure AI Search-erőforrást és az Azure OpenAI-erőforrást tartalmazó erőforráscsoportot, vagy az Azure Developer CLI használatával azonnal törölheti az oktatóanyag által létrehozott összes erőforrást.
azd down --purge