This section provides a practical exercise in building a foundational LLM agent with a specific role and function. We will apply several principles discussed earlier in this chapter, such as defining an agent's persona, specialized function, and integrating basic tool usage. Our goal is to construct a "Web Content Summarizer" agent that can fetch information from a given URL, summarize it, and extract its main topics.
Before writing any code, let's clearly define our agent:
requests
and BeautifulSoup4
).This agent, while simple, demonstrates the core idea of giving an LLM-powered entity a specific job description and the means to accomplish it.
Ensure you have the following Python libraries installed:
pip install openai requests beautifulsoup4
You will also need an OpenAI API key. It's best practice to set this as an environment variable:
export OPENAI_API_KEY='your_api_key_here'
Remember that this hands-on exercise assumes your development environment is configured as outlined in Chapter 1.
Let's build our WebSummarizerAgent
step by step.
First, we'll import the necessary modules and set up our OpenAI client.
import os
import requests
from bs4 import BeautifulSoup
from openai import OpenAI
# Initialize the OpenAI client
# It will automatically pick up the OPENAI_API_KEY environment variable
try:
client = OpenAI()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
print("Please ensure your OPENAI_API_KEY environment variable is set correctly.")
exit()
# Configuration for the LLM
LLM_MODEL = "gpt-3.5-turbo"
Using gpt-3.5-turbo
provides a good balance of capability and cost for this task. You could substitute other models as needed.
Our agent needs to retrieve content from a URL. We'll create a function for this.
def fetch_web_content(url: str) -> str:
"""
Fetches and extracts text content from a given URL.
Returns the text content or an error message.
"""
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status() # Raises an HTTPError for bad responses (4XX or 5XX)
soup = BeautifulSoup(response.content, 'html.parser')
# Extract text from common content tags, attempt to get main content
paragraphs = soup.find_all(['p', 'article', 'main'])
if not paragraphs: # Fallback for simpler pages
paragraphs = soup.find_all('body')
text_content = ""
for p_tag in paragraphs:
text_content += p_tag.get_text(separator=' ', strip=True) + "\n"
# Basic cleaning: reduce multiple newlines and spaces
text_content = '\n'.join([line.strip() for line in text_content.splitlines() if line.strip()])
text_content = ' '.join(text_content.split())
# Limit content length to avoid excessive token usage
# This is a simple truncation; more sophisticated chunking might be needed for very long articles
max_length = 15000 # Approximately 4k tokens, depends on text
return text_content[:max_length]
except requests.exceptions.RequestException as e:
return f"Error fetching URL {url}: {e}"
except Exception as e:
return f"Error processing content from {url}: {e}"
This fetch_web_content
function attempts to grab the main textual parts of a webpage. Real-world web scraping can be much more complex, often requiring site-specific parsers, but this provides a general approach. The content is truncated to prevent excessively long inputs to the LLM.
Now, we'll define the agent's main processing function. This function will orchestrate fetching content and then using the LLM for summarization and topic extraction.
def process_url_with_agent(url: str) -> dict:
"""
Orchestrates fetching web content, summarizing, and extracting topics.
"""
print(f"Processing URL: {url}...")
content = fetch_web_content(url)
if content.startswith("Error"):
return {"error": content}
if not content.strip():
return {"error": "No text content found at the URL."}
# Persona and instruction for the LLM
system_prompt = (
"You are a diligent Research Assistant. "
"Your purpose is to process the provided web article text, "
"generate a concise summary, and identify 3-5 main topics. "
"Format your response as a JSON object with two keys: 'summary' and 'main_topics' (a list of strings)."
)
user_prompt = f"Please process the following web article content:\n\n{content}"
try:
response = client.chat.completions.create(
model=LLM_MODEL,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.3, # Lower temperature for more factual and less creative output
response_format={"type": "json_object"} # Request JSON output
)
# The response content should be a JSON string.
# We'll parse it directly.
assistant_reply = response.choices[0].message.content
# Basic validation if needed before parsing, or rely on OpenAI's JSON mode
import json
result = json.loads(assistant_reply)
return result
except Exception as e:
return {"error": f"LLM processing error: {e}"}
In process_url_with_agent
, we first fetch the content. Then, we construct a system prompt that clearly defines the agent's persona and task, crucially instructing it to return a JSON object. This structured output is easier to parse and use in a larger system. The user prompt provides the actual content. We use OpenAI's JSON mode for reliable structured output.
A simple diagram illustrates the flow of our agent:
The agent takes a URL, fetches its content, processes it with an LLM, and produces a summary and list of topics.
Let's test our agent with a sample URL.
if __name__ == "__main__":
# Example usage:
# Replace with a URL of your choice, preferably an article.
# Be mindful of website terms of service regarding scraping.
test_url = "https://www.nature.com/articles/d41586-023-03913-3" # Example: A Nature news article
print(f"Constructing agent to process: {test_url}")
agent_output = process_url_with_agent(test_url)
if "error" in agent_output:
print(f"\nAgent Error: {agent_output['error']}")
else:
print("\nAgent Output:")
print(f" Summary: {agent_output.get('summary', 'Not available')}")
topics = agent_output.get('main_topics', [])
if topics:
print(" Main Topics:")
for i, topic in enumerate(topics):
print(f" {i+1}. {topic}")
else:
print(" Main Topics: Not available")
When you run this script, replace test_url
with a current news article or blog post. The agent will fetch the content, send it to the LLM with the specified persona and instructions, and print the resulting summary and topics.
Example Output (will vary based on the URL and LLM's response):
Processing URL: https://www.nature.com/articles/d41586-023-03913-3...
Agent Output:
Summary: The article discusses the challenges and advancements in detecting gravitational waves from merging supermassive black holes. While individual detections are difficult, projects like NANOGrav are using pulsar timing arrays to search for a background hum of these waves. Recent findings suggest a signal consistent with this background, though more data is needed for confirmation. Detecting these waves would provide insights into galaxy evolution and the formation of massive structures in the universe.
Main Topics:
1. Gravitational Wave Detection
2. Supermassive Black Hole Mergers
3. Pulsar Timing Arrays (e.g., NANOGrav)
4. Galaxy Evolution
5. Cosmological Background Radiation
This hands-on exercise demonstrated the construction of a simple LLM agent with a defined role, function, and a basic tool (web fetching). We saw how system prompts can establish the agent's persona and guide its output format.
Connections to Chapter Concepts:
fetch_web_content
function acts as a simple, integrated tool. More sophisticated agents might use formal tool registration and calling mechanisms, as discussed in "Integrating External Tools and Functions for Agents."Potential Enhancements:
This foundational agent serves as a building block. As you progress, you'll learn to combine multiple such specialized agents, orchestrate their interactions, and manage complex workflows to tackle more demanding problems. This exercise should give you a concrete understanding of how individual agent architecture contributes to the capabilities of a larger multi-agent system.
Was this section helpful?
© 2025 ApX Machine Learning