Using Retailer Data for RAG Pipelines
Commercial point-of-interest (POI) data is typically absent from static LLM training sets. This guide shows you how to use FetchBrick's JSONL exports to build Retrieval-Augmented Generation (RAG) systems that can answer real-time spatial questions about Belgian retail locations.
What you can build
- AI agents that answer questions about store locations in real time
- Chatbots for market gap analysis and site selection
- Internal tools that combine CRM data with location intelligence
- Automated reporting on competitor coverage by region
Data format
Our JSONL (JSON Lines) format is optimized for streaming into LLMs without parsing large arrays. Each line is a self-contained JSON object representing one store location.
Why RAG for location data?
Large language models are trained on static snapshots of the internet and have no awareness of which stores opened last week, which ones closed, or how a retailer's footprint has changed over the past quarter. This means that when users ask spatial questions like "How many Colruyt stores are there in East Flanders?", the model's answer is based on outdated training data and is often wrong.
Retrieval-Augmented Generation solves this by fetching current data at query time and injecting it into the model's context window. Instead of relying on memorized facts, the LLM reasons over fresh, verified location records. FetchBrick's weekly update cycle ensures your RAG system always has accurate data to work with.
This approach is particularly valuable for three categories of applications: customer-facing chatbots that need to give accurate store directions, internal analytics tools where analysts ask natural-language questions about market coverage, and automated monitoring systems that track competitor expansion.
1. Preparing your data
Unlike long-form text documents that need to be split into overlapping chunks, point-of-interest data is already atomic. Each location is a self-contained record with a name, address, coordinates, and brand. This makes POI data unusually well-suited for RAG because you do not need to worry about chunk boundaries splitting important context.
We recommend including the brand, full address, city, province, and coordinates in the document text field. This ensures the embedding model captures both the semantic meaning (it is a Delhaize store) and the spatial context (it is in Brussels). The metadata field should contain the structured fields for post-retrieval filtering.
# Recommended document structure for each location
{
"text": "Delhaize Anspach is a Delhaize supermarket located at Boulevard Anspachlaan 123, 1000 Brussels, Belgium. Coordinates: 50.8503, 4.3517. Province: Brussels-Capital.",
"metadata": {
"brand": "delhaize",
"retailer": "delhaize",
"city": "Brussels",
"province": "Brussels-Capital",
"postal_code": "1000",
"lat": 50.8503,
"lng": 4.3517,
"store_id": "DEL-102"
}
} Notice that the text field reads like a natural sentence rather than a structured key-value pair. This matters because embedding models are trained on natural language and produce higher-quality vectors when the input reads like prose. The metadata fields duplicate some information from the text, but they enable efficient filtering at query time without relying on semantic search alone.
2. Choosing a vector database
For Belgian retail location data, you are typically working with 500 to 5,000 documents depending on how many retailers you include. This is a small dataset by vector database standards, which means you have flexibility in your choice of technology.
Chroma
Best for prototyping. Runs in-memory or with SQLite. Zero infrastructure needed. Ideal for local development and small-scale deployments.
Recommended for startPinecone
Fully managed, production-ready. Excellent metadata filtering support, which is valuable for filtering by brand, city, or province before semantic search.
Best for productionpgvector
If you already use PostgreSQL, pgvector lets you add vector search to your existing database. Combines structured SQL queries with similarity search in one system.
Best with PostgresFor most FetchBrick use cases, we recommend starting with Chroma for development and migrating to Pinecone or pgvector for production. The dataset size is small enough that performance differences between databases are negligible, so choose based on your existing infrastructure and operational preferences.
3. Implementation with LangChain
LangChain provides the simplest path from JSONL file to working RAG pipeline. The following example loads a FetchBrick export, creates embeddings, stores them in Chroma, and sets up a retrieval chain that can answer natural-language questions about store locations.
from langchain.document_loaders import JSONLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
# Step 1: Load the JSONL file
loader = JSONLoader(
file_path='fetchbrick_grocery_belgium.jsonl',
jq_schema='.text',
text_content=False,
json_lines=True
)
docs = loader.load()
# Step 2: Create embeddings and store in Chroma
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(docs, embeddings)
# Step 3: Create a retrieval chain
qa = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model="gpt-4"),
chain_type="stuff",
retriever=vectorstore.as_retriever(
search_kwargs={"k": 10}
)
)
# Step 4: Ask questions
result = qa.run(
"Which supermarket chain has the most stores "
"in the province of Antwerp?"
)
print(result) The search_kwargs={"k": 10} parameter controls how many documents are retrieved for each query. For location data, we recommend retrieving 10 to 20 documents to give the model enough context to compare across brands and regions. If you are filtering by metadata (such as restricting to a specific province), you can increase this to 50 without significant performance impact.
For production deployments, replace Chroma with Pinecone and add metadata filters to your retriever configuration. This lets users ask questions like "Which Delhaize stores in Brussels are closest to the Grand Place?" and have the retriever pre-filter to Brussels before performing semantic search.
4. Choosing an embedding model
The quality of your RAG system depends heavily on the embedding model used to vectorize your location documents. For POI data, the embedding model needs to understand both semantic meaning (what a supermarket is) and geographic context (where Brussels is relative to Antwerp).
OpenAI text-embedding-3-large
3072 dimensions. Best quality for spatial reasoning. Understands geographic relationships well.
OpenAI text-embedding-3-small
1536 dimensions. Good balance of quality and cost. Sufficient for most location queries.
Sentence Transformers (all-MiniLM-L6-v2)
384 dimensions. Runs locally, no API costs. Lower quality but sufficient for prototyping.
For Belgian retail data specifically, the text-embedding-3-small model from OpenAI provides the best cost-to-quality ratio. At approximately $0.02 per 1 million tokens, embedding the entire Belgian grocery dataset (roughly 3,000 stores) costs less than one cent.
5. Production deployment
When moving from prototype to production, there are several considerations specific to location data that differ from typical document RAG systems.
Weekly re-indexing
FetchBrick updates its data every Monday. Set up a cron job or scheduled task that downloads the latest JSONL export, re-embeds the documents, and replaces the vectors in your database. Because the dataset is small, full re-indexing takes only a few seconds and is simpler than implementing incremental updates.
Hybrid search
For location queries, pure semantic search sometimes misses exact matches. If a user asks about "Colruyt in Leuven", you want exact brand and city matching, not just semantic similarity. Combine metadata filtering (filter by brand=colruyt AND city=Leuven) with semantic search on the remaining results for best accuracy.
Geo-filtering
If your vector database supports geo-spatial queries (pgvector with PostGIS, for example), you can filter by proximity before semantic search. This is powerful for questions like "What stores are within 5 km of my office?" where you want to combine distance-based filtering with natural language understanding.
6. Alternative: Direct API integration
If you are on the Enterprise tier, you can skip the vector database entirely and use FetchBrick's REST API as a real-time data source for your AI agent. This approach is simpler to maintain because you do not need to manage embeddings or re-indexing. The trade-off is that each query requires an API call, which adds latency.
# Using FetchBrick API as a LangChain tool
from langchain.tools import tool
import requests
@tool
def search_stores(query: str, brand: str = None,
city: str = None) -> str:
"""Search Belgian retail store locations."""
params = {"search": query}
if brand:
params["retailer"] = brand
if city:
params["city"] = city
response = requests.get(
"https://api.fetchbrick.com/v1/locations",
params=params,
headers={"Authorization": "Bearer fb_live_..."}
)
return response.json() This tool-based approach works well with frameworks like LangChain Agents, CrewAI, and the Anthropic Agent SDK. The AI model decides when to call the store search tool based on the user's question, making it a natural fit for conversational interfaces.
Ready to fuel your models?
Get the complete Belgian commercial database in LLM-ready JSONL format and start building sophisticated spatial agents today.