diff --git a/langgraph-crusoe/.gitignore b/langgraph-crusoe/.gitignore new file mode 100644 index 0000000..0a16c91 --- /dev/null +++ b/langgraph-crusoe/.gitignore @@ -0,0 +1,4 @@ +.env +__pycache__/ +*.pyc +.DS_Store diff --git a/langgraph-crusoe/README.md b/langgraph-crusoe/README.md new file mode 100644 index 0000000..f0713cc --- /dev/null +++ b/langgraph-crusoe/README.md @@ -0,0 +1,85 @@ +# LangGraph × Crusoe AI + +Run multi-step agentic pipelines on [Crusoe Managed Inference](https://www.crusoe.ai/cloud/managed-inference) using LangGraph — ultra-low latency, powered by MemoryAlloy™. + +## What this does + +A 3-node research pipeline built with LangGraph: +Research → Analysis → Summarize + +Each node calls Crusoe Managed Inference independently. LangGraph manages state between nodes — no manual plumbing required. + +## Prerequisites + +- Python 3.10+ +- A Crusoe Cloud account → [console.crusoecloud.com](https://console.crusoecloud.com) +- Inference API key (Intelligence API Keys section under Security in the console) + +## Setup + +```bash +pip install -r requirements.txt +export CRUSOE_API_KEY="your-api-key" +``` + +## Run the example + +```bash +python examples/research_agent.py +``` + +## Local testing (no Crusoe account needed) + +The agent automatically falls back to Groq if `CRUSOE_API_KEY` is not set. Groq is free and OpenAI-compatible — identical behavior. + +```bash +pip install langchain-groq +export GROQ_API_KEY="your-groq-key" # free at console.groq.com +python examples/research_agent.py +``` + +## How it works + +```python +from agent import run_research_agent + +result = run_research_agent("GPU memory optimization for LLM inference") +print(result["summary"]) +``` + +The graph wires three nodes together: + +| Node | Role | +|------|------| +| `research` | Gathers key facts about the topic | +| `analysis` | Extracts 3 insights and open questions | +| `summarize` | Produces a clean 3-paragraph summary | + +## Swap the model + +Change the model string in `agent.py` to any model available on [Crusoe Intelligence Foundry](https://console.crusoecloud.com/foundry/models): + +```python +return ChatCrusoe( + model="deepseek-ai/DeepSeek-R1-0528", + temperature=0.3, + max_tokens=1024, +) +``` + +## Extend the pipeline + +Add nodes to the graph in `agent.py`: + +```python +graph.add_node("fact_check", fact_check_node) +graph.add_edge("analysis", "fact_check") +graph.add_edge("fact_check", "summarize") +``` + +LangGraph handles state passing. You just write the node logic. + +## Related + +- [langchain-crusoe](../langchain-crusoe/) — LangChain integration for Crusoe Managed Inference +- [Crusoe Managed Inference Docs](https://docs.crusoecloud.com/managed-inference/overview) diff --git a/langgraph-crusoe/agent.py b/langgraph-crusoe/agent.py new file mode 100644 index 0000000..e23e7af --- /dev/null +++ b/langgraph-crusoe/agent.py @@ -0,0 +1,102 @@ +""" +LangGraph multi-node research agent. +Designed for Crusoe Managed Inference (OpenAI-compatible). +Tested locally with Groq as a drop-in replacement. +""" +from typing import TypedDict, Annotated +from langgraph.graph import StateGraph, END +from langgraph.graph.message import add_messages +from langchain_core.messages import HumanMessage, SystemMessage + + +class AgentState(TypedDict): + messages: Annotated[list, add_messages] + topic: str + analysis: str + summary: str + + +def get_llm(): + """ + Returns a ChatCrusoe instance for production use. + For local testing, we use ChatGroq as a drop-in replacement + since both are OpenAI-compatible. + """ + import os + if os.getenv("CRUSOE_API_KEY"): + from langchain_crusoe import ChatCrusoe + return ChatCrusoe( + model="meta-llama/Llama-3.3-70B-Instruct", + temperature=0.3, + max_tokens=1024, + ) + else: + from langchain_groq import ChatGroq + return ChatGroq( + model="llama-3.3-70b-versatile", + temperature=0.3, + max_tokens=1024, + ) + + +def research_node(state: AgentState) -> AgentState: + """Node 1: gather key facts about the topic.""" + llm = get_llm() + response = llm.invoke([ + SystemMessage(content="You are a research assistant. Gather key facts and context about the given topic. Be thorough and factual."), + HumanMessage(content=f"Research this topic and return key facts: {state['topic']}") + ]) + return {"messages": [response]} + + +def analysis_node(state: AgentState) -> AgentState: + """Node 2: analyze the research and extract insights.""" + llm = get_llm() + prior_research = state["messages"][-1].content + response = llm.invoke([ + SystemMessage(content="You are an analyst. Given research notes, identify the 3 most important insights and any open questions."), + HumanMessage(content=f"Analyze this research:\n\n{prior_research}") + ]) + return {"messages": [response], "analysis": response.content} + + +def summarize_node(state: AgentState) -> AgentState: + """Node 3: produce a clean, concise final summary.""" + llm = get_llm() + response = llm.invoke([ + SystemMessage(content="You are a writer. Produce a clear, 3-paragraph summary from the analysis provided. Use plain language."), + HumanMessage(content=f"Summarize this analysis:\n\n{state['analysis']}") + ]) + return {"messages": [response], "summary": response.content} + + +def build_research_graph(): + """Build and compile the 3-node research graph.""" + graph = StateGraph(AgentState) + + graph.add_node("research", research_node) + graph.add_node("analysis", analysis_node) + graph.add_node("summarize", summarize_node) + + graph.set_entry_point("research") + graph.add_edge("research", "analysis") + graph.add_edge("analysis", "summarize") + graph.add_edge("summarize", END) + + return graph.compile() + + +def run_research_agent(topic: str) -> dict: + """Run the full pipeline on a topic.""" + graph = build_research_graph() + result = graph.invoke({ + "topic": topic, + "messages": [], + "analysis": "", + "summary": "" + }) + return { + "topic": topic, + "analysis": result["analysis"], + "summary": result["summary"], + } diff --git a/langgraph-crusoe/examples/research_agent.py b/langgraph-crusoe/examples/research_agent.py new file mode 100644 index 0000000..29ca3ee --- /dev/null +++ b/langgraph-crusoe/examples/research_agent.py @@ -0,0 +1,35 @@ +""" +Example: Run the LangGraph research agent on Crusoe Managed Inference. + +For production (Crusoe): + export CRUSOE_API_KEY="your-api-key" + +For local testing (Groq - free): + export GROQ_API_KEY="your-groq-key" + +Then run: + python examples/research_agent.py +""" +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from dotenv import load_dotenv +load_dotenv() + +from agent import run_research_agent + +if __name__ == "__main__": + topic = "GPU memory optimization techniques for large language model inference" + + print(f"\nTopic: {topic}") + print("=" * 60) + print("Running 3-node LangGraph pipeline: Research → Analysis → Summarize") + print("=" * 60) + + result = run_research_agent(topic) + + print("\n📊 ANALYSIS:") + print(result["analysis"]) + print("\n📝 SUMMARY:") + print(result["summary"]) diff --git a/langgraph-crusoe/requirements.txt b/langgraph-crusoe/requirements.txt new file mode 100644 index 0000000..5588dc6 --- /dev/null +++ b/langgraph-crusoe/requirements.txt @@ -0,0 +1,6 @@ +langchain-crusoe>=0.1.0 +langgraph>=0.2.0 +langchain-core>=0.3.0 +langchain-openai>=0.1.0 +python-dotenv +groq