chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Summary Generator multi-agent workflow with ACP
|
||||
|
||||
A simple demonstration of the Agent Communication Protocol (ACP), showcasing how two agents built using different frameworks (CrewAI and Smolagents) can collaborate seamlessly to generate and verify a research summary.
|
||||
|
||||
---
|
||||
|
||||
## Setup and Installation
|
||||
|
||||
1. **Install Ollama:**
|
||||
```bash
|
||||
# Setting up Ollama on linux
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
|
||||
# Pull the Qwen2.5 model
|
||||
ollama pull qwen2.5:14b
|
||||
```
|
||||
|
||||
2. **Install project dependencies:**
|
||||
|
||||
Ensure you have Python 3.10 or later installed on your system.
|
||||
|
||||
First, install `uv` and set up the environment:
|
||||
```bash
|
||||
# MacOS/Linux
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Windows
|
||||
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
||||
```
|
||||
|
||||
Install dependencies:
|
||||
```bash
|
||||
# Create a new directory for our project
|
||||
uv init acp-project
|
||||
cd acp-project
|
||||
|
||||
# Create virtual environment and activate it
|
||||
uv venv
|
||||
source .venv/bin/activate # MacOS/Linux
|
||||
|
||||
.venv\Scripts\activate # Windows
|
||||
|
||||
# Install dependencies
|
||||
uv add acp-sdk crewai smolagents duckduckgo-search ollama
|
||||
```
|
||||
|
||||
You can also use any other LLM providers such as OpenAI or Anthropic. Create a `.env` file and add your API keys
|
||||
```
|
||||
OPENAI_API_KEY=your_openai_key
|
||||
ANTHROPIC_API_KEY=your_anthropic_key
|
||||
```
|
||||
|
||||
## Usage
|
||||
Start the two ACP servers in separate terminals:
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
uv run crew_acp_server.py
|
||||
|
||||
# Terminal 2
|
||||
uv run smolagents_acp_server.py
|
||||
```
|
||||
|
||||
Run the ACP client to trigger the agent workflow:
|
||||
|
||||
```bash
|
||||
uv run acp_client.py
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
A general summary from the first agent
|
||||
|
||||
A fact-checked and updated version from the second agent
|
||||
|
||||
## 📬 Stay Updated with Our Newsletter!
|
||||
**Get a FREE Data Science eBook** 📖 with 150+ essential lessons in Data Science when you subscribe to our newsletter! Stay in the loop with the latest tutorials, insights, and exclusive resources. [Subscribe now!](https://join.dailydoseofds.com)
|
||||
|
||||
[](https://join.dailydoseofds.com)
|
||||
|
||||
---
|
||||
|
||||
## Contribution
|
||||
|
||||
Contributions are welcome! Please fork the repository and submit a pull request with your improvements.
|
||||
@@ -0,0 +1,24 @@
|
||||
import asyncio
|
||||
from acp_sdk.client import Client
|
||||
|
||||
async def run_workflow() -> None:
|
||||
async with Client(base_url="http://localhost:8000") as drafter, \
|
||||
Client(base_url="http://localhost:8001") as verifier:
|
||||
topic = "Impact of climate change on agriculture in 2025."
|
||||
|
||||
response1 = await drafter.run_sync(
|
||||
agent="research_drafter",
|
||||
input=topic
|
||||
)
|
||||
draft = response1.output[0].parts[0].content
|
||||
print(f"\nDraft Summary:\n{draft}")
|
||||
|
||||
response2 = await verifier.run_sync(
|
||||
agent="research_verifier",
|
||||
input=f"Enhance the following research summary using the latest information available online providing a more accurate and updated version:\n{draft}"
|
||||
)
|
||||
final_summary = response2.output[0].parts[0].content
|
||||
print(f"\nVerified & Enriched Summary:\n{final_summary}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_workflow())
|
||||
@@ -0,0 +1,36 @@
|
||||
from collections.abc import AsyncGenerator
|
||||
from acp_sdk.models import Message, MessagePart
|
||||
from acp_sdk.server import RunYield, RunYieldResume, Server
|
||||
from crewai import Crew, Task, Agent, LLM
|
||||
|
||||
server = Server()
|
||||
|
||||
llm = LLM(
|
||||
model="ollama_chat/qwen2.5:14b",
|
||||
base_url="http://localhost:11434",
|
||||
max_tokens=8192
|
||||
)
|
||||
|
||||
@server.agent()
|
||||
async def research_drafter(input: list[Message]) -> AsyncGenerator[RunYield, RunYieldResume]:
|
||||
"""Agent that creates a general research summary on a given topic."""
|
||||
|
||||
agent = Agent(
|
||||
role="Research summarizer",
|
||||
goal="Draft an informative and structured research summary based on the topic",
|
||||
backstory="You are a researcher who summarizes complex topics for general readers.",
|
||||
llm=llm
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description=f"Write a brief, clear summary on: {input[0].parts[0].content}",
|
||||
expected_output="A concise paragraph summarizing the topic",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
crew = Crew(agents=[agent], tasks=[task])
|
||||
task_output = await crew.kickoff_async()
|
||||
yield Message(parts=[MessagePart(content=str(task_output))])
|
||||
|
||||
if __name__ == "__main__":
|
||||
server.run(port=8000)
|
||||
@@ -0,0 +1,30 @@
|
||||
from collections.abc import AsyncGenerator
|
||||
from acp_sdk.models import Message, MessagePart
|
||||
from acp_sdk.server import RunYield, RunYieldResume, Server
|
||||
from smolagents import CodeAgent, LiteLLMModel, DuckDuckGoSearchTool
|
||||
import warnings
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
server = Server()
|
||||
|
||||
model = LiteLLMModel(
|
||||
model_id="ollama_chat/qwen2.5:14b",
|
||||
api_base="http://localhost:11434",
|
||||
# api_key="your-api-key",
|
||||
num_ctx=8192
|
||||
)
|
||||
|
||||
@server.agent()
|
||||
async def research_verifier(input: list[Message]) -> AsyncGenerator[RunYield, RunYieldResume]:
|
||||
"""Agent that fact-checks and enhances a research summary using web search."""
|
||||
|
||||
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=model)
|
||||
|
||||
prompt = input[0].parts[0].content
|
||||
response = agent.run(prompt)
|
||||
|
||||
yield Message(parts=[MessagePart(content=str(response))])
|
||||
|
||||
if __name__ == "__main__":
|
||||
server.run(port=8001)
|
||||
Reference in New Issue
Block a user