Lesson 37 — Beginner
Other Orchestration Frameworks
LangChain ek option hai, standard nahi. LlamaIndex data-centric rakhta hai, graph frameworks state aur branching, DSPy declarative optimization — aur kabhi-kabhi sabse acha option raw SDK + apna chhota layer hi hota hai. Is lesson mein in approaches ko compare karke choose karna seekhenge.
Orchestration ke alag-alag approaches
WHAT
Orchestration framework = LLM calls, state, tools aur steps ko manage karne wala layer. Har framework ka apna centre of gravity hai: LangChain general chains, LlamaIndex data/retrieval, graphs control flow, DSPy prompt optimization.
WHEN
Jab workflow chhoti Python functions se nahi sambhali ja rahi — state, branches, loops, retries aur testability chahiye. Pehle khud likho, phir framework uthao.
WHERE
RAG systems, stateful agents, research pipelines, prompt-heavy products — jahan control flow aur state pehle se design karna ho.
LlamaIndex — data pehle
# LlamaIndex — ingest -> index -> query ka data-first model
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
docs = SimpleDirectoryReader("./policies").load_data() # ingest
index = VectorStoreIndex.from_documents(docs) # index
query_engine = index.as_query_engine() # query
print(query_engine.query("Refund policy kya hai?"))
- LlamaIndex ka focus data + retrieval hai — ingestion pipelines, indices, retrievers, query engines pehle-class citizens.
- Documents se jawab wala kaam (RAG) wahan aasan lagta hai; LangChain mein retrieval ek integration hai, poora framework nahi.
- Dono ek doosre ke saath use ho sakte hain — real projects mein overlap normal hai, religion nahi.
- Chunne ka test: data-heavy kaam (docs, policies, KB) ho toh LlamaIndex ka model natural lagega; general workflow ho toh LangChain ya raw.
Graph / state-machine orchestration — LangGraph
# Nodes = steps, edges = rules, state = shared memory
from typing import TypedDict
from langgraph.graph import StateGraph, END
class S(TypedDict):
question: str
facts: str
answer: str
def research(state: S):
return {"facts": gather(state["question"])}
def draft(state: S):
return {"answer": write(state["facts"])}
def needs_more(state: S): # routing node
return "research" if len(state["facts"]) < 200 else "draft"
g = StateGraph(S)
g.add_node("research", research)
g.add_node("draft", draft)
g.add_conditional_edges("research", needs_more,
{"research": "research", "draft": "draft"}) # loop + branch
g.add_edge("draft", END)
g.set_entry_point("research")
app = g.compile()
app.invoke({"question": "...", "facts": "", "answer": ""})
- Plain if/else se manage karte-karte bade workflows spaghetti ho jaate hain — graph mein har node aur edge explicitly draw hota hai.
- State ek shared structure hai jo har node padhta hai aur update karta hai — isi mein conversation, memory aur intermediate data rehta hai.
- Loops (research → check → research), branches aur persistent state — graph style isi liye bana gaya hai.
- LangGraph LangChain family ka hi hai — stateful agents ke liye, aur checkpoints se run ko interrupt/resume bhi kar sakte ho.
- Har node ek plain function hai — usse unit test karna aasan, yehi deterministic control flow ka asli faayda hai.
DSPy — declarative prompts
# DSPy — prompt manually nahi, behaviour declare karo
import dspy
class Answer(dspy.Signature):
"""Sawaal ka seedha, 2-line jawab do."""
question = dspy.InputField()
context = dspy.InputField()
answer = dspy.OutputField()
lm = dspy.LM("provider/model-name")
dspy.configure(lm=lm)
predict = dspy.Predict(Answer)
print(predict(question="GST kitna hai?", context="...").answer)
# Compile step: examples + metric se prompt optimize hota hai
- DSPy mein tum desired behaviour specify karte ho (signature: inputs + output) — prompt khud compile hota hai.
- Manual prompt-iteration ki jagah optimizer examples/metric se prompt ko systematically behtar karta hai — prompt likha nahi, seekha jaata hai.
- Yeh tab powerful hai jab tumhare paas eval set hai — wahi optimizer ka feedback hai (L7 ke eval lessons).
- Trade-off: naye logon ko signature/optimizer pehle samajhna padta hai; chhote app mein seedha prompt likhna aasan rehta hai.
Approach choose karna — comparison
APPROACH dev speed debug state/branch deps best for
raw SDK low-ish best manual minimal 1-3 calls, ek provider
LangChain fast mid chain-level medium multi-step, switching
graph (LangGraph) mid good excellent medium-high loops, agents, state
LlamaIndex fast mid basic medium RAG / data-heavy
DSPy mid good manual medium prompt-heavy, eval set ready
apna wrapper slow (shuru) best jitna banao zero tight control, chhota scope
- Development speed frameworks tez karte hain; debugging raw ke paas aasan — abstraction jitni kam, stack trace utni saaf.
- State management: simple chain = tuple; loops/branches = graph style; memory-wala agent = state machine.
- Portability: apna wrapper + provider-neutral messages format = vendor switch aasan; framework-specific classes = migration ka kaam.
- Dependency complexity: har framework ka apna release cycle hai — upgrades break karte hain; raw SDK ka surface chhota.
- Practical recipe: spike in raw → factor common pattern → abhi decide karo framework chahiye ya nahi.
Exercise
Question: Documents ingest karke index banakar query karne par focus karne wala framework kaunsa hai?
Question: Nodes, edges aur shared state se stateful workflow banane wala graph framework kaunsa hai?
Question: DSPy mein manually prompt likhne ki jagah kya define karte hain? (ek word)
Question: Minimal dependencies aur maximum debug control chahiye toh kaunsa approach?
Common mistakes
- LangChain ko universal standard samajhna: — woh ek approach hai. Data-heavy kaam mein LlamaIndex, loops/agents mein graph, prompt-heavy mein DSPy, chhote scope mein raw SDK — context se chuno.
- Pehle framework uthana, control flow samjhe bina: — abstraction ke neeche jo chal raha hai pata na ho toh bug nahi niklega. Pehle plain Python mein spike, phir framework.
- Linear chain ke liye graph framework laga dena: — 3 sequential calls ke liye nodes/edges over-engineering hain. Graph tabhi jab branch, loop ya restartable state ho.
- Framework ke classes mein apna core logic likh dena: — framework badalne par sab port karna padta hai. Core logic plain functions mein, framework sirf glue rakho.
Har supervisor ka apna style hai — koi checklist se chalata hai (DSPy), koi flowchart bana ke (graph), koi seedha boli leta hai (raw). Kaam wahi hai, bas control aur flexibility ka balance alag:
Checklist supervisor (DSPy) : standard procedure, kam masla
Flowchart supervisor (graph) : branch/loop clear, kuch bhi miss nahi
Boli-kar supervisor (LangChain): tez shuruaat, style uska
Khud karo (raw SDK) : poora control, sab tumhara
Canteen ka kaam simple hai toh flowchart banane ki zarurat nahi.- Q: LangChain aur LlamaIndex ka centre of gravity kya hai? — LangChain general orchestration chains; LlamaIndex data ingestion + retrieval (RAG).
- Q: Graph-based orchestration kab choose karein? — Jab branches, loops, persistent state aur explicit control flow chahiye (agents, restartable workflows).
- Q: DSPy ka core idea kya hai? — Manually prompt na likh kar signature se behaviour specify karo, optimizer se prompt compile/optimise hota hai.
- Q: Framework ka main trade-off kya hai? — Development speed vs debug control, dependencies, portability — chhote scope par raw SDK aksar jeetta hai.
Frameworks ka landscape clear. Agla lesson — capstone project — jismein streaming, tools, retries aur tracing sab mila kar ek assistant banayenge.