Capstone Local Document Answering Agent
توسعه عاملهای هوشمند (Agentic Ai) با Langchain و Langgraph
- Integrate local document ingestion, indexing, retrieval, citations, short-term memory, long-term memory, and mixed tools.
- Orchestrate a multi-step agent with routing, verification, bounded repair, and human approval for consequential actions.
- Run, trace, evaluate, and debug the complete system locally.
از اجزا تا سامانه کامل
## هدف نهایی
ساخت و اجرای یک **Capstone Local Document Answering Agent** در محیط محلی
- ورودی: فایلهای محلی + پرسش کاربر
- خروجی: پاسخ مستند با citation، حافظه و گزارش ارزیابی
- ابزارها: دستکم `retriever` و `calculator`
- کنترل: routing → retrieval → answer → verify → bounded repair → approval
**مثال کامل مسیر:** برای پرسش «هزینه 3 مورد با قیمت 12 چیست؟»:
1. `retriever` قطعه `catalog.txt` را پیدا میکند.
2. `calculator` محاسبه میکند: \(3 \times 12 = 36\).
3. عامل پاسخ `36` را با citation همان قطعه برمیگرداند.
4. `verifier` پشتیبانی عدد و citation را بررسی میکند.
**Builds on ←** `8.3`–`8.5`: Answer Verification and Repair Loops، Subgraphs and Specialized Subagents، Parallel Work and Result Aggregation
**Where this leads →** `9.2`–`9.4`: Agent Evaluation and Regression Testing، Reliability Patterns for Agent Workflows، Local LangGraph Project and Development Server
```mermaid
flowchart LR
A["Local files"] --> B["Ingest and index"]
B --> C["Route question"]
C --> D["Retrieve"]
D --> E["Answer with citations"]
E --> F{"Verify"}
F -->|"pass"| G["Return"]
F -->|"fail; budget remains"| H["Repair"]
H --> E
F -->|"consequential action"| I["Human approval"]
```
قرارداد داده و حافظه
## State مرکزی
```python
class State(TypedDict):
question: str
documents: list[str]
answer: str
citations: list[str]
verified: bool
repair_count: int
thread_id: str
```
- `documents`: قطعههای بازیابیشده از فایلهای محلی
- `citations`: شناسه فایل و بازه قطعه، نه حدس مدل
- `repair_count`: شمارنده برای پایان قطعی حلقه
- `thread_id`: کلید حافظه کوتاهمدت هر گفتوگو
**مثال داده:** اگر قطعه بازیابیشده `catalog.txt:12–14` و متن آن `item=service, price=12` باشد، مقدار citation باید همان `catalog.txt:12–14` بماند؛ مدل نباید شناسه تازه بسازد.
```mermaid
flowchart TD
Q["question"] --> R["retriever"]
R --> D["documents + metadata"]
D --> A["answer node"]
A --> C["answer + citations"]
C --> V["verification"]
M["thread memory"] --> A
```
**Builds on ←** `8.4`: Subgraphs and Specialized Subagents؛ هر node بخش مشخصی از State را میخواند یا بهروزرسانی میکند.
**Where this leads →** `9.3` و `9.4`: Reliability Patterns for Agent Workflows و Local LangGraph Project and Development Server
پیادهسازی عامل محلی
## مسیر اجرایی نمونه
```python
from langgraph.graph import StateGraph, START, END
from langchain.agents import create_agent
agent = create_agent(model=model, tools=[retriever_tool, calculator_tool])
def call_agent(state: State) -> dict:
context = "\n\n".join(state["documents"])
prompt = f"Context:\n{context}\n\nQuestion: {state['question']}"
result = agent.invoke({"messages": [{"role": "user", "content": prompt}]})
answer = result["messages"][-1].content
return {"answer": answer}
workflow = StateGraph(State)
workflow.add_node("retrieve", retrieve)
workflow.add_node("agent", call_agent)
workflow.add_edge(START, "retrieve")
workflow.add_edge("retrieve", "agent")
workflow.add_edge("agent", END)
graph = workflow.compile()
```
### اجرای کامل با عددهای مشخص
```python
result = graph.invoke({
"question": "هزینه 3 مورد با قیمت 12 چیست؟",
"documents": ["catalog.txt: item=service, price=12"],
"answer": "",
"citations": [],
"verified": False,
"thread_id": "thread-01",
"repair_count": 0
})
```
1. ورودی شامل پرسش، سند و مقدارهای اولیه است.
2. `retrieve` سند و metadata را آماده میکند.
3. `calculator` مرحله عددی را انجام میدهد: \(3 \times 12 = 36\).
4. عامل پاسخ را میسازد: «هزینه برابر 36 است.»
5. citation باید `catalog.txt` باشد؛ calculator منبع این ادعا نیست.
کنترل، verification و approval
## گراف bounded
```mermaid
flowchart TD
S["START"] --> R["route"]
R --> T["retrieve"]
T --> A["answer"]
A --> V["verify citations and support"]
V -->|"verified"| E["END"]
V -->|"not verified"| B{"repair_count < 2?"}
B -->|"yes"| P["repair"]
P --> C["increase repair_count"]
C --> A
B -->|"no"| F["fail safely"]
A -->|"side effect"| H["human approval"]
H -->|"approved"| X["execute tool"]
H -->|"rejected"| F
```
## شرط تصمیم
- اگر `verified = True` → پاسخ نهایی
- اگر `verified = False` و `repair_count < 2` → تعمیر، سپس افزایش شمارنده
- اگر `repair_count = 2` → توقف امن، بدون ادعای جدید
**مثال مرزیِ کامل:** citation ناموجود → `verified = False` و `repair_count = 0`؛ repair اول → `repair_count = 1`؛ repair دوم → `repair_count = 2`؛ اگر هنوز citation معتبر نیست، `fail safely`.
**محدودیت:** ابزار بیشتر لزوماً قابلیت بیشتر نیست؛ هر tool schema، هزینه و مسیر خطای بیشتری میآورد.
**Builds on ←** `8.3` و `9.3`: Answer Verification and Repair Loops و Reliability Patterns for Agent Workflows
**Where this leads →** الگوی human approval برای actionهای consequential در پروژه محلی `9.4`
حافظه، tracing و اجرای محلی
## دو نوع حافظه
- کوتاهمدت: پیامهای همان thread با `thread_id`
- بلندمدت: ترجیح یا واقعیت پایدار در store جداگانه
- citation همیشه از سند بازیابیشده میآید؛ حافظه منبع سند نیست.
```python
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
graph = workflow.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "thread-01"}}
first = graph.invoke({"question": "نام پروژه چیست?"}, config)
second = graph.invoke({"question": "همان را با citation بگو."}, config)
```
**مثال نتیجه:** اگر پاسخ اول «پروژه آلفا» باشد، پرسش دوم میتواند به «همان» ارجاع دهد؛ اما citation پاسخ دوم باید دوباره از سند بازیابیشده بررسی شود.
### مشاهده اجرا
```python
import mlflow
mlflow.set_experiment("Local Document Agent")
mlflow.langchain.autolog()
```
```mermaid
flowchart LR
D["langgraph dev"] --> T["trace locally"]
T --> E["evaluate test set"]
E --> G{"regression?"}
G -->|"no"| U["validate"]
G -->|"yes"| X["inspect failing trace"]
X --> D
```
**Builds on ←** `9.2`، `9.3` و `9.4`: Agent Evaluation and Regression Testing، Reliability Patterns for Agent Workflows و Local LangGraph Project and Development Server
ارزیابی و تعریف پایان
## test set نماینده
برای هر نمونه ثبت کن:
- `question`
- `expected_answer`
- `required_citations`
- `requires_tool`
- `expected_route`
### محاسبه صریح معیارها
فرض: `8` پرسش؛ `6` پاسخ درست؛ `7` پاسخ دارای citation معتبر؛ `5` پاسخ با route درست.
الف) دقت پاسخ:
\[
\frac{6}{8}=0.75=75\%
\]
ب) نرخ citation معتبر:
\[
\frac{7}{8}=0.875=87.5\%
\]
ج) دقت routing:
\[
\frac{5}{8}=0.625=62.5\%
\]
**تفسیر مثال:** ممکن است یک پاسخ درست باشد اما citation نداشته باشد؛ بنابراین این سه معیار باید جدا گزارش شوند.
**گزارش نهایی:** معیارها، trace شکستها، تعداد repair، latency و هزینه
## تعریف «کامل»
پاسخ خوبِ تنها کافی نیست؛ سامانه باید اجراپذیر، مستند، حافظهدار، bounded، قابل trace و روی test set ارزیابیشده باشد.
**Where this leads →** استفاده از Subgraphs and Specialized Subagents و Parallel Work and Result Aggregation در سامانههای بزرگتر
Back to course