Spaces:
Sleeping
Sleeping
Add car sharing tools and update requirements and README
Browse files- CAR_SHARING_README.md +87 -0
- app.py +20 -1
- requirements.txt +3 -0
- tools/car_sharing_db.py +128 -0
- tools/get_monthly_stats_tool.py +63 -0
- tools/parse_km_reading_tool.py +98 -0
- tools/record_trip_tool.py +72 -0
- tools/user_management_tool.py +148 -0
CAR_SHARING_README.md
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Car Sharing Administration Agent
|
2 |
+
|
3 |
+
This agent helps with car sharing administration by tracking kilometers traveled and generating reports.
|
4 |
+
|
5 |
+
## Features
|
6 |
+
|
7 |
+
- Record trips with starting and ending kilometer readings
|
8 |
+
- Calculate total kilometers traveled in a month
|
9 |
+
- Manage multiple users
|
10 |
+
- Parse kilometer readings from simple user input
|
11 |
+
|
12 |
+
## How to Use
|
13 |
+
|
14 |
+
### Recording a Trip
|
15 |
+
|
16 |
+
1. Set your user name first (if not already set)
|
17 |
+
```
|
18 |
+
Please set my name as John Doe
|
19 |
+
```
|
20 |
+
|
21 |
+
2. Record a starting kilometer reading
|
22 |
+
```
|
23 |
+
61520
|
24 |
+
```
|
25 |
+
The agent will recognize this as a starting reading.
|
26 |
+
|
27 |
+
3. Record an ending kilometer reading
|
28 |
+
```
|
29 |
+
64520
|
30 |
+
```
|
31 |
+
The agent will calculate the distance traveled (3000 km in this example) and record the trip.
|
32 |
+
|
33 |
+
4. Alternatively, provide both readings at once
|
34 |
+
```
|
35 |
+
I drove from 61520 to 64520
|
36 |
+
```
|
37 |
+
The agent will parse both readings and record the trip.
|
38 |
+
|
39 |
+
### Getting Statistics
|
40 |
+
|
41 |
+
To get your monthly statistics, ask something like:
|
42 |
+
```
|
43 |
+
How many kilometers did I travel this month?
|
44 |
+
```
|
45 |
+
or
|
46 |
+
```
|
47 |
+
Show me my trip summary for April 2023
|
48 |
+
```
|
49 |
+
|
50 |
+
### Managing Users
|
51 |
+
|
52 |
+
You can switch between different users:
|
53 |
+
```
|
54 |
+
Switch to user Jane Doe
|
55 |
+
```
|
56 |
+
|
57 |
+
## Examples of Interactions
|
58 |
+
|
59 |
+
**Setting user:**
|
60 |
+
```
|
61 |
+
User: I'm John Doe
|
62 |
+
Agent: I've set your name as John Doe. You can now record your trips.
|
63 |
+
```
|
64 |
+
|
65 |
+
**Recording a trip:**
|
66 |
+
```
|
67 |
+
User: 61520
|
68 |
+
Agent: I've recorded 61520 as your starting kilometer reading. Please provide an ending reading when your trip is complete.
|
69 |
+
|
70 |
+
User: 64520
|
71 |
+
Agent: I've recorded your trip:
|
72 |
+
- Starting km: 61520
|
73 |
+
- Ending km: 64520
|
74 |
+
- Distance traveled: 3000 km
|
75 |
+
```
|
76 |
+
|
77 |
+
**Getting statistics:**
|
78 |
+
```
|
79 |
+
User: How many kilometers did I travel this month?
|
80 |
+
Agent: You've traveled 3000 kilometers in May 2023 across 1 trip.
|
81 |
+
```
|
82 |
+
|
83 |
+
## Technical Notes
|
84 |
+
|
85 |
+
The agent uses a SQLite database to store trip information. The database file (`car_sharing.db`) is created in the working directory.
|
86 |
+
|
87 |
+
User information is stored in a JSON file (`car_sharing_users.json`) in the working directory.
|
app.py
CHANGED
@@ -5,6 +5,12 @@ import pytz
|
|
5 |
import yaml
|
6 |
from tools.final_answer import FinalAnswerTool
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
from Gradio_UI import GradioUI
|
9 |
|
10 |
# Below is an example of a tool that does nothing. Amaze us with your creativity !
|
@@ -36,6 +42,12 @@ def get_current_time_in_timezone(timezone: str) -> str:
|
|
36 |
|
37 |
final_answer = FinalAnswerTool()
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
|
40 |
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
|
41 |
|
@@ -55,7 +67,14 @@ with open("prompts.yaml", 'r') as stream:
|
|
55 |
|
56 |
agent = CodeAgent(
|
57 |
model=model,
|
58 |
-
tools=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
max_steps=6,
|
60 |
verbosity_level=1,
|
61 |
grammar=None,
|
|
|
5 |
import yaml
|
6 |
from tools.final_answer import FinalAnswerTool
|
7 |
|
8 |
+
# Import our new car sharing tools
|
9 |
+
from tools.record_trip_tool import RecordTripTool
|
10 |
+
from tools.get_monthly_stats_tool import GetMonthlyStatsTool
|
11 |
+
from tools.parse_km_reading_tool import ParseKmReadingTool
|
12 |
+
from tools.user_management_tool import UserManagementTool
|
13 |
+
|
14 |
from Gradio_UI import GradioUI
|
15 |
|
16 |
# Below is an example of a tool that does nothing. Amaze us with your creativity !
|
|
|
42 |
|
43 |
final_answer = FinalAnswerTool()
|
44 |
|
45 |
+
# Initialize our car sharing tools
|
46 |
+
record_trip_tool = RecordTripTool()
|
47 |
+
get_monthly_stats_tool = GetMonthlyStatsTool()
|
48 |
+
parse_km_reading_tool = ParseKmReadingTool()
|
49 |
+
user_management_tool = UserManagementTool()
|
50 |
+
|
51 |
# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
|
52 |
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
|
53 |
|
|
|
67 |
|
68 |
agent = CodeAgent(
|
69 |
model=model,
|
70 |
+
tools=[
|
71 |
+
final_answer,
|
72 |
+
get_current_time_in_timezone,
|
73 |
+
record_trip_tool,
|
74 |
+
get_monthly_stats_tool,
|
75 |
+
parse_km_reading_tool,
|
76 |
+
user_management_tool
|
77 |
+
], ## add your tools here (don't remove final answer)
|
78 |
max_steps=6,
|
79 |
verbosity_level=1,
|
80 |
grammar=None,
|
requirements.txt
CHANGED
@@ -3,3 +3,6 @@ smolagents==1.13.0
|
|
3 |
requests
|
4 |
duckduckgo_search
|
5 |
pandas
|
|
|
|
|
|
|
|
3 |
requests
|
4 |
duckduckgo_search
|
5 |
pandas
|
6 |
+
pytz
|
7 |
+
pyyaml
|
8 |
+
sqlite3
|
tools/car_sharing_db.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sqlite3
|
2 |
+
import os
|
3 |
+
import datetime
|
4 |
+
from typing import List, Dict, Any, Optional, Tuple
|
5 |
+
|
6 |
+
class CarSharingDB:
|
7 |
+
def __init__(self, db_path="car_sharing.db"):
|
8 |
+
"""Initialize the car sharing database."""
|
9 |
+
self.db_path = db_path
|
10 |
+
self.initialize_db()
|
11 |
+
|
12 |
+
def initialize_db(self):
|
13 |
+
"""Create the database tables if they don't exist."""
|
14 |
+
conn = sqlite3.connect(self.db_path)
|
15 |
+
cursor = conn.cursor()
|
16 |
+
|
17 |
+
# Create trips table
|
18 |
+
cursor.execute('''
|
19 |
+
CREATE TABLE IF NOT EXISTS trips (
|
20 |
+
id INTEGER PRIMARY KEY,
|
21 |
+
user_name TEXT NOT NULL,
|
22 |
+
start_km INTEGER NOT NULL,
|
23 |
+
end_km INTEGER NOT NULL,
|
24 |
+
km_traveled INTEGER NOT NULL,
|
25 |
+
trip_date TEXT NOT NULL
|
26 |
+
)
|
27 |
+
''')
|
28 |
+
|
29 |
+
conn.commit()
|
30 |
+
conn.close()
|
31 |
+
|
32 |
+
def record_trip(self, user_name: str, start_km: int, end_km: int) -> bool:
|
33 |
+
"""Record a new trip in the database."""
|
34 |
+
try:
|
35 |
+
km_traveled = end_km - start_km
|
36 |
+
if km_traveled <= 0:
|
37 |
+
return False
|
38 |
+
|
39 |
+
trip_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
40 |
+
|
41 |
+
conn = sqlite3.connect(self.db_path)
|
42 |
+
cursor = conn.cursor()
|
43 |
+
|
44 |
+
cursor.execute(
|
45 |
+
"INSERT INTO trips (user_name, start_km, end_km, km_traveled, trip_date) VALUES (?, ?, ?, ?, ?)",
|
46 |
+
(user_name, start_km, end_km, km_traveled, trip_date)
|
47 |
+
)
|
48 |
+
|
49 |
+
conn.commit()
|
50 |
+
conn.close()
|
51 |
+
return True
|
52 |
+
except Exception as e:
|
53 |
+
print(f"Error recording trip: {str(e)}")
|
54 |
+
return False
|
55 |
+
|
56 |
+
def get_monthly_stats(self, user_name: str, month: Optional[int] = None, year: Optional[int] = None) -> Dict[str, Any]:
|
57 |
+
"""Get monthly statistics for a user."""
|
58 |
+
try:
|
59 |
+
if month is None or year is None:
|
60 |
+
# Use current month and year if not specified
|
61 |
+
now = datetime.datetime.now()
|
62 |
+
month = now.month
|
63 |
+
year = now.year
|
64 |
+
|
65 |
+
# Format date range for the specified month
|
66 |
+
start_date = f"{year}-{month:02d}-01"
|
67 |
+
|
68 |
+
# Calculate the last day of the month
|
69 |
+
if month == 12:
|
70 |
+
next_month_year = year + 1
|
71 |
+
next_month = 1
|
72 |
+
else:
|
73 |
+
next_month_year = year
|
74 |
+
next_month = month + 1
|
75 |
+
|
76 |
+
end_date = f"{next_month_year}-{next_month:02d}-01"
|
77 |
+
|
78 |
+
conn = sqlite3.connect(self.db_path)
|
79 |
+
cursor = conn.cursor()
|
80 |
+
|
81 |
+
# Get total kilometers and trip count
|
82 |
+
cursor.execute(
|
83 |
+
"SELECT SUM(km_traveled), COUNT(*) FROM trips WHERE user_name = ? AND trip_date >= ? AND trip_date < ?",
|
84 |
+
(user_name, start_date, end_date)
|
85 |
+
)
|
86 |
+
|
87 |
+
total_km, trip_count = cursor.fetchone()
|
88 |
+
|
89 |
+
# Get all trips in the month
|
90 |
+
cursor.execute(
|
91 |
+
"SELECT start_km, end_km, km_traveled, trip_date FROM trips WHERE user_name = ? AND trip_date >= ? AND trip_date < ? ORDER BY trip_date",
|
92 |
+
(user_name, start_date, end_date)
|
93 |
+
)
|
94 |
+
|
95 |
+
trips = []
|
96 |
+
for row in cursor.fetchall():
|
97 |
+
trips.append({
|
98 |
+
"start_km": row[0],
|
99 |
+
"end_km": row[1],
|
100 |
+
"km_traveled": row[2],
|
101 |
+
"trip_date": row[3]
|
102 |
+
})
|
103 |
+
|
104 |
+
conn.close()
|
105 |
+
|
106 |
+
# Default to 0 if no trips found
|
107 |
+
total_km = total_km or 0
|
108 |
+
trip_count = trip_count or 0
|
109 |
+
|
110 |
+
return {
|
111 |
+
"user_name": user_name,
|
112 |
+
"month": month,
|
113 |
+
"year": year,
|
114 |
+
"total_km": total_km,
|
115 |
+
"trip_count": trip_count,
|
116 |
+
"trips": trips
|
117 |
+
}
|
118 |
+
except Exception as e:
|
119 |
+
print(f"Error getting monthly stats: {str(e)}")
|
120 |
+
return {
|
121 |
+
"user_name": user_name,
|
122 |
+
"month": month,
|
123 |
+
"year": year,
|
124 |
+
"total_km": 0,
|
125 |
+
"trip_count": 0,
|
126 |
+
"trips": [],
|
127 |
+
"error": str(e)
|
128 |
+
}
|
tools/get_monthly_stats_tool.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Dict, Optional
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
from tools.car_sharing_db import CarSharingDB
|
4 |
+
|
5 |
+
class GetMonthlyStatsTool(Tool):
|
6 |
+
name = "get_monthly_stats"
|
7 |
+
description = "Retrieves monthly car sharing statistics for a specific user."
|
8 |
+
inputs = {
|
9 |
+
'user_name': {'type': 'string', 'description': 'Name of the user to get statistics for'},
|
10 |
+
'month': {'type': 'integer', 'description': 'Month number (1-12). If not provided, current month is used.'},
|
11 |
+
'year': {'type': 'integer', 'description': 'Year (e.g., 2023). If not provided, current year is used.'}
|
12 |
+
}
|
13 |
+
output_type = "dict"
|
14 |
+
|
15 |
+
def __init__(self, db_path="car_sharing.db"):
|
16 |
+
self.db = CarSharingDB(db_path)
|
17 |
+
self.is_initialized = True
|
18 |
+
|
19 |
+
def forward(self, user_name: str, month: Optional[int] = None, year: Optional[int] = None) -> Dict[str, Any]:
|
20 |
+
"""
|
21 |
+
Get monthly car sharing statistics for a user.
|
22 |
+
|
23 |
+
Args:
|
24 |
+
user_name: Name of the user to get statistics for
|
25 |
+
month: Month number (1-12). If not provided, current month is used.
|
26 |
+
year: Year (e.g., 2023). If not provided, current year is used.
|
27 |
+
|
28 |
+
Returns:
|
29 |
+
A dictionary with monthly statistics
|
30 |
+
"""
|
31 |
+
try:
|
32 |
+
# Convert month and year to integers if provided
|
33 |
+
if month is not None:
|
34 |
+
month = int(month)
|
35 |
+
if month < 1 or month > 12:
|
36 |
+
return {
|
37 |
+
"success": False,
|
38 |
+
"error": "Month must be between 1 and 12",
|
39 |
+
"total_km": 0
|
40 |
+
}
|
41 |
+
|
42 |
+
if year is not None:
|
43 |
+
year = int(year)
|
44 |
+
|
45 |
+
# Get monthly statistics
|
46 |
+
stats = self.db.get_monthly_stats(user_name, month, year)
|
47 |
+
|
48 |
+
# Add success flag
|
49 |
+
stats["success"] = True
|
50 |
+
|
51 |
+
return stats
|
52 |
+
except ValueError:
|
53 |
+
return {
|
54 |
+
"success": False,
|
55 |
+
"error": "Month and year must be integers",
|
56 |
+
"total_km": 0
|
57 |
+
}
|
58 |
+
except Exception as e:
|
59 |
+
return {
|
60 |
+
"success": False,
|
61 |
+
"error": str(e),
|
62 |
+
"total_km": 0
|
63 |
+
}
|
tools/parse_km_reading_tool.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Dict, Union
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
import re
|
4 |
+
|
5 |
+
class ParseKmReadingTool(Tool):
|
6 |
+
name = "parse_km_reading"
|
7 |
+
description = "Parses kilometer readings from user input."
|
8 |
+
inputs = {
|
9 |
+
'input_text': {'type': 'string', 'description': 'Text input from the user that may contain kilometer readings'}
|
10 |
+
}
|
11 |
+
output_type = "dict"
|
12 |
+
|
13 |
+
def __init__(self):
|
14 |
+
self.is_initialized = True
|
15 |
+
# Store the last valid kilometer reading to use as start_km for future trips
|
16 |
+
self.last_reading = None
|
17 |
+
|
18 |
+
def forward(self, input_text: str) -> Dict[str, Any]:
|
19 |
+
"""
|
20 |
+
Parse kilometer readings from user input.
|
21 |
+
|
22 |
+
Args:
|
23 |
+
input_text: Text input that may contain kilometer readings
|
24 |
+
|
25 |
+
Returns:
|
26 |
+
A dictionary with parsed kilometer readings
|
27 |
+
"""
|
28 |
+
try:
|
29 |
+
# Clean and normalize input
|
30 |
+
clean_text = input_text.strip().replace(',', '')
|
31 |
+
|
32 |
+
# Find all numbers in the input
|
33 |
+
numbers = re.findall(r'\b\d+\b', clean_text)
|
34 |
+
numbers = [int(num) for num in numbers]
|
35 |
+
|
36 |
+
# Determine what kind of reading this is
|
37 |
+
result = {
|
38 |
+
"success": True,
|
39 |
+
"numbers_found": numbers,
|
40 |
+
"reading_type": None
|
41 |
+
}
|
42 |
+
|
43 |
+
if len(numbers) == 0:
|
44 |
+
result["success"] = False
|
45 |
+
result["error"] = "No kilometer readings found in input"
|
46 |
+
return result
|
47 |
+
|
48 |
+
if len(numbers) == 1:
|
49 |
+
# Single reading - could be start or end
|
50 |
+
km_reading = numbers[0]
|
51 |
+
|
52 |
+
if self.last_reading is None:
|
53 |
+
# First reading ever, must be start
|
54 |
+
result["reading_type"] = "start"
|
55 |
+
result["start_km"] = km_reading
|
56 |
+
self.last_reading = km_reading
|
57 |
+
else:
|
58 |
+
# We have a previous reading
|
59 |
+
if km_reading > self.last_reading:
|
60 |
+
# This is likely an end reading
|
61 |
+
result["reading_type"] = "end"
|
62 |
+
result["end_km"] = km_reading
|
63 |
+
result["start_km"] = self.last_reading
|
64 |
+
result["km_traveled"] = km_reading - self.last_reading
|
65 |
+
self.last_reading = km_reading
|
66 |
+
else:
|
67 |
+
# This is likely a new start reading
|
68 |
+
result["reading_type"] = "start"
|
69 |
+
result["start_km"] = km_reading
|
70 |
+
self.last_reading = km_reading
|
71 |
+
|
72 |
+
elif len(numbers) == 2:
|
73 |
+
# Two readings - likely start and end
|
74 |
+
start_km = min(numbers)
|
75 |
+
end_km = max(numbers)
|
76 |
+
|
77 |
+
result["reading_type"] = "complete"
|
78 |
+
result["start_km"] = start_km
|
79 |
+
result["end_km"] = end_km
|
80 |
+
result["km_traveled"] = end_km - start_km
|
81 |
+
self.last_reading = end_km
|
82 |
+
|
83 |
+
else:
|
84 |
+
# More than 2 numbers - take first and last assuming chronological order
|
85 |
+
result["reading_type"] = "multiple"
|
86 |
+
result["start_km"] = numbers[0]
|
87 |
+
result["end_km"] = numbers[-1]
|
88 |
+
result["km_traveled"] = numbers[-1] - numbers[0]
|
89 |
+
result["all_readings"] = numbers
|
90 |
+
self.last_reading = numbers[-1]
|
91 |
+
|
92 |
+
return result
|
93 |
+
|
94 |
+
except Exception as e:
|
95 |
+
return {
|
96 |
+
"success": False,
|
97 |
+
"error": str(e)
|
98 |
+
}
|
tools/record_trip_tool.py
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Dict
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
from tools.car_sharing_db import CarSharingDB
|
4 |
+
|
5 |
+
class RecordTripTool(Tool):
|
6 |
+
name = "record_trip"
|
7 |
+
description = "Records a car sharing trip with starting and ending kilometer readings."
|
8 |
+
inputs = {
|
9 |
+
'user_name': {'type': 'string', 'description': 'Name of the user who made the trip'},
|
10 |
+
'start_km': {'type': 'integer', 'description': 'Starting kilometer reading of the vehicle'},
|
11 |
+
'end_km': {'type': 'integer', 'description': 'Ending kilometer reading of the vehicle'}
|
12 |
+
}
|
13 |
+
output_type = "dict"
|
14 |
+
|
15 |
+
def __init__(self, db_path="car_sharing.db"):
|
16 |
+
self.db = CarSharingDB(db_path)
|
17 |
+
self.is_initialized = True
|
18 |
+
|
19 |
+
def forward(self, user_name: str, start_km: int, end_km: int) -> Dict[str, Any]:
|
20 |
+
"""
|
21 |
+
Record a car sharing trip in the database.
|
22 |
+
|
23 |
+
Args:
|
24 |
+
user_name: Name of the user who made the trip
|
25 |
+
start_km: Starting kilometer reading
|
26 |
+
end_km: Ending kilometer reading
|
27 |
+
|
28 |
+
Returns:
|
29 |
+
A dictionary with the result of the operation
|
30 |
+
"""
|
31 |
+
try:
|
32 |
+
# Ensure kilometers are integers
|
33 |
+
start_km = int(start_km)
|
34 |
+
end_km = int(end_km)
|
35 |
+
|
36 |
+
# Validate input
|
37 |
+
if end_km <= start_km:
|
38 |
+
return {
|
39 |
+
"success": False,
|
40 |
+
"error": "End kilometer reading must be greater than start kilometer reading",
|
41 |
+
"km_traveled": 0
|
42 |
+
}
|
43 |
+
|
44 |
+
# Record the trip
|
45 |
+
success = self.db.record_trip(user_name, start_km, end_km)
|
46 |
+
|
47 |
+
if success:
|
48 |
+
return {
|
49 |
+
"success": True,
|
50 |
+
"user_name": user_name,
|
51 |
+
"start_km": start_km,
|
52 |
+
"end_km": end_km,
|
53 |
+
"km_traveled": end_km - start_km
|
54 |
+
}
|
55 |
+
else:
|
56 |
+
return {
|
57 |
+
"success": False,
|
58 |
+
"error": "Failed to record trip",
|
59 |
+
"km_traveled": 0
|
60 |
+
}
|
61 |
+
except ValueError:
|
62 |
+
return {
|
63 |
+
"success": False,
|
64 |
+
"error": "Kilometer readings must be integers",
|
65 |
+
"km_traveled": 0
|
66 |
+
}
|
67 |
+
except Exception as e:
|
68 |
+
return {
|
69 |
+
"success": False,
|
70 |
+
"error": str(e),
|
71 |
+
"km_traveled": 0
|
72 |
+
}
|
tools/user_management_tool.py
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any, Dict, Optional
|
2 |
+
from smolagents.tools import Tool
|
3 |
+
import json
|
4 |
+
import os
|
5 |
+
|
6 |
+
class UserManagementTool(Tool):
|
7 |
+
name = "user_management"
|
8 |
+
description = "Manages user information for the car sharing system."
|
9 |
+
inputs = {
|
10 |
+
'action': {'type': 'string', 'description': 'The action to perform (get, set, list)'},
|
11 |
+
'user_name': {'type': 'string', 'description': 'Name of the user'},
|
12 |
+
'user_info': {'type': 'any', 'description': 'User information to store (for set action)'}
|
13 |
+
}
|
14 |
+
output_type = "dict"
|
15 |
+
|
16 |
+
def __init__(self, users_file="car_sharing_users.json"):
|
17 |
+
self.is_initialized = True
|
18 |
+
self.users_file = users_file
|
19 |
+
self.users = self._load_users()
|
20 |
+
self.current_user = None
|
21 |
+
|
22 |
+
def _load_users(self) -> Dict[str, Dict[str, Any]]:
|
23 |
+
"""Load users from file or create an empty dict if file doesn't exist."""
|
24 |
+
if os.path.exists(self.users_file):
|
25 |
+
try:
|
26 |
+
with open(self.users_file, 'r') as f:
|
27 |
+
return json.load(f)
|
28 |
+
except Exception:
|
29 |
+
return {}
|
30 |
+
return {}
|
31 |
+
|
32 |
+
def _save_users(self) -> bool:
|
33 |
+
"""Save users to file."""
|
34 |
+
try:
|
35 |
+
with open(self.users_file, 'w') as f:
|
36 |
+
json.dump(self.users, f, indent=2)
|
37 |
+
return True
|
38 |
+
except Exception:
|
39 |
+
return False
|
40 |
+
|
41 |
+
def forward(self, action: str, user_name: Optional[str] = None, user_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
42 |
+
"""
|
43 |
+
Manage user information.
|
44 |
+
|
45 |
+
Args:
|
46 |
+
action: The action to perform (get, set, list, set_current)
|
47 |
+
user_name: Name of the user
|
48 |
+
user_info: User information to store (for set action)
|
49 |
+
|
50 |
+
Returns:
|
51 |
+
A dictionary with the result of the operation
|
52 |
+
"""
|
53 |
+
try:
|
54 |
+
action = action.lower()
|
55 |
+
|
56 |
+
if action == "list":
|
57 |
+
# List all users
|
58 |
+
return {
|
59 |
+
"success": True,
|
60 |
+
"action": "list",
|
61 |
+
"users": list(self.users.keys()),
|
62 |
+
"current_user": self.current_user
|
63 |
+
}
|
64 |
+
|
65 |
+
elif action == "get":
|
66 |
+
# Get user info
|
67 |
+
if not user_name:
|
68 |
+
return {
|
69 |
+
"success": False,
|
70 |
+
"action": "get",
|
71 |
+
"error": "User name is required for 'get' action"
|
72 |
+
}
|
73 |
+
|
74 |
+
if user_name not in self.users:
|
75 |
+
return {
|
76 |
+
"success": False,
|
77 |
+
"action": "get",
|
78 |
+
"error": f"User '{user_name}' not found"
|
79 |
+
}
|
80 |
+
|
81 |
+
return {
|
82 |
+
"success": True,
|
83 |
+
"action": "get",
|
84 |
+
"user_name": user_name,
|
85 |
+
"user_info": self.users[user_name]
|
86 |
+
}
|
87 |
+
|
88 |
+
elif action == "set":
|
89 |
+
# Set user info
|
90 |
+
if not user_name:
|
91 |
+
return {
|
92 |
+
"success": False,
|
93 |
+
"action": "set",
|
94 |
+
"error": "User name is required for 'set' action"
|
95 |
+
}
|
96 |
+
|
97 |
+
if user_info is None:
|
98 |
+
user_info = {}
|
99 |
+
|
100 |
+
# Create or update user
|
101 |
+
if user_name in self.users:
|
102 |
+
self.users[user_name].update(user_info)
|
103 |
+
else:
|
104 |
+
self.users[user_name] = user_info
|
105 |
+
|
106 |
+
self._save_users()
|
107 |
+
|
108 |
+
return {
|
109 |
+
"success": True,
|
110 |
+
"action": "set",
|
111 |
+
"user_name": user_name,
|
112 |
+
"user_info": self.users[user_name]
|
113 |
+
}
|
114 |
+
|
115 |
+
elif action == "set_current":
|
116 |
+
# Set current user
|
117 |
+
if not user_name:
|
118 |
+
return {
|
119 |
+
"success": False,
|
120 |
+
"action": "set_current",
|
121 |
+
"error": "User name is required for 'set_current' action"
|
122 |
+
}
|
123 |
+
|
124 |
+
# Create user if it doesn't exist
|
125 |
+
if user_name not in self.users:
|
126 |
+
self.users[user_name] = {}
|
127 |
+
self._save_users()
|
128 |
+
|
129 |
+
self.current_user = user_name
|
130 |
+
|
131 |
+
return {
|
132 |
+
"success": True,
|
133 |
+
"action": "set_current",
|
134 |
+
"user_name": user_name,
|
135 |
+
"current_user": self.current_user
|
136 |
+
}
|
137 |
+
|
138 |
+
else:
|
139 |
+
return {
|
140 |
+
"success": False,
|
141 |
+
"error": f"Unknown action: {action}"
|
142 |
+
}
|
143 |
+
|
144 |
+
except Exception as e:
|
145 |
+
return {
|
146 |
+
"success": False,
|
147 |
+
"error": str(e)
|
148 |
+
}
|