Skip to content

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.

  1. SSH into an interactive compute node.

  2. 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 &

  3. Monitor the logs: vllm.out for standard output. vllm.err for 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()