agentsclimarketplace

Rag patterns

Skill build-with-dhiraj/ai-workflow-framework-portability-kit/Skills/rag-patterns

Portable, self-contained snapshot of a complete Claude Code setup — 36 specialist agents, 134 skills, plugins, MCP servers & host tooling. Clone, claude login, run one script, restore the whole orchestration stack in ~20 min.

Install
npx -y skills add build-with-dhiraj/ai-workflow-framework-portability-kit --skill rag-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Build RAG pipelines — vector DB + LLM, document Q&A, chunking/embedding strategies. Triggers on 'build RAG', 'document Q&A', 'retrieval pipeline', 'embed and search'.

SKILL.md

7.6 KB, as published. Nobody here has run it

RAG Patterns with LlamaIndex

Core Principle

Check the LlamaIndex docs before writing code. APIs shift between minor versions.

Primary stack: llama-index-core + llama-index-vector-stores-pinecone + Pinecone MCP.


1. RAG Decision Tree

SituationApproach
Documents > 20 pages, answers must cite sourcesRAG
Knowledge changes weekly or is privateRAG
Task needs specialized style/format learned from examplesFine-tuning
Total context fits in <100k tokens and is staticContext-stuffing (simpler, cheaper)
Need both grounding AND behavioral changeRAG + fine-tuning together

For UPSC article pipelines: always RAG. Articles are dense, frequently updated, and answers must be traceable to source text.


2. Document Loading

from llama_index.core import SimpleDirectoryReader
from llama_index.readers.web import BeautifulSoupWebReader

# PDFs, txt, md from a directory
docs = SimpleDirectoryReader(
    input_dir="./articles",
    required_exts=[".pdf", ".txt", ".md"],
    recursive=True,
).load_data()

# HTML / web articles
loader = BeautifulSoupWebReader()
docs = loader.load_data(urls=["https://example.com/article"])

# Structured JSON (article pipeline pattern)
from llama_index.core import Document

docs = [
    Document(
        text=article["body"],
        metadata={
            "title": article["title"],
            "source": article["url"],
            "date": article["published_at"],
            "category": article["category"],   # e.g. "polity", "economy"
        },
        excluded_embed_metadata_keys=["date"],   # don't embed date noise
    )
    for article in articles
]

3. Chunking Strategy

StrategyWhen to useLlamaIndex class
Fixed-sizeUniform docs, simple retrievalSentenceSplitter(chunk_size=512)
Sentence-windowDense prose, need surrounding contextSentenceWindowNodeParser
HierarchicalLong docs where sections matterHierarchicalNodeParser

UPSC articles: use sentence-window (window=3). Dense factual text; surrounding sentences add critical context for exam Q&A.

from llama_index.core.node_parser import SentenceWindowNodeParser, SentenceSplitter

# Sentence-window (recommended for UPSC)
parser = SentenceWindowNodeParser.from_defaults(
    window_size=3,
    window_metadata_key="window",
    original_text_metadata_key="original_text",
)

# Fixed-size fallback
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = splitter.get_nodes_from_documents(docs)

4. Embedding Model Selection

ModelLatencyCostQualityUse when
text-embedding-3-small (OpenAI)~50ms$0.02/1M tokensHighProduction default
text-embedding-3-large (OpenAI)~80ms$0.13/1M tokensHighestCritical retrieval
embed-english-v3.0 (Cohere)~60ms$0.10/1M tokensHighMultilingual or rerank
BAAI/bge-small-en-v1.5 (local)variesFreeGoodOffline/privacy
from llama_index.core import Settings
from llama_index.embeddings.openai import OpenAIEmbedding

Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# Dimension: 1536. Set Pinecone index dimension to match.

5. Pinecone Integration (native MCP connector)

Use the Pinecone MCP tools (mcp__pinecone__*) for index introspection, then LlamaIndex for ingestion and query.

from pinecone import Pinecone
from llama_index.vector_stores.pinecone import PineconeVectorStore
from llama_index.core import VectorStoreIndex, StorageContext

pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
index = pc.Index("upsc-articles")   # must match embedding dimension

vector_store = PineconeVectorStore(pinecone_index=index, namespace="v1")
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# Ingest
llama_index = VectorStoreIndex.from_documents(
    docs,
    storage_context=storage_context,
    show_progress=True,
)

# Query (no re-ingestion needed — Pinecone is the store)
llama_index = VectorStoreIndex.from_vector_store(vector_store)

Always set a namespace per pipeline version so you can do blue-green index swaps without downtime.


6. Query Pipeline: Retrieval → Reranking → Synthesis

from llama_index.core.postprocessor import SentenceTransformerRerank
from llama_index.core import get_response_synthesizer

# Step 1 — retrieve more candidates than you need
retriever = llama_index.as_retriever(similarity_top_k=10)

# Step 2 — rerank down to top-3 (use Cohere or cross-encoder)
reranker = SentenceTransformerRerank(
    model="cross-encoder/ms-marco-MiniLM-L-2-v2",
    top_n=3,
)

# Step 3 — synthesize with source citations
synthesizer = get_response_synthesizer(response_mode="compact")

from llama_index.core.query_engine import RetrieverQueryEngine

query_engine = RetrieverQueryEngine(
    retriever=retriever,
    node_postprocessors=[reranker],
    response_synthesizer=synthesizer,
)

response = query_engine.query("What are the powers of the Rajya Sabha?")
# response.source_nodes contains the cited chunks

7. Evaluation: Retrieval Quality Metrics

# deepeval (recommended — integrates with LlamaIndex)
from deepeval.metrics import (
    AnswerRelevancyMetric,
    FaithfulnessMetric,
    ContextualRecallMetric,
)
from deepeval.test_case import LLMTestCase

test_case = LLMTestCase(
    input=question,
    actual_output=str(response),
    expected_output=ground_truth,
    retrieval_context=[n.text for n in response.source_nodes],
)

# Run with: deepeval test run test_rag.py

Key metrics to track per pipeline version:

MetricTargetMeasures
Answer Relevancy> 0.80Does answer address the question
Faithfulness> 0.85Is answer grounded in retrieved chunks
Contextual Recall> 0.75Did retrieval surface the right chunks
MRR@10> 0.60Mean reciprocal rank of first relevant chunk

8. Production Patterns

Async ingestion — for ask-ai-daily-automation:

import asyncio
from llama_index.core import VectorStoreIndex

async def ingest_batch(docs_batch):
    index = VectorStoreIndex.from_vector_store(vector_store)
    await index.ainsert_nodes(nodes)   # non-blocking

asyncio.run(ingest_batch(new_articles))

Incremental updates — avoid re-embedding unchanged docs:

from llama_index.core.ingestion import IngestionPipeline, DocstoreStrategy
from llama_index.storage.docstore.redis import RedisDocumentStore

pipeline = IngestionPipeline(
    transformations=[parser, Settings.embed_model],
    vector_store=vector_store,
    docstore=RedisDocumentStore.from_host_and_port("localhost", 6379),
    docstore_strategy=DocstoreStrategy.UPSERTS,  # skip unchanged docs
)
pipeline.run(documents=docs)

Query caching — for repeated UPSC question patterns:

from llama_index.core.query_engine import RouterQueryEngine
from llama_index.storage.kvstore.redis import RedisKVStore

# Cache query results in Redis with TTL=3600s
# Wire this between query_engine.query() and the response return

Blue-green namespace swap:

  1. Ingest new batch into namespace="v2"
  2. Evaluate v2 metrics vs v1
  3. Switch vector_store namespace to "v2" in app config
  4. Delete namespace="v1" after 24h stability window

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.