Documents and splitting
Answering from the shop's policies starts with the text. A Document holds text and metadata, and a text splitter cuts long text into chunks worth searching.
So far the agent knows orders. Customers also ask about the rules: how long a refund takes, when shipping is free. The answers are in three short policy files, and parts 6 and 7 build an assistant that answers from them. Two more packages are needed: the text splitters, and numpy, which LangChain's in-memory search in lesson 27 uses but does not install.
pip install "langchain-text-splitters==1.1.2" "numpy==2.5.3"Documents
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
POLICIES = {
"refunds.md": "Refunds go back to the card you paid with. They take up to 5 working days to arrive."
"\n\nYou can ask for a refund within 30 days of delivery. Opened items can be refunded if they are faulty.",
"shipping.md": "Standard shipping takes 3 to 5 working days. Shipping is free on orders over 50 euros."
"\n\nExpress shipping arrives the next working day and costs 9 euros.",
"accounts.md": "To reset your password, use the reset link on the sign-in page. Support staff never ask for your password.",
}
docs = [Document(page_content=text, metadata={"source": name}) for name, text in POLICIES.items()]print(len(docs))
print(docs[0].metadata)
print(docs[0].page_content[:60])A Document has page_content, the text, and metadata, a dictionary for anything else. The file name goes in the metadata so every answer can say where it came from.
Chunks
splitter = RecursiveCharacterTextSplitter(chunk_size=120, chunk_overlap=0, add_start_index=True)
chunks = splitter.split_documents(docs)for chunk in chunks:
print(chunk.metadata["source"], chunk.metadata["start_index"], chunk.page_content[:45])A search should find the paragraph that answers the question, not a whole file. RecursiveCharacterTextSplitter splits on paragraph breaks first and only cuts smaller when a piece is still over chunk_size characters. Every paragraph here fits in 120, so each became one chunk. add_start_index records where each chunk began in its document.
Chunks that overlap
small = RecursiveCharacterTextSplitter(chunk_size=60, chunk_overlap=20)
for piece in small.split_text(POLICIES["refunds.md"])[:4]:
print(repr(piece))At 60 characters the splitter had to cut inside paragraphs, at spaces. chunk_overlap repeats up to 20 characters from the end of one chunk at the start of the next, so a sentence cut in two still appears whole somewhere. The documentation's tutorial uses chunks of 1,000 characters with 200 of overlap for a long PDF.
- Set
chunk_size=50and count the chunks for all three documents. - Add a fourth policy,
"payments.md", and check its chunks. - Split with
chunk_overlap=0at size 60 and compare the pieces.
Little by little, you're building something great.