LangChain¶
LangChain is an open-source framework designed to build applications like RAG and Agents with Large Language Models (LLMs). It provides following key components:
- Chat models and prompts: Build LLM applications that can scale across resources, using prompt templates and chat models.
- Semantic search: Process large research datasets and PDFs efficiently by combining document loaders, embedding models, and vector stores.
- Classification: Classify text into categories or labels using chat models with structured outputs.
- Extraction: Extract structured data from text and other unstructured media using chat models and few-shot examples.
Quick guide¶
The LangChain module comes with following Extensions: jsonpatch, jsonpointer, LangChain, langchain-core, langchain-text-splitters, langsmith, orjson, packaging, tenacity and gets loaded by loading LangChain module:
module load LangChain
Simple python example¶
from langchain.text_splitter import CharacterTextSplitter
def main():
# Example text
text = """
LangChain is a framework for developing applications powered by language models.
It enables developers to chain together different components to create more complex applications.
"""
# Initialize a text splitter
text_splitter = CharacterTextSplitter(
separator="\n", # Split by newlines
chunk_size=50, # Maximum size of each chunk
chunk_overlap=10 # Overlap between chunks
)
# Split the text into chunks
chunks = text_splitter.split_text(text)
# Print the resulting chunks
print("Text Chunks:")
for i, chunk in enumerate(chunks):
print(f"Chunk {i + 1}: {chunk}")
if __name__ == "__main__":
main()
RAG agent using LangChain¶
This example requires langchain_community, langchain_huggingface and langchain_milvus that are not included in the langchain core module by the developer. It also requires the know-how of using vLLM to start a inference engine.
-
SSH into an interactive compute node.
-
Start the VLLM inference engine using the following command:
apptainer exec /apps/containers/vLLM/vllm-0.11.0.sif vllm serve /mimer/NOBACKUP/Datasets/LLM/huggingface/hub/models--HuggingFaceTB--SmolLM3-3B/snapshots/a07cc9a04f16550a088caea529712d1d335b0ac1 --port=$(find_ports) --gpu-memory-utilization 0.6 --enable_auto_tool_choice --tool_call_parser=hermes > vllm.out 2> vllm.err & -
Monitor the logs:
vllm.outfor standard output.vllm.errfor error logs.
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.chat_models import init_chat_model
import bs4
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_milvus import Milvus
from langchain.agents.middleware import dynamic_prompt, ModelRequest
def main():
# Initialize local sentence-transformers embeddings model
embeddings = HuggingFaceEmbeddings(model_name="/mimer/NOBACKUP/Datasets/LLM/huggingface/hub/models--sentence-transformers--all-MiniLM-L6-v2/snapshots/c9745ed1d9f207416be6d2e6f8de32d1f16199bf")
URI = "./milvus_example.db"
# Initialize Milvus vector store with local embeddings
vector_store = Milvus(
embedding_function=embeddings,
connection_args={"uri": URI},
index_params={"index_type": "FLAT", "metric_type": "L2"},
)
VLLM_PORT = 46219 # REPLACE WITH YOUR VLLM PORT
LLM_MODEL = "/mimer/NOBACKUP/Datasets/LLM/huggingface/hub/models--HuggingFaceTB--SmolLM3-3B/snapshots/a07cc9a04f16550a088caea529712d1d335b0ac1"
# Initialize local vLLM chat model
model = init_chat_model(
model=LLM_MODEL,
model_provider="openai",
base_url=f"http://localhost:{VLLM_PORT}/v1",
api_key="none",
)
# INDEXING
# Loading documents
bs4_strainer = bs4.SoupStrainer(class_=("post-title", "post-header", "post-content"))
# Load a blog post from Lilian Weng's blog
loader = WebBaseLoader(
web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
bs_kwargs={"parse_only": bs4_strainer},
)
docs = loader.load()
assert len(docs) == 1
print(f"Total characters: {len(docs[0].page_content)}")
print(docs[0].page_content[:500]) # Print the first 500 characters of the loaded document
# Splitting documents
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # chunk size (characters)
chunk_overlap=200, # chunk overlap (characters)
add_start_index=True, # track index in original document
)
all_splits = text_splitter.split_documents(docs)
print(f"Split blog post into {len(all_splits)} sub-documents.")
# Storing documents
document_ids = vector_store.add_documents(documents=all_splits)
print(document_ids[:3])
# RETRIEVAL AND GENERATION
# Tool usage
@tool(response_format="content_and_artifact")
def retrieve_context(query: str):
"""Retrieve information to help answer a query."""
retrieved_docs = vector_store.similarity_search(query, k=2)
serialized = "\n\n".join(
(f"Source: {doc.metadata}\nContent: {doc.page_content}")
for doc in retrieved_docs
)
return serialized, retrieved_docs
# Create an agent with the retrieval tool
tools = [retrieve_context]
prompt = (
"/no_think You have access to a tool that retrieves context from a blog post. "
"Use the tool to help answer user queries."
)
agent = create_agent(model, tools, system_prompt=prompt)
# Example query to the agent
query = (
"What is the standard method for Task Decomposition?\n\n"
"Once you get the answer, look up common extensions of that method."
)
for event in agent.stream(
{"messages": [
{"role": "system", "content": "/no_think"},
{"role": "user", "content": query}
]},
stream_mode="values",
):
event["messages"][-1].pretty_print()
# No tool usage
@dynamic_prompt
def prompt_with_context(request: ModelRequest) -> str:
"""Inject context into state messages."""
last_query = request.state["messages"][-1].text
retrieved_docs = vector_store.similarity_search(last_query)
docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs)
system_message = (
"/no_think You are a helpful assistant. Use the following context in your response:"
f"\n\n{docs_content}"
)
print(system_message)
return system_message
agent = create_agent(model, tools=[], middleware=[prompt_with_context])
query = "What is task decomposition?"
for step in agent.stream(
{"messages": [{"role": "user", "content": query}]},
stream_mode="values",
):
step["messages"][-1].pretty_print()
if __name__ == "__main__":
main()