Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

LangChain API Tutorial

This tutorial demonstrates how to use LangChain’s core functionalities. LangChain is a powerful framework designed to facilitate building language model-powered applications. We’ll explore its components, including prompt creation, chains, retrieval, and agents.

# Use this to enable vim shortcuts.
# !sudo /bin/bash -c "(source /venv/bin/activate; pip install --quiet jupyterlab-vim)"
# !jupyter labextension enable
%load_ext autoreload
%autoreload 2

Setting Up

We’ll start by setting up the environment and initializing our language model (ChatOpenAI). Here, we’re using OpenAI’s gpt-4o-mini model with a temperature of 0 for deterministic outputs.

#!sudo /venv/bin/pip install langchain --quiet
#!sudo /venv/bin/pip install -U langchain-community --quiet
#!sudo /venv/bin/pip install -U langchain-openai --quiet
#!sudo /venv/bin/pip install -U langchain-core --quiet
#!sudo /venv/bin/pip install -U langchainhub --quiet
#!sudo /venv/bin/pip install -U unstructured --quiet
#!sudo /venv/bin/pip install --quiet chromadb
import logging
import random
import time

import helpers.hdbg as hdbg
import langchain
import langchain.agents as lngchagents
import langchain.document_loaders.csv_loader as csvloader
import langchain.hub
import langchain.prompts as lngchprmt
import langchain.schema.messages as lnchscme
import langchain.schema.runnable as lngchschrun
import langchain_community.vectorstores as vectorstores
import langchain_core.output_parsers as lngchoutpar
import langchain_openai as lngchopai
# Avoid messages from OpenAI REST interface.
hdbg.init_logger(verbosity=logging.CRITICAL)

_LOG = logging.getLogger(__name__)
WARNING: Running in Jupyter

Add your OpenAPI key and initiate GPT model

# Add OpenAPI to environment variable.
# os.environ["OPENAI_API_KEY"] = ""
# Initiate OpenAI model.
chat_model = lngchopai.ChatOpenAI(model="gpt-4o-mini", temperature=0)

Message Handling with HumanMessage and SystemMessage

LangChain uses HumanMessage and SystemMessage objects to structure conversations.

  • SystemMessage: Defines the behavior of the assistant.
  • HumanMessage: Represents user input.

Let’s see how this works in practice with some example messages.

# Define system behavior and user input.
messages = [
    lnchscme.SystemMessage(
        content="You're an assistant knowledgeable about healthcare."
    ),
    lnchscme.HumanMessage(content="What is Medicaid managed care?"),
]
# Generate a response.
val = chat_model.invoke(messages)
type(val)
langchain_core.messages.ai.AIMessage
print(val.content)
Medicaid managed care is a system of delivering Medicaid benefits through private health insurance plans. In this model, state Medicaid programs contract with private insurance companies to provide a range of healthcare services to Medicaid beneficiaries. Here are some key features of Medicaid managed care:

1. **Care Coordination**: Managed care organizations (MCOs) often focus on coordinating care for their members, which can lead to improved health outcomes. They may provide case management services to help beneficiaries navigate the healthcare system.

2. **Cost Control**: By contracting with private insurers, states aim to control costs while ensuring that beneficiaries receive necessary services. MCOs are incentivized to manage care efficiently, which can help reduce unnecessary hospitalizations and emergency room visits.

3. **Network of Providers**: MCOs typically have a network of healthcare providers, including primary care physicians, specialists, and hospitals. Beneficiaries usually need to receive care from providers within this network to have their services covered.

4. **Preventive Services**: Many Medicaid managed care plans emphasize preventive care and wellness services, aiming to keep members healthy and reduce the need for more expensive treatments.

5. **Variety of Services**: Medicaid managed care plans may offer a range of services beyond traditional medical care, including behavioral health services, dental care, and long-term services and supports, depending on the state’s program.

6. **State Flexibility**: States have flexibility in designing their Medicaid managed care programs, including the types of services covered, payment structures, and the populations served.

7. **Enrollment**: Beneficiaries may be automatically enrolled in a managed care plan or have the option to choose from several plans. Enrollment processes can vary by state.

Overall, Medicaid managed care aims to improve access to care, enhance the quality of services, and manage costs effectively for both states and beneficiaries.
val.usage_metadata
{'input_tokens': 24, 'output_tokens': 371, 'total_tokens': 395, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}

Restricting Assistant’s Scope

You can further control the assistant’s responses by tailoring the SystemMessage. For instance, we’ll restrict it to only answer healthcare-related questions.

messages = [
    lnchscme.SystemMessage(
        content="You're an assistant knowledgeable about healthcare. Only answer healthcare-related questions."
    ),
    lnchscme.HumanMessage(content="How do I change a tire?"),
]
val = chat_model.invoke(messages)
print(val.content)
I'm here to help with healthcare-related questions. If you have any health concerns or questions about medical topics, feel free to ask!

Creating Custom Prompts with ChatPromptTemplate

Custom prompts are essential for tasks like summarization, question answering, or content generation. We’ll use ChatPromptTemplate to define structured prompts and format them dynamically.

# Define a custom template for hospital reviews.
review_template_str = """
Your job is to use patient reviews to answer questions about their experience at a hospital.
Use the following context to answer questions. Be as detailed as possible, but don't make up
any information that's not from the context. If you don't know an answer, say you don't know.

{context}

{question}
"""

review_template = lngchprmt.ChatPromptTemplate.from_template(review_template_str)

# Provide context and a question.
context = "I had a great stay!"
question = "Did anyone have a positive experience?"

# Format the template.
print(review_template.format(context=context, question=question))
Human: 
Your job is to use patient reviews to answer questions about their experience at a hospital.
Use the following context to answer questions. Be as detailed as possible, but don't make up
any information that's not from the context. If you don't know an answer, say you don't know.

I had a great stay!

Did anyone have a positive experience?

Advanced Prompt Structuring

Sometimes, you may need to structure prompts with multiple components, like system instructions and user input. SystemMessagePromptTemplate and HumanMessagePromptTemplate allow fine-grained control.

# Define system and human message templates.
review_system_prompt = lngchprmt.SystemMessagePromptTemplate(
    prompt=lngchprmt.PromptTemplate(
        input_variables=["context"], template=review_template_str
    )
)

review_human_prompt = lngchprmt.HumanMessagePromptTemplate(
    prompt=lngchprmt.PromptTemplate(
        input_variables=["question"], template="{question}"
    )
)

# Combine into a chat prompt template.
review_prompt_template = lngchprmt.ChatPromptTemplate(
    input_variables=["context", "question"],
    messages=[review_system_prompt, review_human_prompt],
)

# Format messages.
formatted_messages = review_prompt_template.format_messages(
    context=context, question=question
)
print(formatted_messages)
[SystemMessage(content="\nYour job is to use patient reviews to answer questions about their experience at a hospital.\nUse the following context to answer questions. Be as detailed as possible, but don't make up\nany information that's not from the context. If you don't know an answer, say you don't know.\n\nI had a great stay!\n\nDid anyone have a positive experience?\n", additional_kwargs={}, response_metadata={}), HumanMessage(content='Did anyone have a positive experience?', additional_kwargs={}, response_metadata={})]
print(formatted_messages[0].content)

Your job is to use patient reviews to answer questions about their experience at a hospital.
Use the following context to answer questions. Be as detailed as possible, but don't make up
any information that's not from the context. If you don't know an answer, say you don't know.

I had a great stay!

Did anyone have a positive experience?

print(formatted_messages[1].content)
Did anyone have a positive experience?

Chains

Chains are a fundamental abstraction in LangChain, allowing you to combine prompts and models into workflows. We’ll create a simple chain to answer questions based on a given context.

# Create a chain using the template and chat model.
output_parser = lngchoutpar.StrOutputParser()
review_chain = review_prompt_template | chat_model | output_parser

# Test the chain.
review_chain.invoke({"context": context, "question": question})
'Yes, one patient mentioned that they had a great stay at the hospital, indicating a positive experience.'

Retrieval with FAISS

FAISS (Facebook AI Similarity Search) is used to efficiently retrieve relevant documents based on similarity scores. We’ll demonstrate how to load a dataset, create embeddings, and retrieve documents.

import pandas as pd

REVIEWS_CSV_PATH = "data/reviews.csv"

df = pd.read_csv(REVIEWS_CSV_PATH)
df.head(3)

# Load reviews dataset.
loader = csvloader.CSVLoader(file_path=REVIEWS_CSV_PATH, source_column="review")
reviews = loader.load()
Loading...
len(reviews)
1005
REVIEWS_CHROMA_PATH = "chroma_data"

# Create a vector store.
reviews_vector_db = vectorstores.Chroma.from_documents(
    reviews, lngchopai.OpenAIEmbeddings(), persist_directory=REVIEWS_CHROMA_PATH
)
# Retrieve relevant documents.
question = "Has anyone complained about communication with the hospital staff?"
relevant_docs = reviews_vector_db.similarity_search(question, k=3)

print("#0\n" + relevant_docs[0].page_content)
print("#1\n" + relevant_docs[1].page_content)
print("#2\n" + relevant_docs[2].page_content)
#0
review_id: 73
visit_id: 7696
review: I had a frustrating experience at the hospital. The communication between the medical staff and me was unclear, leading to misunderstandings about my treatment plan. Improvement is needed in this area.
physician_name: Maria Thompson
hospital_name: Little-Spencer
patient_name: Terri Smith
#1
review_id: 521
visit_id: 631
review: I had a challenging time at the hospital. The medical care was adequate, but the lack of communication between the staff and me left me feeling frustrated and confused about my treatment plan.
physician_name: Samantha Mendez
hospital_name: Richardson-Powell
patient_name: Kurt Gordon
#2
review_id: 785
visit_id: 2593
review: My stay at the hospital was challenging. The medical care was adequate, but the lack of communication from the staff created some frustration.
physician_name: Brittany Harris
hospital_name: Jones, Taylor and Garcia
patient_name: Ryan Jacobs

Building a Retrieval-Enhanced QA Chain

We’ll combine retrieval and prompts to build a more dynamic question-answering system. This chain retrieves relevant documents and uses them as context for the assistant.

# Create a retriever.
reviews_retriever = reviews_vector_db.as_retriever(k=10)

# Build the QA chain.
review_chain = (
    {"context": reviews_retriever, "question": lngchschrun.RunnablePassthrough()}
    | review_prompt_template
    | chat_model
    | lngchoutpar.StrOutputParser()
)

# Test the QA chain.
question = "Has anyone complained about communication with the hospital staff?"
# question = "Has anyone complained the price of eggs?"
review_chain.invoke(question)
'Yes, several patients have complained about communication with the hospital staff. For example, Terri Smith mentioned that the communication between the medical staff and herself was unclear, leading to misunderstandings about her treatment plan. Kurt Gordon expressed frustration and confusion due to a lack of communication, despite finding the medical care adequate. Ryan Jacobs also noted that the lack of communication from the staff created some frustration during his stay. Additionally, Shannon Williams had a mixed experience, stating that while the medical care was good, the lack of communication made her stay less enjoyable.'

Agents

Agents are more flexible than chains, as they can decide the sequence of actions to take. We’ll demonstrate an agent that can answer questions using tools for reviews and wait times.

  • The chain is hardwired
  • An agent is an LLM that decides the sequence of actions to execute.
def get_current_wait_time(hospital: str) -> int | str:
    """
    Dummy function to generate fake wait times.
    """
    if hospital not in ["A", "B", "C", "D"]:
        return f"Hospital {hospital} does not exist"
    # Simulate API call delay.
    time.sleep(1)
    return random.randint(0, 10000)
# Tool is an interface that an agent uses to interact with a function.
# Each description explains the Agent when to call each tool.
tools = [
    lngchagents.Tool(
        name="Reviews",
        func=review_chain.invoke,
        description="""Useful when you need to answer questions
        about patient reviews or experiences at the hospital.
        Not useful for answering questions about specific visit
        details such as payer, billing, treatment, diagnosis,
        chief complaint, hospital, or physician information.
        Pass the entire question as input to the tool. For instance,
        if the question is "What do patients think about the triage system?",
        the input should be "What do patients think about the triage system?"
        """,
    ),
    lngchagents.Tool(
        name="Waits",
        func=get_current_wait_time,
        description="""Use when asked about current wait times
        at a specific hospital. This tool can only get the current
        wait time at a hospital and does not have any information about
        aggregate or historical wait times. This tool returns wait times in
        minutes. Do not pass the word "hospital" as input,
        only the hospital name itself. For instance, if the question is
        "What is the wait time at hospital A?", the input should be "A".
        """,
    ),
]

hospital_agent_prompt = langchain.hub.pull("hwchase17/openai-functions-agent")

hospital_agent = lngchagents.create_openai_functions_agent(
    llm=chat_model,
    prompt=hospital_agent_prompt,
    tools=tools,
)

# Agent run-time.
hospital_agent_executor = lngchagents.AgentExecutor(
    agent=hospital_agent,
    tools=tools,
    return_intermediate_steps=True,
    verbose=True,
)
/venv/lib/python3.12/site-packages/langsmith/client.py:278: LangSmithMissingAPIKeyWarning: API key must be provided when using hosted LangSmith API
  warnings.warn(
hospital_agent_executor.invoke(
    {"input": "What is the current wait time at hospital C?"}
)


> Entering new AgentExecutor chain...

Invoking: `Waits` with `C`


4022The current wait time at hospital C is 4022 minutes.

> Finished chain.
{'input': 'What is the current wait time at hospital C?', 'output': 'The current wait time at hospital C is 4022 minutes.', 'intermediate_steps': [(AgentActionMessageLog(tool='Waits', tool_input='C', log='\nInvoking: `Waits` with `C`\n\n\n', message_log=[AIMessageChunk(content='', additional_kwargs={'function_call': {'arguments': '{"__arg1":"C"}', 'name': 'Waits'}}, response_metadata={'finish_reason': 'function_call', 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_86d0290411'}, id='run-58fe8f60-0495-4374-95bc-9df9bc0c74b8')]), 4022)]}
hospital_agent_executor.invoke(
    {"input": "What have patients said about their comfort at the hospital?"}
)


> Entering new AgentExecutor chain...

Invoking: `Reviews` with `What have patients said about their comfort at the hospital?`


Patients have expressed mixed feelings about their comfort at the hospital. 

One patient, Jasmine Patel, noted that the hospital's dedication to patient comfort was evident in the well-designed private rooms and comfortable furnishings, which made her recovery more bearable and contributed to an overall positive experience.

In contrast, other patients reported issues with comfort. Tammy Benson mentioned that while she appreciated the staff's dedication to patient care, the uncomfortable beds made it difficult for her to get a good night's sleep during her stay. Similarly, Crystal Johnson echoed this sentiment, stating that the uncomfortable beds affected her overall comfort despite the staff's dedication to care. Nancy Collins also highlighted the outdated and uncomfortable beds, which impacted her comfort, although she acknowledged the knowledgeable doctors and clean environment of the hospital.

Overall, while some patients appreciated the efforts made for comfort, others found the beds to be a significant drawback.Patients have expressed mixed feelings about their comfort at the hospital. 

Some, like Jasmine Patel, noted that the hospital's dedication to patient comfort was evident in the well-designed private rooms and comfortable furnishings, which made recovery more bearable and contributed to a positive experience. 

However, other patients reported issues with comfort. Tammy Benson mentioned that while she appreciated the staff's dedication to care, the uncomfortable beds made it difficult for her to get a good night's sleep. Crystal Johnson echoed this sentiment, stating that the uncomfortable beds affected her overall comfort despite the staff's dedication. Nancy Collins also highlighted the outdated and uncomfortable beds, which impacted her comfort, although she acknowledged the knowledgeable doctors and clean environment of the hospital.

In summary, while some patients appreciated the efforts made for comfort, others found the beds to be a significant drawback.

> Finished chain.
{'input': 'What have patients said about their comfort at the hospital?', 'output': "Patients have expressed mixed feelings about their comfort at the hospital. \n\nSome, like Jasmine Patel, noted that the hospital's dedication to patient comfort was evident in the well-designed private rooms and comfortable furnishings, which made recovery more bearable and contributed to a positive experience. \n\nHowever, other patients reported issues with comfort. Tammy Benson mentioned that while she appreciated the staff's dedication to care, the uncomfortable beds made it difficult for her to get a good night's sleep. Crystal Johnson echoed this sentiment, stating that the uncomfortable beds affected her overall comfort despite the staff's dedication. Nancy Collins also highlighted the outdated and uncomfortable beds, which impacted her comfort, although she acknowledged the knowledgeable doctors and clean environment of the hospital.\n\nIn summary, while some patients appreciated the efforts made for comfort, others found the beds to be a significant drawback.", 'intermediate_steps': [(AgentActionMessageLog(tool='Reviews', tool_input='What have patients said about their comfort at the hospital?', log='\nInvoking: `Reviews` with `What have patients said about their comfort at the hospital?`\n\n\n', message_log=[AIMessageChunk(content='', additional_kwargs={'function_call': {'arguments': '{"__arg1":"What have patients said about their comfort at the hospital?"}', 'name': 'Reviews'}}, response_metadata={'finish_reason': 'function_call', 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_86d0290411'}, id='run-6d696ba4-0b7b-4f72-9ef9-894490e530c3')]), "Patients have expressed mixed feelings about their comfort at the hospital. \n\nOne patient, Jasmine Patel, noted that the hospital's dedication to patient comfort was evident in the well-designed private rooms and comfortable furnishings, which made her recovery more bearable and contributed to an overall positive experience.\n\nIn contrast, other patients reported issues with comfort. Tammy Benson mentioned that while she appreciated the staff's dedication to patient care, the uncomfortable beds made it difficult for her to get a good night's sleep during her stay. Similarly, Crystal Johnson echoed this sentiment, stating that the uncomfortable beds affected her overall comfort despite the staff's dedication to care. Nancy Collins also highlighted the outdated and uncomfortable beds, which impacted her comfort, although she acknowledged the knowledgeable doctors and clean environment of the hospital.\n\nOverall, while some patients appreciated the efforts made for comfort, others found the beds to be a significant drawback.")]}