Skip to content

Commit 97c28f6

Browse files
authored
Merge pull request #41 from debuggerone/examples
add binary classify agent + example and add separate examples documentation
2 parents 994d25f + 002b35a commit 97c28f6

File tree

5 files changed

+178
-33
lines changed

5 files changed

+178
-33
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ For more detailed information, please refer to the [INSTALL.md](INSTALL.md) file
2424

2525
## Examples
2626

27+
You can find more detailed examples in our [Examples Documentation](docs/EXAMPLES.md).
28+
2729
### Example 1: Filter List
2830

2931
Run the **filter list** example to see how AgentM filters a list of items based on whether they are considered healthy snacks:
@@ -101,4 +103,4 @@ Thus, the final answer is:
101103
\[
102104
\sqrt{144} = 12
103105
\]
104-
```
106+
```

docs/EXAMPLES.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# AgentM Examples
2+
3+
This document contains detailed examples of how to use the micro-agents in AgentM. Here, we walk through practical use cases and outputs to help you understand how the library functions in various scenarios.
4+
5+
For more general information and a quick overview, refer to the [README](../README.md).
6+
7+
## Example 1: Filter List
8+
9+
Run the **filter list** example to see how AgentM filters a list of items based on whether they are considered healthy snacks:
10+
11+
```bash
12+
python examples/filter_list_example.py
13+
```
14+
15+
### Sample Output:
16+
```bash
17+
Original list: ['Apple', 'Chocolate bar', 'Carrot', 'Chips', 'Orange']
18+
19+
Filtered results:
20+
21+
{'explanation': 'The apple is a healthy snack option, as it is low in calories, rich in fiber, and provides essential vitamins such as vitamin C.', 'remove_item': False}
22+
{'explanation': 'A chocolate bar is generally considered an unhealthy snack because it is high in sugar and saturated fats, which can contribute to weight gain and other health issues if consumed in excess.', 'remove_item': True}
23+
{'explanation': 'Carrots are a healthy snack option, as they are low in calories, high in fiber, and rich in vitamins and minerals.', 'remove_item': False}
24+
{'explanation': 'Chips are typically high in unhealthy fats, sodium, and calories, making them a less nutritious snack choice...', 'remove_item': True}
25+
{'explanation': 'The orange is a healthy snack option, as it is low in calories and high in vitamin C and dietary fiber, making it a nutritious choice.', 'remove_item': False}
26+
27+
Final Filtered List: ['Apple', 'Carrot', 'Orange']
28+
```
29+
30+
## Example 2: Sort List
31+
32+
Run the **sort list** example to see how AgentM sorts a list of items using LLM intelligence:
33+
34+
```bash
35+
python examples/sort_list_example.py
36+
```
37+
38+
### Sample Output:
39+
```bash
40+
2024-09-11 10:46:22,401 - INFO - Sending batch comparison request with prompt: Compare Apple and Orange and return the items in the correct order as 'item1,item2'.
41+
2024-09-11 10:46:22,729 - INFO - Received response: Apple,Orange
42+
2024-09-11 10:46:22,730 - INFO - Sending batch comparison request with prompt: Compare Grape and Pineapple and return the items in the correct order as 'item1,item2'.
43+
2024-09-11 10:46:23,094 - INFO - Received response: Grape,Pineapple
44+
2024-09-11 10:46:23,094 - INFO - Sending batch comparison request with prompt: Compare Banana and Grape and return the items in the correct order as 'item1,item2'.
45+
2024-09-11 10:46:23,539 - INFO - Received response: Banana,Grape
46+
2024-09-11 10:46:23,540 - INFO - Sending batch comparison request with prompt: Compare Apple and Banana and return the items in the correct order as 'item1,item2'.
47+
Compare Orange and Grape and return the items in the correct order as 'item1,item2'.
48+
2024-09-11 10:46:24,067 - INFO - Received response: Apple,Banana
49+
Grape,Orange
50+
Original list: ['Apple', 'Orange', 'Banana', 'Grape', 'Pineapple']
51+
Sorted list: ['Apple', 'Banana', 'Orange', 'Grape', 'Pineapple']
52+
```
53+
54+
## Example 3: Chain of Thought
55+
56+
Run the **chain of thought** example to see how AgentM solves problems using a step-by-step reasoning approach:
57+
58+
```bash
59+
python examples/chain_of_thought_example.py
60+
```
61+
62+
### Sample Output:
63+
```bash
64+
Question: What is the square root of 144?
65+
Chain of Thought Reasoning: To find the square root of 144 step-by-step, follow these steps:
66+
67+
1. **Understanding Square Roots**: The square root of a number is a value that, when multiplied by itself, gives that number. For example, if x is the square root of y, then x * x = y.
68+
69+
2. **Identifying the Number**: In this case, we need to find the square root of 144.
70+
71+
3. **Finding Factors**: We'll look for a number that, when multiplied by itself, equals 144.
72+
73+
4. **Testing Numbers**:
74+
- Let's start with smaller numbers:
75+
- 12 * 12 = 144 (this is the answer)
76+
77+
5. **Conclusion**: The square root of 144 is 12.
78+
79+
Thus, the final answer is:
80+
81+
\[
82+
\sqrt{144} = 12
83+
\]
84+
```
85+
86+
## Example 4: Binary Classification List
87+
88+
Run the **binary classification list** example to classify items as healthy or unhealthy:
89+
90+
```bash
91+
python examples/binary_classify_list_example.py
92+
```
93+
94+
### Sample Output:
95+
```bash
96+
Classifying item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Apple' as true or false.
97+
Received response for item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Apple' as true or false. -> True
98+
Classifying item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Chocolate' as true or false.
99+
Received response for item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Chocolate' as true or false. -> Chocolate can be classified as unhealthy (false) if it contains high levels of sugar and fat, such as most commercially available milk chocolates. However, dark chocolate with a high cocoa content (70% or more) has health benefits and can be considered healthy in moderation.
100+
101+
Without specific context, the classification can vary. Generally:
102+
103+
- If we consider typical chocolate, it would be classified as unhealthy (false).
104+
- If it is high-quality dark chocolate and consumed in moderation, it could be classified as healthy (true).
105+
106+
For general classification, I would classify 'Chocolate' as unhealthy (false).
107+
Classifying item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Carrot' as true or false.
108+
Received response for item: Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Carrot' as true or false. -> True
109+
Original list: ['Apple', 'Chocolate', 'Carrot']
110+
Binary classified results: [{'item': "Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Apple' as true or false.", 'classification': 'True'}, {'item': "Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Chocolate' as true or false.", 'classification': "Chocolate can be classified as unhealthy (false) if it contains high levels of sugar and fat, such as most commercially available milk chocolates. However, dark chocolate with a high cocoa content (70% or more) has health benefits and can be considered healthy in moderation. \n\nWithout specific context, the classification can vary. Generally:\n\n- If we consider typical chocolate, it would be classified as unhealthy (false).\n- If it is high-quality dark chocolate and consumed in moderation, it could be classified as healthy (true).\n\nFor general classification, I would classify 'Chocolate' as unhealthy (false)."}, {'item': "Based on the following criteria 'Classify each item as either healthy (true) or unhealthy (false)', classify the item 'Carrot' as true or false.", 'classification': 'True'}]
111+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import asyncio
2+
from core.binary_classify_list_agent import BinaryClassifyListAgent
3+
4+
async def run_binary_classify_list_example():
5+
items_to_classify = ['Apple', 'Chocolate', 'Carrot']
6+
criteria = 'Classify each item as either healthy (true) or unhealthy (false)'
7+
agent = BinaryClassifyListAgent(list_to_classify=items_to_classify, criteria=criteria)
8+
classified_items = await agent.classify_list()
9+
10+
print("Original list:", items_to_classify)
11+
print("Binary classified results:", classified_items)
12+
13+
if __name__ == "__main__":
14+
asyncio.run(run_binary_classify_list_example())
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import asyncio
2+
from typing import List, Dict
3+
from .openai_api import OpenAIClient
4+
from .logging import Logger # Using correct logging abstraction
5+
6+
class BinaryClassifyListAgent:
7+
def __init__(self, list_to_classify: List[str], criteria: str, max_tokens: int = 1000, temperature: float = 0.0):
8+
self.list_to_classify = list_to_classify
9+
self.criteria = criteria
10+
self.max_tokens = max_tokens
11+
self.temperature = temperature
12+
self.openai_client = OpenAIClient()
13+
self.logger = Logger()
14+
15+
async def classify_list(self) -> List[Dict]:
16+
tasks = []
17+
for item in self.list_to_classify:
18+
user_prompt = f"Based on the following criteria '{self.criteria}', classify the item '{item}' as true or false."
19+
tasks.append(self.classify_item(user_prompt))
20+
21+
results = await asyncio.gather(*tasks)
22+
return results
23+
24+
async def classify_item(self, user_prompt: str) -> Dict:
25+
system_prompt = "You are an assistant tasked with binary classification of items."
26+
27+
self.logger.info(f"Classifying item: {user_prompt}") # Logging the classification request
28+
29+
response = await self.openai_client.complete_chat([
30+
{"role": "system", "content": system_prompt},
31+
{"role": "user", "content": user_prompt}
32+
], max_tokens=self.max_tokens)
33+
34+
self.logger.info(f"Received response for item: {user_prompt} -> {response.strip()}") # Logging the response
35+
36+
return {"item": user_prompt, "classification": response.strip()}

src/core/logging.py

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,29 @@
1-
import logging
2-
import http.client
3-
import json
41
import os
2+
import json
3+
import logging
4+
from datetime import datetime
55

66
class Logger:
7-
def __init__(self, settings_path="../config/settings.json"):
7+
def __init__(self, settings_path=None):
8+
if settings_path is None:
9+
settings_path = os.path.join(os.path.dirname(__file__), '../../config/settings.json')
810
self.settings = self.load_settings(settings_path)
9-
self.log_path = self.settings["log_path"]
10-
os.makedirs(os.path.dirname(self.log_path), exist_ok=True)
11-
12-
# Create a logger instance
13-
self.logger = logging.getLogger("AgentMLogger")
14-
self.logger.setLevel(logging.DEBUG if self.settings.get("debug", False) else logging.INFO)
15-
16-
# File handler for logging to a file
17-
file_handler = logging.FileHandler(self.log_path)
18-
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
19-
self.logger.addHandler(file_handler)
20-
21-
# Console handler for output to the console
22-
console_handler = logging.StreamHandler()
23-
console_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
24-
self.logger.addHandler(console_handler)
25-
26-
# Enable HTTP-level logging if debug is enabled
27-
if self.settings.get("debug", False):
28-
self.enable_http_debug()
11+
log_file_path = self.settings.get('log_path', './var/logs/error.log')
12+
os.makedirs(os.path.dirname(log_file_path), exist_ok=True)
13+
logging.basicConfig(filename=log_file_path, level=logging.INFO,
14+
format='%(asctime)s - %(levelname)s - %(message)s')
15+
self.logger = logging.getLogger()
2916

3017
def load_settings(self, settings_path):
3118
if not os.path.exists(settings_path):
3219
raise FileNotFoundError(f"Settings file not found at {settings_path}")
33-
with open(settings_path, "r") as f:
20+
with open(settings_path, 'r') as f:
3421
return json.load(f)
3522

36-
def enable_http_debug(self):
37-
"""Enable HTTP-level logging for API communication."""
38-
http.client.HTTPConnection.debuglevel = 1
39-
logging.getLogger("http.client").setLevel(logging.DEBUG)
40-
logging.getLogger("http.client").propagate = True
41-
4223
def info(self, message):
24+
print(message)
4325
self.logger.info(message)
4426

4527
def error(self, message):
28+
print(message)
4629
self.logger.error(message)
47-
print(f"ERROR: {message}")

0 commit comments

Comments
 (0)