Benjamin Consolvo
commited on
Commit
·
78797ac
0
Parent(s):
init1
Browse files- .gitattributes +35 -0
- LICENSE +21 -0
- README.md +164 -0
- README_backup.md +166 -0
- app.py +134 -0
- requirements.txt +7 -0
- tools/__init__.py +0 -0
- tools/browser_tools.py +38 -0
- tools/calculator_tools.py +13 -0
- tools/search_tools.py +37 -0
- trip_agents.py +110 -0
- trip_tasks.py +86 -0
.gitattributes
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2024 Tony Kipkemboi
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
README.md
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: VacAIgent
|
3 |
+
emoji: 🐨
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: purple
|
6 |
+
sdk: streamlit
|
7 |
+
sdk_version: 1.44.1
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
license: apache-2.0
|
11 |
+
short_description: Let AI agents plan your next vacation!
|
12 |
+
---
|
13 |
+
|
14 |
+
# 🏖️ VacAIgent: Streamlit-Integrated AI Crew for Trip Planning
|
15 |
+
|
16 |
+
_Forked and enhanced from the_ [_crewAI examples repository_](https://github.com/joaomdmoura/crewAI-examples/tree/main/trip_planner)
|
17 |
+
|
18 |
+
## Introduction
|
19 |
+
|
20 |
+
VacAIgent leverages the CrewAI framework to automate and enhance the trip planning experience, integrating a user-friendly Streamlit interface. This project demonstrates how autonomous AI agents can collaborate and execute complex tasks efficiently, now with an added layer of interactivity and accessibility through Streamlit.
|
21 |
+
|
22 |
+
**Check out the video below for code walkthrough** 👇
|
23 |
+
|
24 |
+
<a href="https://youtu.be/nKG_kbQUDDE">
|
25 |
+
<img src="https://img.youtube.com/vi/nKG_kbQUDDE/hqdefault.jpg" alt="Watch the video" width="100%">
|
26 |
+
</a>
|
27 |
+
|
28 |
+
(_Trip example originally developed by [@joaomdmoura](https://x.com/joaomdmoura)_)
|
29 |
+
|
30 |
+
## CrewAI Framework
|
31 |
+
|
32 |
+
CrewAI simplifies the orchestration of role-playing AI agents. In VacAIgent, these agents collaboratively decide on cities and craft a complete itinerary for your trip based on specified preferences, all accessible via a streamlined Streamlit user interface.
|
33 |
+
|
34 |
+
## Streamlit Interface
|
35 |
+
|
36 |
+
The introduction of [Streamlit](https://streamlit.io/) transforms this application into an interactive web app, allowing users to easily input their preferences and receive tailored travel plans.
|
37 |
+
|
38 |
+
## Running the Application
|
39 |
+
|
40 |
+
To experience the VacAIgent app:
|
41 |
+
|
42 |
+
### Pre-Requisites
|
43 |
+
1. Install and Configure **git** on your machine
|
44 |
+
2. Get the API key from **scrapinagent.com** from scrapinagent [Click Here to Signup](https://scrapingant.com/)
|
45 |
+
3. Get the API from **SERPER API** from serper [Click here to Signup]( https://serper.dev/)
|
46 |
+
|
47 |
+
### Deploy Trip Planner
|
48 |
+
|
49 |
+
#### Step 1
|
50 |
+
```sh
|
51 |
+
git clone https://github.com/intel-sandbox/trip_planner_agent
|
52 |
+
```
|
53 |
+
* *Please make sure git is installed*
|
54 |
+
|
55 |
+
#### Step 2
|
56 |
+
|
57 |
+
Insall Dependencies
|
58 |
+
```sh
|
59 |
+
pip install -r requirements.txt
|
60 |
+
```
|
61 |
+
#### Step 3
|
62 |
+
|
63 |
+
```sh
|
64 |
+
cd trip_planner_agent
|
65 |
+
```
|
66 |
+
|
67 |
+
create `.streamlit/secrets.toml` file and Update **Credentials**
|
68 |
+
you can use secrtes.example file for reference
|
69 |
+
|
70 |
+
```sh
|
71 |
+
SERPER_API_KEY=""
|
72 |
+
SCRAPINGANT_API_KEY=""
|
73 |
+
OPENAI_API_KEY=""
|
74 |
+
MODEL_ID=""
|
75 |
+
MODEL_BASE_URL=""
|
76 |
+
```
|
77 |
+
#### Step 4
|
78 |
+
|
79 |
+
Run the application
|
80 |
+
|
81 |
+
```sh
|
82 |
+
streamlit run streamlit_app.py
|
83 |
+
```
|
84 |
+
|
85 |
+
Your application should be up and running
|
86 |
+
|
87 |
+
★ **Disclaimer**: The application uses GPT-4 by default. Ensure you have access to OpenAI's API and be aware of the associated costs.
|
88 |
+
|
89 |
+
## Details & Explanation
|
90 |
+
|
91 |
+
- **Streamlit UI**: The Streamlit interface is implemented in `streamlit_app.py`, where users can input their trip details.
|
92 |
+
- **Components**:
|
93 |
+
- `./trip_tasks.py`: Contains task prompts for the agents.
|
94 |
+
- `./trip_agents.py`: Manages the creation of agents.
|
95 |
+
- `./tools directory`: Houses tool classes used by agents.
|
96 |
+
- `./streamlit_app.py`: The heart of the Streamlit app.
|
97 |
+
|
98 |
+
## Using GPT 3.5
|
99 |
+
|
100 |
+
To switch from GPT-4 to GPT-3.5, pass the llm argument in the agent constructor:
|
101 |
+
|
102 |
+
```python
|
103 |
+
from langchain.chat_models import ChatOpenAI
|
104 |
+
|
105 |
+
llm = ChatOpenAI(model='gpt-3.5-turbo') # Loading gpt-3.5-turbo (see more OpenAI models at https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4)
|
106 |
+
|
107 |
+
class TripAgents:
|
108 |
+
# ... existing methods
|
109 |
+
|
110 |
+
def local_expert(self):
|
111 |
+
return Agent(
|
112 |
+
role='Local Expert',
|
113 |
+
goal='Provide insights about the selected city',
|
114 |
+
tools=[SearchTools.search_internet, BrowserTools.scrape_and_summarize_website],
|
115 |
+
llm=llm,
|
116 |
+
verbose=True
|
117 |
+
)
|
118 |
+
|
119 |
+
```
|
120 |
+
|
121 |
+
## Using Local Models with Ollama
|
122 |
+
|
123 |
+
For enhanced privacy and customization, you can integrate local models like Ollama:
|
124 |
+
|
125 |
+
### Setting Up Ollama
|
126 |
+
|
127 |
+
- **Installation**: Follow Ollama's guide for installation.
|
128 |
+
- **Configuration**: Customize the model as per your requirements.
|
129 |
+
|
130 |
+
### Integrating Ollama with CrewAI
|
131 |
+
|
132 |
+
Pass the Ollama model to agents in the CrewAI framework:
|
133 |
+
|
134 |
+
```python
|
135 |
+
from langchain.llms import Ollama
|
136 |
+
|
137 |
+
ollama_model = Ollama(model="agent")
|
138 |
+
|
139 |
+
class TripAgents:
|
140 |
+
# ... existing methods
|
141 |
+
|
142 |
+
def local_expert(self):
|
143 |
+
return Agent(
|
144 |
+
role='Local Expert',
|
145 |
+
tools=[SearchTools.search_internet, BrowserTools.scrape_and_summarize_website],
|
146 |
+
llm=ollama_model,
|
147 |
+
verbose=True
|
148 |
+
)
|
149 |
+
|
150 |
+
```
|
151 |
+
|
152 |
+
## Benefits of Local Models
|
153 |
+
|
154 |
+
- **Privacy**: Process sensitive data in-house.
|
155 |
+
- **Customization**: Tailor models to fit specific needs.
|
156 |
+
- **Performance**: Potentially faster responses with on-premises models.
|
157 |
+
|
158 |
+
## License
|
159 |
+
|
160 |
+
VacAIgent is open-sourced under the MIT License.
|
161 |
+
|
162 |
+
|
163 |
+
|
164 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
README_backup.md
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: VacAIgent
|
3 |
+
emoji: 🐨
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: purple
|
6 |
+
sdk: streamlit
|
7 |
+
sdk_version: 1.44.1
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
license: apache-2.0
|
11 |
+
short_description: Let AI agents plan your next vacation!
|
12 |
+
---
|
13 |
+
|
14 |
+
# 🏖️ VacAIgent: Streamlit-Integrated AI Crew for Trip Planning
|
15 |
+
|
16 |
+
_Forked and enhanced from the_ [_crewAI examples repository_](https://github.com/joaomdmoura/crewAI-examples/tree/main/trip_planner)
|
17 |
+
|
18 |
+

|
19 |
+
|
20 |
+
## Introduction
|
21 |
+
|
22 |
+
VacAIgent leverages the CrewAI framework to automate and enhance the trip planning experience, integrating a user-friendly Streamlit interface. This project demonstrates how autonomous AI agents can collaborate and execute complex tasks efficiently, now with an added layer of interactivity and accessibility through Streamlit.
|
23 |
+
|
24 |
+
**Check out the video below for code walkthrough** 👇
|
25 |
+
|
26 |
+
<a href="https://youtu.be/nKG_kbQUDDE">
|
27 |
+
<img src="https://img.youtube.com/vi/nKG_kbQUDDE/hqdefault.jpg" alt="Watch the video" width="100%">
|
28 |
+
</a>
|
29 |
+
|
30 |
+
(_Trip example originally developed by [@joaomdmoura](https://x.com/joaomdmoura)_)
|
31 |
+
|
32 |
+
## CrewAI Framework
|
33 |
+
|
34 |
+
CrewAI simplifies the orchestration of role-playing AI agents. In VacAIgent, these agents collaboratively decide on cities and craft a complete itinerary for your trip based on specified preferences, all accessible via a streamlined Streamlit user interface.
|
35 |
+
|
36 |
+
## Streamlit Interface
|
37 |
+
|
38 |
+
The introduction of [Streamlit](https://streamlit.io/) transforms this application into an interactive web app, allowing users to easily input their preferences and receive tailored travel plans.
|
39 |
+
|
40 |
+
## Running the Application
|
41 |
+
|
42 |
+
To experience the VacAIgent app:
|
43 |
+
|
44 |
+
### Pre-Requisites
|
45 |
+
1. Install and Configure **git** on your machine
|
46 |
+
2. Get the API key from **scrapinagent.com** from scrapinagent [Click Here to Signup](https://scrapingant.com/)
|
47 |
+
3. Get the API from **SERPER API** from serper [Click here to Signup]( https://serper.dev/)
|
48 |
+
|
49 |
+
### Deploy Trip Planner
|
50 |
+
|
51 |
+
#### Step 1
|
52 |
+
```sh
|
53 |
+
git clone https://github.com/intel-sandbox/trip_planner_agent
|
54 |
+
```
|
55 |
+
* *Please make sure git is installed*
|
56 |
+
|
57 |
+
#### Step 2
|
58 |
+
|
59 |
+
Insall Dependencies
|
60 |
+
```sh
|
61 |
+
pip install -r requirements.txt
|
62 |
+
```
|
63 |
+
#### Step 3
|
64 |
+
|
65 |
+
```sh
|
66 |
+
cd trip_planner_agent
|
67 |
+
```
|
68 |
+
|
69 |
+
create `.streamlit/secrets.toml` file and Update **Credentials**
|
70 |
+
you can use secrtes.example file for reference
|
71 |
+
|
72 |
+
```sh
|
73 |
+
SERPER_API_KEY=""
|
74 |
+
SCRAPINGANT_API_KEY=""
|
75 |
+
OPENAI_API_KEY=""
|
76 |
+
MODEL_ID=""
|
77 |
+
MODEL_BASE_URL=""
|
78 |
+
```
|
79 |
+
#### Step 4
|
80 |
+
|
81 |
+
Run the application
|
82 |
+
|
83 |
+
```sh
|
84 |
+
streamlit run streamlit_app.py
|
85 |
+
```
|
86 |
+
|
87 |
+
Your application should be up and running
|
88 |
+
|
89 |
+
★ **Disclaimer**: The application uses GPT-4 by default. Ensure you have access to OpenAI's API and be aware of the associated costs.
|
90 |
+
|
91 |
+
## Details & Explanation
|
92 |
+
|
93 |
+
- **Streamlit UI**: The Streamlit interface is implemented in `streamlit_app.py`, where users can input their trip details.
|
94 |
+
- **Components**:
|
95 |
+
- `./trip_tasks.py`: Contains task prompts for the agents.
|
96 |
+
- `./trip_agents.py`: Manages the creation of agents.
|
97 |
+
- `./tools directory`: Houses tool classes used by agents.
|
98 |
+
- `./streamlit_app.py`: The heart of the Streamlit app.
|
99 |
+
|
100 |
+
## Using GPT 3.5
|
101 |
+
|
102 |
+
To switch from GPT-4 to GPT-3.5, pass the llm argument in the agent constructor:
|
103 |
+
|
104 |
+
```python
|
105 |
+
from langchain.chat_models import ChatOpenAI
|
106 |
+
|
107 |
+
llm = ChatOpenAI(model='gpt-3.5-turbo') # Loading gpt-3.5-turbo (see more OpenAI models at https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4)
|
108 |
+
|
109 |
+
class TripAgents:
|
110 |
+
# ... existing methods
|
111 |
+
|
112 |
+
def local_expert(self):
|
113 |
+
return Agent(
|
114 |
+
role='Local Expert',
|
115 |
+
goal='Provide insights about the selected city',
|
116 |
+
tools=[SearchTools.search_internet, BrowserTools.scrape_and_summarize_website],
|
117 |
+
llm=llm,
|
118 |
+
verbose=True
|
119 |
+
)
|
120 |
+
|
121 |
+
```
|
122 |
+
|
123 |
+
## Using Local Models with Ollama
|
124 |
+
|
125 |
+
For enhanced privacy and customization, you can integrate local models like Ollama:
|
126 |
+
|
127 |
+
### Setting Up Ollama
|
128 |
+
|
129 |
+
- **Installation**: Follow Ollama's guide for installation.
|
130 |
+
- **Configuration**: Customize the model as per your requirements.
|
131 |
+
|
132 |
+
### Integrating Ollama with CrewAI
|
133 |
+
|
134 |
+
Pass the Ollama model to agents in the CrewAI framework:
|
135 |
+
|
136 |
+
```python
|
137 |
+
from langchain.llms import Ollama
|
138 |
+
|
139 |
+
ollama_model = Ollama(model="agent")
|
140 |
+
|
141 |
+
class TripAgents:
|
142 |
+
# ... existing methods
|
143 |
+
|
144 |
+
def local_expert(self):
|
145 |
+
return Agent(
|
146 |
+
role='Local Expert',
|
147 |
+
tools=[SearchTools.search_internet, BrowserTools.scrape_and_summarize_website],
|
148 |
+
llm=ollama_model,
|
149 |
+
verbose=True
|
150 |
+
)
|
151 |
+
|
152 |
+
```
|
153 |
+
|
154 |
+
## Benefits of Local Models
|
155 |
+
|
156 |
+
- **Privacy**: Process sensitive data in-house.
|
157 |
+
- **Customization**: Tailor models to fit specific needs.
|
158 |
+
- **Performance**: Potentially faster responses with on-premises models.
|
159 |
+
|
160 |
+
## License
|
161 |
+
|
162 |
+
VacAIgent is open-sourced under the MIT License.
|
163 |
+
|
164 |
+
|
165 |
+
|
166 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from crewai import Crew
|
2 |
+
from trip_agents import TripAgents, StreamToExpander
|
3 |
+
from trip_tasks import TripTasks
|
4 |
+
import streamlit as st
|
5 |
+
import datetime
|
6 |
+
import sys
|
7 |
+
|
8 |
+
st.set_page_config(page_icon="✈️", layout="wide")
|
9 |
+
|
10 |
+
|
11 |
+
def icon(emoji: str):
|
12 |
+
"""Shows an emoji as a Notion-style page icon."""
|
13 |
+
st.write(
|
14 |
+
f'<span style="font-size: 78px; line-height: 1">{emoji}</span>',
|
15 |
+
unsafe_allow_html=True,
|
16 |
+
)
|
17 |
+
|
18 |
+
|
19 |
+
class TripCrew:
|
20 |
+
|
21 |
+
def __init__(self, origin, cities, date_range, interests):
|
22 |
+
self.cities = cities
|
23 |
+
self.origin = origin
|
24 |
+
self.interests = interests
|
25 |
+
self.date_range = date_range
|
26 |
+
self.output_placeholder = st.empty()
|
27 |
+
|
28 |
+
def run(self):
|
29 |
+
agents = TripAgents()
|
30 |
+
tasks = TripTasks()
|
31 |
+
|
32 |
+
city_selector_agent = agents.city_selection_agent()
|
33 |
+
local_expert_agent = agents.local_expert()
|
34 |
+
travel_concierge_agent = agents.travel_concierge()
|
35 |
+
|
36 |
+
identify_task = tasks.identify_task(
|
37 |
+
city_selector_agent,
|
38 |
+
self.origin,
|
39 |
+
self.cities,
|
40 |
+
self.interests,
|
41 |
+
self.date_range
|
42 |
+
)
|
43 |
+
|
44 |
+
gather_task = tasks.gather_task(
|
45 |
+
local_expert_agent,
|
46 |
+
self.origin,
|
47 |
+
self.interests,
|
48 |
+
self.date_range
|
49 |
+
)
|
50 |
+
|
51 |
+
plan_task = tasks.plan_task(
|
52 |
+
travel_concierge_agent,
|
53 |
+
self.origin,
|
54 |
+
self.interests,
|
55 |
+
self.date_range
|
56 |
+
)
|
57 |
+
|
58 |
+
crew = Crew(
|
59 |
+
agents=[
|
60 |
+
city_selector_agent, local_expert_agent, travel_concierge_agent
|
61 |
+
],
|
62 |
+
tasks=[identify_task, gather_task, plan_task],
|
63 |
+
verbose=True
|
64 |
+
)
|
65 |
+
|
66 |
+
result = crew.kickoff()
|
67 |
+
self.output_placeholder.markdown(result)
|
68 |
+
|
69 |
+
return result
|
70 |
+
|
71 |
+
|
72 |
+
if __name__ == "__main__":
|
73 |
+
icon("🏖️ VacAIgent")
|
74 |
+
|
75 |
+
st.subheader("Let AI agents plan your next vacation!",
|
76 |
+
divider="rainbow", anchor=False)
|
77 |
+
|
78 |
+
import datetime
|
79 |
+
|
80 |
+
today = datetime.datetime.now().date()
|
81 |
+
next_year = today.year + 1
|
82 |
+
jan_16_next_year = datetime.date(next_year, 1, 10)
|
83 |
+
|
84 |
+
with st.sidebar:
|
85 |
+
st.header("👇 Enter your trip details")
|
86 |
+
with st.form("my_form"):
|
87 |
+
location = st.text_input(
|
88 |
+
"Where are you currently located?", placeholder="San Mateo, CA")
|
89 |
+
cities = st.text_input(
|
90 |
+
"City and country are you interested in vacationing at?", placeholder="Bali, Indonesia")
|
91 |
+
date_range = st.date_input(
|
92 |
+
"Date range you are interested in traveling?",
|
93 |
+
min_value=today,
|
94 |
+
value=(today, jan_16_next_year + datetime.timedelta(days=6)),
|
95 |
+
format="MM/DD/YYYY",
|
96 |
+
)
|
97 |
+
interests = st.text_area("High level interests and hobbies or extra details about your trip?",
|
98 |
+
placeholder="2 adults who love swimming, dancing, hiking, and eating")
|
99 |
+
|
100 |
+
submitted = st.form_submit_button("Submit")
|
101 |
+
|
102 |
+
st.divider()
|
103 |
+
|
104 |
+
# Credits to joaomdmoura/CrewAI for the code: https://github.com/joaomdmoura/crewAI
|
105 |
+
st.sidebar.markdown(
|
106 |
+
"""
|
107 |
+
Credits to [**@joaomdmoura**](https://twitter.com/joaomdmoura)
|
108 |
+
for creating **crewAI** 🚀
|
109 |
+
""",
|
110 |
+
unsafe_allow_html=True
|
111 |
+
)
|
112 |
+
|
113 |
+
st.sidebar.info("Click the logo to visit GitHub repo", icon="👇")
|
114 |
+
st.sidebar.markdown(
|
115 |
+
"""
|
116 |
+
<a href="https://github.com/joaomdmoura/crewAI" target="_blank">
|
117 |
+
<img src="https://raw.githubusercontent.com/joaomdmoura/crewAI/main/docs/crewai_logo.png" alt="CrewAI Logo" style="width:100px;"/>
|
118 |
+
</a>
|
119 |
+
""",
|
120 |
+
unsafe_allow_html=True
|
121 |
+
)
|
122 |
+
|
123 |
+
|
124 |
+
if submitted:
|
125 |
+
with st.status("🤖 **Agents at work...**", state="running", expanded=True) as status:
|
126 |
+
with st.container(height=500, border=False):
|
127 |
+
sys.stdout = StreamToExpander(st)
|
128 |
+
trip_crew = TripCrew(location, cities, date_range, interests)
|
129 |
+
result = trip_crew.run()
|
130 |
+
status.update(label="✅ Trip Plan Ready!",
|
131 |
+
state="complete", expanded=False)
|
132 |
+
|
133 |
+
st.subheader("Here is your Trip Plan", anchor=False, divider="rainbow")
|
134 |
+
st.markdown(result)
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
crewai==0.98.0
|
2 |
+
streamlit==1.41.1
|
3 |
+
openai==1.60.1
|
4 |
+
unstructured==0.16.15
|
5 |
+
pyowm==3.3.0
|
6 |
+
tools==0.1.9
|
7 |
+
langchain_community==0.3.15
|
tools/__init__.py
ADDED
File without changes
|
tools/browser_tools.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
|
3 |
+
import requests
|
4 |
+
import streamlit as st
|
5 |
+
from crewai import Agent, Task
|
6 |
+
from langchain.tools import tool
|
7 |
+
from unstructured.partition.html import partition_html
|
8 |
+
|
9 |
+
|
10 |
+
class BrowserTools():
|
11 |
+
|
12 |
+
@tool("Scrape website content")
|
13 |
+
def scrape_and_summarize_website(website):
|
14 |
+
"""Useful to scrape and summarize a website content"""
|
15 |
+
url = f"http://api.scrapingant.com/v2/general?url{website}&x-api-key={st.secrets['SCRAPINGANT_API_KEY']}"
|
16 |
+
payload = json.dumps({"url": website})
|
17 |
+
headers = {'cache-control': 'no-cache', 'content-type': 'application/json'}
|
18 |
+
response = requests.request("GET", url, headers=headers, data=payload)
|
19 |
+
elements = partition_html(text=response.text)
|
20 |
+
content = "\n\n".join([str(el) for el in elements])
|
21 |
+
content = [content[i:i + 8000] for i in range(0, len(content), 8000)]
|
22 |
+
summaries = []
|
23 |
+
for chunk in content:
|
24 |
+
agent = Agent(
|
25 |
+
role='Principal Researcher',
|
26 |
+
goal=
|
27 |
+
'Do amazing researches and summaries based on the content you are working with',
|
28 |
+
backstory=
|
29 |
+
"You're a Principal Researcher at a big company and you need to do a research about a given topic.",
|
30 |
+
allow_delegation=False)
|
31 |
+
task = Task(
|
32 |
+
agent=agent,
|
33 |
+
description=
|
34 |
+
f'Analyze and summarize the content bellow, make sure to include the most relevant information in the summary, return only the summary nothing else.\n\nCONTENT\n----------\n{chunk}'
|
35 |
+
)
|
36 |
+
summary = task.execute()
|
37 |
+
summaries.append(summary)
|
38 |
+
return "\n\n".join(summaries)
|
tools/calculator_tools.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain.tools import tool
|
2 |
+
|
3 |
+
|
4 |
+
class CalculatorTools():
|
5 |
+
|
6 |
+
@tool("Make a calcualtion")
|
7 |
+
def calculate(operation):
|
8 |
+
"""Useful to perform any mathematical calculations,
|
9 |
+
like sum, minus, multiplication, division, etc.
|
10 |
+
The input to this tool should be a mathematical
|
11 |
+
expression, a couple examples are `200*7` or `5000/2*10`
|
12 |
+
"""
|
13 |
+
return eval(operation)
|
tools/search_tools.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
|
3 |
+
import requests
|
4 |
+
import streamlit as st
|
5 |
+
from langchain.tools import tool
|
6 |
+
|
7 |
+
|
8 |
+
class SearchTools():
|
9 |
+
|
10 |
+
@tool("Search the internet")
|
11 |
+
def search_internet(query):
|
12 |
+
"""Useful to search the internet
|
13 |
+
about a a given topic and return relevant results"""
|
14 |
+
top_result_to_return = 4
|
15 |
+
url = "https://google.serper.dev/search"
|
16 |
+
payload = json.dumps({"q": query})
|
17 |
+
headers = {
|
18 |
+
'X-API-KEY': st.secrets['SERPER_API_KEY'],
|
19 |
+
'content-type': 'application/json'
|
20 |
+
}
|
21 |
+
response = requests.request("POST", url, headers=headers, data=payload)
|
22 |
+
# check if there is an organic key
|
23 |
+
if 'organic' not in response.json():
|
24 |
+
return "Sorry, I couldn't find anything about that, there could be an error with you serper api key."
|
25 |
+
else:
|
26 |
+
results = response.json()['organic']
|
27 |
+
string = []
|
28 |
+
for result in results[:top_result_to_return]:
|
29 |
+
try:
|
30 |
+
string.append('\n'.join([
|
31 |
+
f"Title: {result['title']}", f"Link: {result['link']}",
|
32 |
+
f"Snippet: {result['snippet']}", "\n-----------------"
|
33 |
+
]))
|
34 |
+
except KeyError:
|
35 |
+
next
|
36 |
+
|
37 |
+
return '\n'.join(string)
|
trip_agents.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from crewai import Agent
|
2 |
+
import re
|
3 |
+
import streamlit as st
|
4 |
+
from langchain_community.llms import OpenAI
|
5 |
+
|
6 |
+
from tools.browser_tools import BrowserTools
|
7 |
+
from tools.calculator_tools import CalculatorTools
|
8 |
+
from tools.search_tools import SearchTools
|
9 |
+
from crewai.llm import LLM
|
10 |
+
|
11 |
+
model_kwargs = {
|
12 |
+
"model": f"openai/{st.secrets['MODEL_ID']}",
|
13 |
+
"base_url": st.secrets["MODEL_BASE_URL"],
|
14 |
+
"api_key": st.secrets["OPENAI_API_KEY"]
|
15 |
+
}
|
16 |
+
llm = LLM(**model_kwargs) # Loading Llama
|
17 |
+
|
18 |
+
|
19 |
+
class TripAgents():
|
20 |
+
|
21 |
+
def city_selection_agent(self):
|
22 |
+
return Agent(
|
23 |
+
role='City Selection Expert',
|
24 |
+
goal='Select the best city based on weather, season, and prices',
|
25 |
+
backstory='An expert in analyzing travel data to pick ideal destinations',
|
26 |
+
tools=[
|
27 |
+
SearchTools.search_internet,
|
28 |
+
BrowserTools.scrape_and_summarize_website,
|
29 |
+
],
|
30 |
+
verbose=True,
|
31 |
+
llm=llm
|
32 |
+
# step_callback=streamlit_callback,
|
33 |
+
)
|
34 |
+
|
35 |
+
def local_expert(self):
|
36 |
+
return Agent(
|
37 |
+
role='Local Expert at this city',
|
38 |
+
goal='Provide the BEST insights about the selected city',
|
39 |
+
backstory="""A knowledgeable local guide with extensive information
|
40 |
+
about the city, it's attractions and customs""",
|
41 |
+
tools=[
|
42 |
+
SearchTools.search_internet,
|
43 |
+
BrowserTools.scrape_and_summarize_website,
|
44 |
+
],
|
45 |
+
verbose=True,
|
46 |
+
llm=llm
|
47 |
+
# step_callback=streamlit_callback,
|
48 |
+
)
|
49 |
+
|
50 |
+
def travel_concierge(self):
|
51 |
+
return Agent(
|
52 |
+
role='Amazing Travel Concierge',
|
53 |
+
goal="""Create the most amazing travel itineraries with budget and
|
54 |
+
packing suggestions for the city""",
|
55 |
+
backstory="""Specialist in travel planning and logistics with
|
56 |
+
decades of experience""",
|
57 |
+
tools=[
|
58 |
+
SearchTools.search_internet,
|
59 |
+
BrowserTools.scrape_and_summarize_website,
|
60 |
+
CalculatorTools.calculate,
|
61 |
+
],
|
62 |
+
verbose=True,
|
63 |
+
llm=llm
|
64 |
+
# step_callback=streamlit_callback,
|
65 |
+
)
|
66 |
+
|
67 |
+
class StreamToExpander:
|
68 |
+
def __init__(self, expander):
|
69 |
+
self.expander = expander
|
70 |
+
self.buffer = []
|
71 |
+
self.colors = ['red', 'green', 'blue', 'orange'] # Define a list of colors
|
72 |
+
self.color_index = 0 # Initialize color index
|
73 |
+
|
74 |
+
def write(self, data):
|
75 |
+
# Filter out ANSI escape codes using a regular expression
|
76 |
+
cleaned_data = re.sub(r'\x1B\[[0-9;]*[mK]', '', data)
|
77 |
+
|
78 |
+
# Check if the data contains 'task' information
|
79 |
+
task_match_object = re.search(r'\"task\"\s*:\s*\"(.*?)\"', cleaned_data, re.IGNORECASE)
|
80 |
+
task_match_input = re.search(r'task\s*:\s*([^\n]*)', cleaned_data, re.IGNORECASE)
|
81 |
+
task_value = None
|
82 |
+
if task_match_object:
|
83 |
+
task_value = task_match_object.group(1)
|
84 |
+
elif task_match_input:
|
85 |
+
task_value = task_match_input.group(1).strip()
|
86 |
+
|
87 |
+
if task_value:
|
88 |
+
st.toast(":robot_face: " + task_value)
|
89 |
+
|
90 |
+
# Check if the text contains the specified phrase and apply color
|
91 |
+
if "Entering new CrewAgentExecutor chain" in cleaned_data:
|
92 |
+
# Apply different color and switch color index
|
93 |
+
self.color_index = (self.color_index + 1) % len(self.colors) # Increment color index and wrap around if necessary
|
94 |
+
|
95 |
+
cleaned_data = cleaned_data.replace("Entering new CrewAgentExecutor chain", f":{self.colors[self.color_index]}[Entering new CrewAgentExecutor chain]")
|
96 |
+
|
97 |
+
if "City Selection Expert" in cleaned_data:
|
98 |
+
# Apply different color
|
99 |
+
cleaned_data = cleaned_data.replace("City Selection Expert", f":{self.colors[self.color_index]}[City Selection Expert]")
|
100 |
+
if "Local Expert at this city" in cleaned_data:
|
101 |
+
cleaned_data = cleaned_data.replace("Local Expert at this city", f":{self.colors[self.color_index]}[Local Expert at this city]")
|
102 |
+
if "Amazing Travel Concierge" in cleaned_data:
|
103 |
+
cleaned_data = cleaned_data.replace("Amazing Travel Concierge", f":{self.colors[self.color_index]}[Amazing Travel Concierge]")
|
104 |
+
if "Finished chain." in cleaned_data:
|
105 |
+
cleaned_data = cleaned_data.replace("Finished chain.", f":{self.colors[self.color_index]}[Finished chain.]")
|
106 |
+
|
107 |
+
self.buffer.append(cleaned_data)
|
108 |
+
if "\n" in data:
|
109 |
+
self.expander.markdown(''.join(self.buffer), unsafe_allow_html=True)
|
110 |
+
self.buffer = []
|
trip_tasks.py
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from crewai import Task
|
2 |
+
from textwrap import dedent
|
3 |
+
from datetime import date
|
4 |
+
|
5 |
+
|
6 |
+
class TripTasks():
|
7 |
+
|
8 |
+
def identify_task(self, agent, origin, cities, interests, range):
|
9 |
+
return Task(description=dedent(f"""
|
10 |
+
Analyze and select the best city for the trip based
|
11 |
+
on specific criteria such as weather patterns, seasonal
|
12 |
+
events, and travel costs. This task involves comparing
|
13 |
+
multiple cities, considering factors like current weather
|
14 |
+
conditions, upcoming cultural or seasonal events, and
|
15 |
+
overall travel expenses.
|
16 |
+
|
17 |
+
Your final answer must be a detailed
|
18 |
+
report on the chosen city, and everything you found out
|
19 |
+
about it, including the actual flight costs, weather
|
20 |
+
forecast and attractions.
|
21 |
+
{self.__tip_section()}
|
22 |
+
|
23 |
+
Traveling from: {origin}
|
24 |
+
City Options: {cities}
|
25 |
+
Trip Date: {range}
|
26 |
+
Traveler Interests: {interests}
|
27 |
+
"""),
|
28 |
+
expected_output="A detailed report on the chosen city with flight costs, weather forecast, and attractions.",
|
29 |
+
agent=agent)
|
30 |
+
|
31 |
+
def gather_task(self, agent, origin, interests, range):
|
32 |
+
return Task(description=dedent(f"""
|
33 |
+
As a local expert on this city you must compile an
|
34 |
+
in-depth guide for someone traveling there and wanting
|
35 |
+
to have THE BEST trip ever!
|
36 |
+
Gather information about key attractions, local customs,
|
37 |
+
special events, and daily activity recommendations.
|
38 |
+
Find the best spots to go to, the kind of place only a
|
39 |
+
local would know.
|
40 |
+
This guide should provide a thorough overview of what
|
41 |
+
the city has to offer, including hidden gems, cultural
|
42 |
+
hotspots, must-visit landmarks, weather forecasts, and
|
43 |
+
high level costs.
|
44 |
+
|
45 |
+
The final answer must be a comprehensive city guide,
|
46 |
+
rich in cultural insights and practical tips,
|
47 |
+
tailored to enhance the travel experience.
|
48 |
+
{self.__tip_section()}
|
49 |
+
|
50 |
+
Trip Date: {range}
|
51 |
+
Traveling from: {origin}
|
52 |
+
Traveler Interests: {interests}
|
53 |
+
"""),
|
54 |
+
expected_output="A comprehensive city guide with cultural insights and practical tips.",
|
55 |
+
agent=agent)
|
56 |
+
|
57 |
+
def plan_task(self, agent, origin, interests, range):
|
58 |
+
return Task(description=dedent(f"""
|
59 |
+
Expand this guide into a full travel
|
60 |
+
itinerary for this time {range} with detailed per-day plans, including
|
61 |
+
weather forecasts, places to eat, packing suggestions,
|
62 |
+
and a budget breakdown.
|
63 |
+
|
64 |
+
You MUST suggest actual places to visit, actual hotels
|
65 |
+
to stay and actual restaurants to go to.
|
66 |
+
|
67 |
+
This itinerary should cover all aspects of the trip,
|
68 |
+
from arrival to departure, integrating the city guide
|
69 |
+
information with practical travel logistics.
|
70 |
+
|
71 |
+
Your final answer MUST be a complete expanded travel plan,
|
72 |
+
formatted as markdown, encompassing a daily schedule,
|
73 |
+
anticipated weather conditions, recommended clothing and
|
74 |
+
items to pack, and a detailed budget, ensuring THE BEST
|
75 |
+
TRIP EVER, Be specific and give it a reason why you picked
|
76 |
+
# up each place, what make them special! {self.__tip_section()}
|
77 |
+
|
78 |
+
Trip Date: {range}
|
79 |
+
Traveling from: {origin}
|
80 |
+
Traveler Interests: {interests}
|
81 |
+
"""),
|
82 |
+
expected_output="A complete 7-day travel plan, formatted as markdown, with a daily schedule and budget.",
|
83 |
+
agent=agent)
|
84 |
+
|
85 |
+
def __tip_section(self):
|
86 |
+
return "If you do your BEST WORK, I'll tip you $100 and grant you any wish you want!"
|