AI Agent
Translated from the Spanish original. Read in Spanish
In this tutorial we’ll learn how to build an Artificial Intelligence (AI) Agent that can answer questions using Active Directory and a Knowledge Base (KB). We’ll use LangChain and Azure for this.

Agents
The core idea of agents is to use a language model to choose a sequence of actions to take. In chains, the sequence of actions is predefined (in code). In agents, a language model is used as a reasoning engine to decide which actions to take and in what order.
Setting Up the Environment
Before we start, we need to set some environment variables and get an Azure access token. To do this, put a .env file in the same directory with the following information:
AZURE_TENANT_ID = "00000000-0000-0000-0000-000000000000"
AZURE_CLIENT_ID = "00000000-0000-0000-0000-000000000000"
AZURE_CLIENT_SECRET = "xxxxx"
Once we have the .env file, we’ll add the code needed to get the token.
import os
from azure.identity import ChainedTokenCredential, EnvironmentCredential
from dotenv import load_dotenv
load_dotenv()
credential = ChainedTokenCredential(EnvironmentCredential())
access_token = credential.get_token("https://cognitiveservices.azure.com/.default")
Configuring the Model and Environment Variables
Next, we’ll configure the Azure OpenAI model and set the required environment variables.
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://zerogap.openai.azure.com/"
os.environ["AZURE_OPENAI_API_KEY"] = access_token.token
os.environ["OPENAI_API_TYPE"] = "azure_ad"
os.environ["OPENAI_DEPLOYMENT"] = "zerogap-openai-ue2-gpt4-turbo"
Initialising the AI Tools
We’ll initialise the Azure OpenAI chat model, the AzureOpenAIEmbeddings class and the embeddings model.
from langchain.chat_models import AzureChatOpenAI
from langchain.embeddings import AzureOpenAIEmbeddings
llm = AzureChatOpenAI(openai_api_version="2023-07-01-preview", azure_deployment="zerogap-openai-ue2-gpt4-turbo", temperature=0.5)
embeddings = AzureOpenAIEmbeddings(
azure_deployment="zerogap-openai-ue2-ada",
openai_api_version="2023-07-01-preview",
chunk_size=1000
)
Setting Up the Vector DB and Retriever
We’ll load documents from the persistent directory, assuming you already have the KB loaded into a vector database (more information here: QA AI Bot using a local LLM and documents – The Zero Gap Zone).
from langchain.vectorstores import Chroma
persist_directory = "chroma_db_generic"
vectordb = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
vectordb.get()
retriever = vectordb.as_retriever(search_type="similarity", search_kwargs={"k": 5})
Tools for Working with Active Directory and the Knowledge Base
Create tools to interact with Active Directory and get information from the Knowledge Base.
import subprocess
from langchain.tools import Tool
def get_ad_user(search_query):
ps_command = f'get-aduser -Filter {{Name -like "*{search_query}*"}} -Properties Office, OfficePhone | Select-Object Name, Office, OfficePhone'
result = subprocess.run(["powershell", ps_command], capture_output=True, text=True)
return result.stdout
run_ad_tool = Tool.from_function(
name="get_ad_user",
description="Get user information from Active Directory",
func=get_ad_user
)
def get_kb(question):
context = retriever.invoke(question)
formated_context = format_docs(context)
return formated_context
run_kb_tool = Tool.from_function(
name="get_kb",
description="Get information from the Knowledge Base",
func=get_kb
)
tools = [run_ad_tool, run_kb_tool]
Creating and Running the AI Agent
We’ll define a prompt template and the function that runs the agent.
from langchain.agents import AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
react_prompt = PromptTemplate.from_template("""
You are an assistant for question-answering tasks. Follow these instructions step by step:
1. If the question is about a person, try to get more information from Active Directory.
2. If the question is not about a person, try to get more information from your Knowledge Base
3. If you can not find the answer, respond with 'Sorry, I do not know'
These are examples:
Example 1:
Question: Who is John Doe?
Thought: The question is about a person, I should use the Active Directory tool.
Action: get_ad_user
Action Input: John Doe
Observation: The get_ad_user tool indicates John Doe is an Actor in Friends.
Thought: I now have the final answer.
Final Answer: John Doe is an Actor in the TV Show Friends.
Example 2:
Question: What is a transistor?
Thought: The question is not about a person, I need to use the Knowledge Base tool.
Action: get_kb
Action Input: What is a transistor?
Observation: A transistor is a semiconductor device used to amplify or switch electrical signals and power. It is one of the basic building blocks of modern electronics.
Thought: I now have the final answer.
Final Answer: A transistor is a semiconductor device used to amplify or switch electrical signals and power. It is one of the basic building blocks of modern electronics
You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}
""")
def run_agent(question):
agent = create_react_agent(
llm=llm,
prompt=react_prompt,
tools=tools
)
agent_executor = AgentExecutor(
agent=agent,
verbose=True,
tools=tools
)
response = agent_executor.invoke({"input": question})
return response
Interacting with the AI Agent
Finally, we’ll create a loop to interact with the AI Agent and get answers to our questions.
print("\033[92m" + "Welcome to the ZEROGAP AI QA Bot!" + "\033[0m")
print("\033[92m" + "###############################" + "\033[0m")
print("\033[92m" + "###############################" + "\033[0m")
print("\n")
while True:
question = input("\033[93m" + "You: " + "\033[0m")
print("\n")
if question == "quit":
break
result = run_agent(question)
print("\033[92m" + result + "\033[0m")
print("\n")
Complete Code
Here is the complete code for the AI Agent we built in this tutorial:
import os, subprocess
from azure.identity import ChainedTokenCredential, EnvironmentCredential
from langchain.vectorstores import Chroma
from langchain.embeddings import AzureOpenAIEmbeddings
from langchain.chat_models import AzureChatOpenAI
from langchain.tools import Tool
from langchain.agents import AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
from dotenv import load_dotenv
load_dotenv()
# Place a .env file within the same folder with the following information:
# AZURE_TENANT_ID = "00000000-0000-0000-0000-000000000000"
# AZURE_CLIENT_ID = "00000000-0000-0000-0000-000000000000"
# AZURE_CLIENT_SECRET = "xxxxx"
credential = ChainedTokenCredential(EnvironmentCredential())
access_token = credential.get_token("https://cognitiveservices.azure.com/.default")
# Model
deployment = "zerogap-openai-ue2-gpt4-turbo"
# Model text-embedding-ada-002
embedding_deployment = "zerogap-openai-ue2-ada"
# Set OS environment variables
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://zerogap.openai.azure.com/"
os.environ["AZURE_OPENAI_API_KEY"] = access_token.token
os.environ["OPENAI_API_TYPE"] = "azure_ad"
os.environ["OPENAI_DEPLOYMENT"] = deployment
llm = AzureChatOpenAI(openai_api_version="2023-07-01-preview", azure_deployment=deployment, temperature=0.5)
# Initialize the OpenAIEmbeddings class
embeddings = AzureOpenAIEmbeddings(
azure_deployment=embedding_deployment,
openai_api_version="2023-07-01-preview",
chunk_size=1000
)
# Load documents from the persisted directory
# Assuming you already have the KB loaded to a vector database
persist_directory = "chroma_db_generic"
vectordb = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
vectordb.get()
retriever = vectordb.as_retriever(search_type="similarity", search_kwargs={"k": 5})
# Join all the documents from the retriever together with newlines
def format_docs(docs):
if docs:
return "\n\n".join(doc.page_content for doc in docs)
# Function to get AD user
def get_ad_user(search_query):
# Run the PowerShell command to retrieve user information including the specified attributes
ps_command = f'get-aduser -Filter {{Name -like "*{search_query}*"}} -Properties Office, OfficePhone | Select-Object Name, Office, OfficePhone'
result = subprocess.run(["powershell", ps_command], capture_output=True, text=True)
# Return the output
return result.stdout
run_ad_tool = Tool.from_function(
name="get_ad_user",
description="Get user information from Active Directory",
func=get_ad_user
)
def get_kb(question):
# Queries the Vector DB using user's question
context = retriever.invoke(question)
formated_context = format_docs(context)
return formated_context
run_kb_tool = Tool.from_funcion(
name="get_kb",
description="Get information from the Knowledge Base",
func=get_kb
)
tools = [run_ad_tool,run_kb_tool]
tool_names = [tool.name for tool in tools]
react_prompt = PromptTemplate.from_template("""
You are an assistant for question-answering tasks. Follow these instructions step by step:
1. If the question is about a person, try to get more information from Active Directory.
2. If the question is not about a person, try to get more information from your Knowledge Base
3. If you can not find the answer, respond with 'Sorry, I do not know'
These are examples:
Example 1:
Question: Who is John Doe?
Thought: The question is about a person, I should use the Active Directory tool.
Action: get_ad_user
Action Input: John Doe
Observation: The get_ad_user tool indicates John Doe is an Actor in Friends.
Thought: I now have the final answer.
Final Answer: John Doe is an Actor in the TV Show Friends.
Example 2:
Question: What is a transistor?
Thought: The question is not about a person, I need to use the Knowledge Base tool.
Action: get_kb
Action Input: What is a transistor?
Observation: A transistor is a semiconductor device used to amplify or switch electrical signals and power. It is one of the basic building blocks of modern electronics.
Thought: I now have the final answer.
Final Answer: A transistor is a semiconductor device used to amplify or switch electrical signals and power. It is one of the basic building blocks of modern electronics
You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}
""")
def run_agent(question):
agent = create_react_agent(
llm=llm,
prompt=react_prompt,
tools=tools
)
agent_executor = AgentExecutor(
agent=agent,
verbose=True,
tools=tools
)
response = agent_executor.invoke({"input": question})
return response
# print welcome message in green
print("\033[92m" + "Welcome to the ZEROGAP AI QA Bot!" + "\033[0m")
print("\033[92m" + "###############################" + "\033[0m")
print("\033[92m" + "###############################" + "\033[0m")
print("\n")
while True:
#input in yellow
question = input("\033[93m" + "You: " + "\033[0m")
print("\n")
if question == "quit":
break
result = run_agent(question)
print("\033[92m" + result + "\033[0m")
print("\n")
