from transformers import pipeline
from langchain_core.documents import Document
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings, HuggingFacePipeline
# 1. Create a long article
article = """
Retrieval-Augmented Generation, commonly called RAG, is a technique
used to improve the responses generated by language models.
Traditional language models generate answers using information learned
during training. However, the information available during training may
be incomplete, outdated, or unrelated to a specific organization's data.
RAG addresses this limitation by retrieving relevant information from
an external knowledge source before generating a response.
A typical RAG system begins by collecting documents from sources such
as PDFs, websites, databases, documentation, or text files.
Large documents are usually divided into smaller pieces called chunks.
Chunking makes it easier to search for specific information and retrieve
only the most relevant parts of a document.
Each chunk is converted into an embedding. An embedding is a numerical
representation of the meaning of text.
The embeddings are stored inside a vector database or vector store.
FAISS is a popular library that can perform efficient similarity search
over vector embeddings.
When a user asks a question, the question is also converted into an
embedding. The system compares the query embedding with the embeddings
stored in the vector store.
The most similar chunks are retrieved and used as context for the
language model.
The language model receives the retrieved context together with the
user's question or instruction. It then generates a response based on
the provided information.
RAG can reduce hallucinations by grounding the model's response in
retrieved information. However, the quality of the final response still
depends heavily on the quality of document chunking, embeddings, and
retrieval.
Choosing an appropriate chunk size is important. Very large chunks may
contain unnecessary information, while very small chunks may lose
important context.
Chunk overlap can help preserve information that appears near the
boundary between two chunks.
RAG systems are commonly used for document question answering,
enterprise search, knowledge assistants, customer support, and
summarisation.
"""
# 2 convert the article into langchain doc
documents = [Document(page_content=article)]
# 3. create a text splitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)
# 4. split the article into smaller chunks
chunks = text_splitter.split_documents(documents)
# 5. display the chunks
for index, chunk in enumerate(chunks, start=1):
print(f"\nChunk {index}:")
print(chunk.page_content)
# 6. Load the embedding model
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 7. Create the FAISS vector store
vector_store = FAISS.from_documents(chunks, embeddings)
# 8. create a retriever
retriever = vector_store.as_retriever(search_kwargs={"k": 4})
# 9. get a summarisation topic
query = input("\nEnter a topic to summarize: ")
# 10. retrieve relevant chunks
retrieved_chunks = retriever.invoke(query)
# 11. displaying retrieved chunks
print("\nRetrieved chunks: ")
for rank, chunk in enumerate(retrieved_chunks, start=1):
print(f"\nRank {rank}:")
print(chunk.page_content)
# 12. combine retrieved chunks into context
context = "\n\n".join(chunk.page_content for chunk in retrieved_chunks)
# 13. load a local hugging face lang model
hf_pipeline = pipeline(
task="text-generation", model="distilgpt2", max_new_tokens=150, do_sample=False
)
# 14. convert the hugging face pipeline into a langchain llm
llm = HuggingFacePipeline(pipeline=hf_pipeline)
# 15. create the summarisation prompt
prompt = PromptTemplate.from_template("""
Summarise the provided context.
Focus specifically on the topic given below.
Use only information from the provided context.
Do not add information that is not present in the context.
Topic:
{query}
Context:
{context}
Summary:
""")
# 16. Create the output parser
output_parser = StrOutputParser()
# 17. Build the summarisation chain
chain = prompt | llm | output_parser
# 18. generate the summary
response = chain.invoke({"query": query, "context": context})
# 19. final summary
print("\nFinal Summary: ")
print(response)