Download setup_and_deployment.md from PrernaKu/LegalDoc: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/spaces/PrernaKu/LegalDoc/resolve/main/setup_and_deployment.md
- Command line
-
hf download hf://spaces/PrernaKu/LegalDoc/setup_and_deployment.md
-
curl -L -o setup_and_deployment.md https://huggingface.co/spaces/PrernaKu/LegalDoc/resolve/main/setup_and_deployment.md
Multi-Agent Procurement System: Setup & Deployment Guide
Quick Start
1. Prerequisites
- Python 3.10+
- pip or poetry for dependency management
2. Installation
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
3. Configure Environment Variables
Create a .env file in the project root:
# LangChain / Anthropic Configuration
ANTHROPIC_API_KEY="sk-ant-xxx"
# LangSmith Configuration (Optional but recommended)
LANGSMITH_API_KEY="your_langsmith_key_here"
LANGSMITH_PROJECT="procurement_system"
LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
# Optional: Debugging
DEBUG=False
LOG_LEVEL="INFO"
4. Run the System
python procurement_system.py
Architecture Deep Dive
Graph Flow Diagram
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PROCUREMENT WORKFLOW β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
START
β
βΌ
ββββββββββββββββ
β ResearchNode β ββββ Vendor Search Tool
β (Agent 1) β
ββββββββ¬ββββββββ
β Returns: vendor_options[]
βΌ
ββββββββββββββββ
β AnalysisNode β ββββ Budget Validator Tool
β (Agent 2) β LLM Recommendation
ββββββββ¬ββββββββ
β
βββββββββββββββΌβββββββββββββββ
β β
Within Exceeds
Budget Budget
β β
βΌ βΌ
ββββββββββββββββ βββββββββββ
β ApprovalGate β β END β
β (Interrupts) β β REJECT β
ββββββββ¬ββββββββ βββββββββββ
β
*** GRAPH PAUSES HERE ***
External system updates:
state.human_approved = True/False
β
βΌ
ββββββββββββββββββββββ
β ApprovalDecRouter β
ββββββββββ¬ββββββββββββ
β
βββββββββΌβββββββββ
β β
Approved Rejected
β β
βΌ βΌ
βββββββββββ ββββββββββ
βLegalNodeβ β END β
β(Agent 3)β βREJECT β
ββββββ¬βββββ ββββββββββ
β
βΌ
βββββ
βENDβ (Contract generated)
βββββ
State Evolution
Initial State:
{
"procurement_request": "...",
"vendor_options": [],
"selected_vendor": {},
"budget_limit": 5500.0,
"analysis_approved": False,
"human_approved": False,
"contract_draft": "",
"logs": ["Workflow initiated"]
}
After ResearchNode:
{
# ... previous fields
"vendor_options": [
{
"vendor_id": "VENDOR_001",
"name": "CloudTech Solutions",
"price_per_month": 5000,
"capabilities": [...],
...
},
# ... more vendors
]
}
After AnalysisNode (Budget OK):
{
# ... previous fields
"selected_vendor": {
"vendor_id": "VENDOR_001",
"name": "CloudTech Solutions",
"price_per_month": 5000,
...
},
"analysis_approved": True
}
After ApprovalGate (INTERRUPTED):
Graph PAUSES at interrupt_before=["legal_node"]
Human reviews state and updates via executor.approve_vendor(approval=True)
After LegalNode:
{
# ... all previous fields
"contract_draft": "# PURCHASE AGREEMENT\n\n## Parties\n...",
"human_approved": True
}
LangSmith Integration Setup
Why LangSmith?
For a multi-agent system, observability is critical:
- Trace each LLM call: See what each agent is asking the LLM
- Track tool invocations: Log vendor search and budget validation calls
- Monitor latency: Identify bottlenecks in agent reasoning
- Debug state transitions: Understand why the graph routed to a specific node
- Audit trail: Full compliance logging for procurement decisions
Step-by-Step LangSmith Setup
1. Create LangSmith Account
- Visit: https://smith.langchain.com
- Sign up with email or GitHub
- Create organization (if needed)
2. Generate API Key
- Navigate to Settings (bottom-left profile)
- Click "API keys"
- Create new API key
- Copy the key (format:
lsk_xyz...)
3. Configure Environment
# Set environment variables
export LANGSMITH_API_KEY="lsk_your_api_key_here"
export LANGSMITH_PROJECT="procurement_system"
# Verify configuration
python -c "from langsmith import Client; c = Client(); print('β LangSmith connected')"
4. Run System with Tracing
python procurement_system.py
5. View Traces in LangSmith Dashboard
- Go to: https://smith.langchain.com/projects
- Select project: "procurement_system"
- Each workflow run appears as a trace tree showing:
- ResearchNode execution:
mock_vendor_searchtool call - AnalysisNode: LLM invocation with vendor analysis prompt
- AnalysisNode:
validate_budgettool call - Approval interruption: State checkpoint
- LegalNode: Contract generation LLM call
- ResearchNode execution:
LangSmith Dashboard Features
Traces Tab
Run #1: Procurement for "Cloud Infrastructure"
βββ ResearchNode
β βββ Tool: mock_vendor_search
β βββ Input: "cloud infrastructure"
β βββ Output: [3 vendors found]
β
βββ AnalysisNode
β βββ LLM Call: ChatAnthropic
β β βββ Tokens: 342 prompt, 198 completion
β β βββ Cost: $0.00X
β β βββ Latency: 1.23s
β βββ Tool: validate_budget
β βββ Status: APPROVED (within budget)
β
βββ ApprovalGate: INTERRUPTED
Analytics
- Agent performance: Which agent takes longest?
- LLM costs: Total spend on this project
- Tool success rate: How often do tools succeed?
- Latency breakdown: Time spent in each node
Dataset Features (for continuous improvement)
- Log LLM calls as training examples
- Create feedback loops for agent improvements
- Track prompt performance over time
Production Deployment Considerations
1. Checkpointer Upgrade
Development (current):
checkpointer = MemorySaver() # In-memory only, lost on restart
Production:
from langgraph.checkpoint.postgres import PostgresSaver
checkpointer = PostgresSaver(
conn_string="postgresql://user:password@localhost:5432/langgraph"
)
This persists all state to a database, allowing:
- Recovery from crashes
- Long-running workflows
- Concurrent workflow management
2. LLM Configuration
Development:
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022", temperature=0.3)
Production - Consider:
llm = ChatAnthropic(
model="claude-3-5-sonnet-20241022",
temperature=0.1, # Lower for consistency
max_tokens=4096,
timeout=30,
max_retries=3 # Retry failed calls
)
3. Tool Enhancements
Mock tools (current):
@tool
def mock_vendor_search(query: str) -> list[dict]:
# Returns hardcoded data
Production - Real implementations:
@tool
def real_vendor_search(query: str) -> list[dict]:
"""Search live vendor database or API."""
response = requests.get(
"https://vendor-api.example.com/search",
params={"q": query}
)
return response.json()
@tool
def real_budget_validator(vendor_id: str, budget: float) -> dict:
"""Query actual ERP system for budget allocation."""
erp = ERPClient(api_key=os.getenv("ERP_API_KEY"))
allocation = erp.get_budget_allocation()
return {"within_budget": allocation >= budget}
4. Error Handling & Resilience
def research_node(state: ProcurementState) -> Command:
"""Enhanced with error handling."""
try:
vendors = self.vendor_search_tool(state["procurement_request"])
if not vendors:
raise ValueError("No vendors found for request")
except Exception as e:
new_log = f"ERROR in ResearchNode: {str(e)}"
return Command(
update={"logs": [new_log]},
goto=END # Graceful failure
)
return Command(
update={"vendor_options": vendors, "logs": [...]},
goto="analysis_node"
)
5. Approval Gate Enhancement
Current (manual):
state_update = {"human_approved": True}
self.graph.update_state(config, state_update)
Production (with workflow engine):
# Integrate with Slack bot, email approval link, web dashboard
async def wait_for_human_approval(thread_id: str, timeout_seconds=86400):
"""Poll approval status from database."""
while True:
approval = db.get_approval_status(thread_id)
if approval is not None:
return approval
await asyncio.sleep(60)
6. Logging & Monitoring
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# In each node:
logger.info(f"ResearchNode: Processing request: {request}")
logger.info(f"AnalysisNode: Budget validation completed: {validation}")
7. Async Execution
# For long-running workflows, use async execution
from langgraph.types import StreamMode
async def run_async():
config = {"configurable": {"thread_id": thread_id}}
async for event in graph.astream(initial_state, config):
logger.info(f"Event: {event}")
Troubleshooting
Issue: Graph doesn't pause at approval_gate
Cause: interrupt_before=["legal_node"] pauses before legal_node, not at approval_gate.
Solution: Current design is correct. The graph pauses when it reaches the logical point before executing legal_node (which only runs if approved).
Issue: State not persisting across restarts
Cause: Using MemorySaver (in-memory only).
Solution: Upgrade to PostgresSaver for production:
pip install "langgraph[postgres]"
Issue: LLM calls not appearing in LangSmith
Cause: LANGSMITH_API_KEY not set.
Solution:
export LANGSMITH_API_KEY="your_key"
echo $LANGSMITH_API_KEY # Verify it's set
python procurement_system.py
Issue: Vendor search returns empty list
Cause: Query doesn't match mock data keywords.
Solution: Use "cloud" or "software" in procurement request:
executor.start_workflow(
procurement_request="We need enterprise cloud infrastructure", # β Works
budget_limit=5000
)
Testing the System
Unit Test Example
import pytest
from procurement_system import ProcurementAgents, ProcurementState
@pytest.fixture
def llm():
from langchain_anthropic import ChatAnthropic
return ChatAnthropic(model="claude-3-5-sonnet-20241022")
def test_research_node(llm):
agents = ProcurementAgents(llm)
state = ProcurementState(
procurement_request="cloud infrastructure",
vendor_options=[],
selected_vendor={},
budget_limit=5000,
analysis_approved=False,
human_approved=False,
contract_draft="",
logs=[]
)
result = agents.research_node(state)
assert len(result.update["vendor_options"]) > 0
assert result.goto == "analysis_node"
def test_analysis_node_budget_exceeded(llm):
agents = ProcurementAgents(llm)
state = ProcurementState(
procurement_request="",
vendor_options=[{"name": "Expensive", "price_per_month": 10000}],
selected_vendor={},
budget_limit=1000,
analysis_approved=False,
human_approved=False,
contract_draft="",
logs=[]
)
result = agents.analysis_node(state)
assert result.goto == END
assert result.update["analysis_approved"] == False
# Run tests
pytest test_procurement.py -v
Next Steps
- Test locally with mock tools
- Integrate real tools: Connect to actual vendor APIs
- Deploy checkpointer: Use PostgreSQL for state persistence
- Add web UI: Build frontend for approval gate (Streamlit, FastAPI + React)
- Monitor in LangSmith: Track performance and costs
- Add compliance logging: Audit trail for procurement regulations