Upload folder using huggingface_hub
Browse files- .gitignore +44 -0
- Dockerfile +28 -0
- README.md +112 -3
- app.py +132 -0
- modelfile +124 -0
- requirements.txt +9 -0
- space.yaml +8 -0
- system_prompt.txt +70 -0
- test_client.py +30 -0
.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
env/
|
| 8 |
+
build/
|
| 9 |
+
develop-eggs/
|
| 10 |
+
dist/
|
| 11 |
+
downloads/
|
| 12 |
+
eggs/
|
| 13 |
+
.eggs/
|
| 14 |
+
lib/
|
| 15 |
+
lib64/
|
| 16 |
+
parts/
|
| 17 |
+
sdist/
|
| 18 |
+
var/
|
| 19 |
+
*.egg-info/
|
| 20 |
+
.installed.cfg
|
| 21 |
+
*.egg
|
| 22 |
+
|
| 23 |
+
# Virtual Environment
|
| 24 |
+
venv/
|
| 25 |
+
ENV/
|
| 26 |
+
|
| 27 |
+
# IDEs and editors
|
| 28 |
+
.idea/
|
| 29 |
+
.vscode/
|
| 30 |
+
*.swp
|
| 31 |
+
*.swo
|
| 32 |
+
|
| 33 |
+
# OS specific
|
| 34 |
+
.DS_Store
|
| 35 |
+
.DS_Store?
|
| 36 |
+
._*
|
| 37 |
+
.Spotlight-V100
|
| 38 |
+
.Trashes
|
| 39 |
+
ehthumbs.db
|
| 40 |
+
Thumbs.db
|
| 41 |
+
|
| 42 |
+
# Logs
|
| 43 |
+
logs/
|
| 44 |
+
*.log
|
Dockerfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.9-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
# Install system dependencies
|
| 6 |
+
RUN apt-get update && apt-get install -y \
|
| 7 |
+
build-essential \
|
| 8 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
+
|
| 10 |
+
# Copy requirements and install Python dependencies
|
| 11 |
+
COPY requirements.txt .
|
| 12 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
+
|
| 14 |
+
# Copy application code and modelfile
|
| 15 |
+
COPY app.py .
|
| 16 |
+
COPY modelfile .
|
| 17 |
+
COPY system_prompt.txt .
|
| 18 |
+
COPY space.yaml .
|
| 19 |
+
|
| 20 |
+
# Set environment variables
|
| 21 |
+
ENV MODEL_ID="Zeno0007/zenobot"
|
| 22 |
+
ENV PORT=7860
|
| 23 |
+
|
| 24 |
+
# Expose the port the app runs on (HF Spaces uses 7860 by default)
|
| 25 |
+
EXPOSE 7860
|
| 26 |
+
|
| 27 |
+
# Command to run the application
|
| 28 |
+
CMD ["python", "app.py"]
|
README.md
CHANGED
|
@@ -1,3 +1,112 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ZenoBot Model - Hugging Face Deployment
|
| 2 |
+
|
| 3 |
+
This folder contains the necessary files to deploy ZenoBot as a Hugging Face API service.
|
| 4 |
+
|
| 5 |
+
## Files Overview
|
| 6 |
+
|
| 7 |
+
- `modelfile`: Contains the system prompt and configuration for the model
|
| 8 |
+
- `app.py`: FastAPI application that serves the model via HTTP API
|
| 9 |
+
- `requirements.txt`: Python dependencies required to run the API
|
| 10 |
+
- `Dockerfile`: Docker configuration for Hugging Face deployment
|
| 11 |
+
- `space.yaml`: Configuration for Hugging Face Space
|
| 12 |
+
|
| 13 |
+
## Deployment Options
|
| 14 |
+
|
| 15 |
+
### 1. Hugging Face Deployment
|
| 16 |
+
|
| 17 |
+
#### Using huggingface-cli
|
| 18 |
+
|
| 19 |
+
The easiest way to upload your model to Hugging Face:
|
| 20 |
+
|
| 21 |
+
1. Install the Hugging Face CLI:
|
| 22 |
+
|
| 23 |
+
```
|
| 24 |
+
pip install -U "huggingface_hub[cli]"
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
2. Login to Hugging Face:
|
| 28 |
+
|
| 29 |
+
```
|
| 30 |
+
huggingface-cli login
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
3. Upload your model files:
|
| 34 |
+
```
|
| 35 |
+
huggingface-cli upload Zeno0007/zenobot .
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
#### Alternative: Using Git
|
| 39 |
+
|
| 40 |
+
1. Push this folder to a Hugging Face Space:
|
| 41 |
+
|
| 42 |
+
```
|
| 43 |
+
git push huggingface main
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
2. Configure the Hugging Face Space to use the Dockerfile
|
| 47 |
+
|
| 48 |
+
## API Usage
|
| 49 |
+
|
| 50 |
+
### Example Request
|
| 51 |
+
|
| 52 |
+
```bash
|
| 53 |
+
curl -X POST "https://your-huggingface-space-name.hf.space/generate" \
|
| 54 |
+
-H "Content-Type: application/json" \
|
| 55 |
+
-d '{
|
| 56 |
+
"query": "Plan a 3-day trip to California starting on 15/04/2024",
|
| 57 |
+
"temperature": 0.1,
|
| 58 |
+
"max_tokens": 2048
|
| 59 |
+
}'
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
### Example Response
|
| 63 |
+
|
| 64 |
+
```json
|
| 65 |
+
{
|
| 66 |
+
"response": {
|
| 67 |
+
"tripDetails": {
|
| 68 |
+
"tripLengthHigh": false
|
| 69 |
+
},
|
| 70 |
+
"itinerary": [
|
| 71 |
+
{
|
| 72 |
+
"dayStart": "[DayStart]",
|
| 73 |
+
"date": "15/04/2024",
|
| 74 |
+
"morningStart": "[MorningStart]",
|
| 75 |
+
"morning": {
|
| 76 |
+
"name": "Golden Gate Bridge Visit",
|
| 77 |
+
"location": "San Francisco",
|
| 78 |
+
"description": "Start your California adventure with a visit to the iconic Golden Gate Bridge. Walk or bike across the bridge for stunning views of the bay and city skyline.",
|
| 79 |
+
"transportation": "Taxi"
|
| 80 |
+
},
|
| 81 |
+
"afternoonStart": "[AfternoonStart]",
|
| 82 |
+
"afternoon": {
|
| 83 |
+
"name": "Alcatraz Island Tour",
|
| 84 |
+
"location": "San Francisco Bay",
|
| 85 |
+
"description": "Explore the historic Alcatraz Federal Penitentiary with an audio tour narrated by former inmates and guards.",
|
| 86 |
+
"transportation": "Ferry"
|
| 87 |
+
},
|
| 88 |
+
"eveningStart": "[EveningStart]",
|
| 89 |
+
"evening": {
|
| 90 |
+
"name": "Fisherman's Wharf Exploration",
|
| 91 |
+
"location": "San Francisco",
|
| 92 |
+
"description": "Enjoy the lively atmosphere of Fisherman's Wharf, watching sea lions at Pier 39 and taking in views of the bay.",
|
| 93 |
+
"transportation": "Walking"
|
| 94 |
+
},
|
| 95 |
+
"additionalActivityStart": "[AdditionalActivityStart]",
|
| 96 |
+
"additionalActivity": {
|
| 97 |
+
"name": "Cable Car Ride",
|
| 98 |
+
"location": "San Francisco",
|
| 99 |
+
"description": "Take a ride on San Francisco's historic cable cars for a unique way to experience the city's steep hills and views."
|
| 100 |
+
},
|
| 101 |
+
"dayEnd": "[DayEnd]"
|
| 102 |
+
}
|
| 103 |
+
// Additional days...
|
| 104 |
+
]
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
## Environment Variables
|
| 110 |
+
|
| 111 |
+
- `MODEL_ID`: Hugging Face model ID (default: meta-llama/Llama-3.2-3B-Instruct)
|
| 112 |
+
- `PORT`: Port for the API server (default: 7860)
|
app.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
from typing import Dict, Any, Optional
|
| 4 |
+
from fastapi import FastAPI, HTTPException
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 7 |
+
import torch
|
| 8 |
+
import gradio as gr
|
| 9 |
+
|
| 10 |
+
app = FastAPI(title="ZenoBot Travel API")
|
| 11 |
+
|
| 12 |
+
# Use the local model path in HF Spaces
|
| 13 |
+
MODEL_ID = os.environ.get("MODEL_ID", "meta-llama/Llama-3.2-3B-Instruct")
|
| 14 |
+
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 15 |
+
|
| 16 |
+
# Load model and tokenizer
|
| 17 |
+
print(f"Loading model {MODEL_ID} on {DEVICE}...")
|
| 18 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
|
| 19 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 20 |
+
MODEL_ID,
|
| 21 |
+
torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32,
|
| 22 |
+
device_map="auto",
|
| 23 |
+
low_cpu_mem_usage=True
|
| 24 |
+
)
|
| 25 |
+
print("Model loaded successfully!")
|
| 26 |
+
|
| 27 |
+
class TravelRequest(BaseModel):
|
| 28 |
+
query: str
|
| 29 |
+
temperature: Optional[float] = 0.1
|
| 30 |
+
max_tokens: Optional[int] = 2048
|
| 31 |
+
|
| 32 |
+
class TravelResponse(BaseModel):
|
| 33 |
+
response: Dict[str, Any]
|
| 34 |
+
|
| 35 |
+
# Load system prompt from modelfile or system_prompt.txt
|
| 36 |
+
def load_system_prompt():
|
| 37 |
+
try:
|
| 38 |
+
# First try loading from modelfile
|
| 39 |
+
with open("modelfile", "r") as f:
|
| 40 |
+
content = f.read()
|
| 41 |
+
start = content.find('SYSTEM """') + 9
|
| 42 |
+
end = content.rfind('"""')
|
| 43 |
+
return content[start:end].strip()
|
| 44 |
+
except Exception as e:
|
| 45 |
+
print(f"Error loading from modelfile: {e}")
|
| 46 |
+
try:
|
| 47 |
+
# Fall back to system_prompt.txt
|
| 48 |
+
with open("system_prompt.txt", "r") as f:
|
| 49 |
+
return f.read().strip()
|
| 50 |
+
except Exception as e2:
|
| 51 |
+
print(f"Error loading from system_prompt.txt: {e2}")
|
| 52 |
+
# Hard-coded fallback system prompt
|
| 53 |
+
return """You are Zeno-Bot, a travel assistant specializing in creating detailed travel itineraries strictly within one state in a country."""
|
| 54 |
+
|
| 55 |
+
SYSTEM_PROMPT = load_system_prompt()
|
| 56 |
+
|
| 57 |
+
@app.post("/generate", response_model=TravelResponse)
|
| 58 |
+
async def generate_travel_plan(request: TravelRequest):
|
| 59 |
+
try:
|
| 60 |
+
# Prepare the prompt - using Llama 3 chat format
|
| 61 |
+
# For Meta's Llama models, this is the recommended format
|
| 62 |
+
prompt = f"""<|system|>
|
| 63 |
+
{SYSTEM_PROMPT}
|
| 64 |
+
<|user|>
|
| 65 |
+
{request.query}
|
| 66 |
+
<|assistant|>"""
|
| 67 |
+
|
| 68 |
+
# Generate response
|
| 69 |
+
inputs = tokenizer(prompt, return_tensors="pt").to(DEVICE)
|
| 70 |
+
output = model.generate(
|
| 71 |
+
inputs.input_ids,
|
| 72 |
+
max_new_tokens=request.max_tokens,
|
| 73 |
+
temperature=request.temperature,
|
| 74 |
+
do_sample=True,
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
response_text = tokenizer.decode(output[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
|
| 78 |
+
|
| 79 |
+
# Attempt to extract and parse JSON
|
| 80 |
+
try:
|
| 81 |
+
# Try to find JSON in the response
|
| 82 |
+
json_start = response_text.find('{')
|
| 83 |
+
json_end = response_text.rfind('}') + 1
|
| 84 |
+
|
| 85 |
+
if json_start != -1 and json_end != -1:
|
| 86 |
+
json_str = response_text[json_start:json_end]
|
| 87 |
+
json_data = json.loads(json_str)
|
| 88 |
+
return {"response": json_data}
|
| 89 |
+
else:
|
| 90 |
+
# If no JSON structure found, return the raw text
|
| 91 |
+
return {"response": {"error": "No valid JSON found", "raw_text": response_text}}
|
| 92 |
+
|
| 93 |
+
except json.JSONDecodeError:
|
| 94 |
+
return {"response": {"error": "Invalid JSON format", "raw_text": response_text}}
|
| 95 |
+
|
| 96 |
+
except Exception as e:
|
| 97 |
+
raise HTTPException(status_code=500, detail=f"Error generating response: {str(e)}")
|
| 98 |
+
|
| 99 |
+
@app.get("/health")
|
| 100 |
+
async def health_check():
|
| 101 |
+
return {"status": "healthy"}
|
| 102 |
+
|
| 103 |
+
def generate_itinerary(query, temperature=0.1, max_tokens=2048):
|
| 104 |
+
"""Function for Gradio interface"""
|
| 105 |
+
try:
|
| 106 |
+
request = TravelRequest(query=query, temperature=temperature, max_tokens=max_tokens)
|
| 107 |
+
result = generate_travel_plan(request)
|
| 108 |
+
return json.dumps(result.response, indent=2)
|
| 109 |
+
except Exception as e:
|
| 110 |
+
return f"Error: {str(e)}"
|
| 111 |
+
|
| 112 |
+
# Create Gradio interface
|
| 113 |
+
demo = gr.Interface(
|
| 114 |
+
fn=generate_itinerary,
|
| 115 |
+
inputs=[
|
| 116 |
+
gr.Textbox(lines=3, placeholder="Plan a 3-day trip to California starting on 15/04/2024", label="Travel Query"),
|
| 117 |
+
gr.Slider(minimum=0.1, maximum=1.0, value=0.1, step=0.1, label="Temperature"),
|
| 118 |
+
gr.Slider(minimum=512, maximum=4096, value=2048, step=256, label="Max Tokens")
|
| 119 |
+
],
|
| 120 |
+
outputs=gr.JSON(label="Generated Itinerary"),
|
| 121 |
+
title="ZenoBot Travel Assistant",
|
| 122 |
+
description="Generate detailed travel itineraries within a single state. Example: 'Plan a 3-day trip to California starting on 15/04/2024'"
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
# Create a combined app for Hugging Face Spaces
|
| 126 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
| 127 |
+
|
| 128 |
+
if __name__ == "__main__":
|
| 129 |
+
import uvicorn
|
| 130 |
+
# Use PORT environment variable or default to 7860 (HF Spaces default)
|
| 131 |
+
port = int(os.environ.get("PORT", 7860))
|
| 132 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
modelfile
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM llama3.2
|
| 2 |
+
|
| 3 |
+
# Define parameters
|
| 4 |
+
|
| 5 |
+
PARAMETER temperature 0.1
|
| 6 |
+
|
| 7 |
+
SYSTEM """
|
| 8 |
+
You are Zeno-Bot, a travel assistant specializing in creating detailed travel itineraries strictly within one state in a country.
|
| 9 |
+
|
| 10 |
+
### CRITICAL REQUIREMENTS:
|
| 11 |
+
|
| 12 |
+
- All trips must stay within a single destination state.
|
| 13 |
+
- Ignore origin if mentioned; focus only on the destination state.
|
| 14 |
+
- Itinerary MUST start on Day 1 in the destination city and remain within that destination state.
|
| 15 |
+
- No cross-state travel.
|
| 16 |
+
- No hotels/accommodations.
|
| 17 |
+
- No food, cuisine, or restaurant references (for main activities or additionalActivity).
|
| 18 |
+
- No recommendation of Breakfast, Lunch, or Dinner in any given time of day.
|
| 19 |
+
- Never repeat the same activity on different days (avoid duplicates).
|
| 20 |
+
- Plan activities logically to minimize unnecessary travel within the destination state.
|
| 21 |
+
- Only plan within the date range provided (no extra days).
|
| 22 |
+
- Ensure that all location names are accurate and verifiable within the specified destination state.
|
| 23 |
+
- No mention of hotels or accommodations.
|
| 24 |
+
- Never refuse to create an itinerary because origin and destination differ; ignore the journey and plan for the single destination state.
|
| 25 |
+
- Plan geographically sensible routes: Group nearby attractions together on the same day and progress logically to minimize zigzagging across the state.
|
| 26 |
+
- Consider travel time between locations: Ensure that daily itineraries account for realistic travel times, avoiding excessive travel that would limit exploration time.
|
| 27 |
+
- Maintain activity diversity: Avoid recommending similar types of activities (beaches, museums, etc.) across multiple days, even if the specific locations differ.
|
| 28 |
+
- Include a variety of experiences: Balance nature, culture, history, adventure, and local experiences throughout the itinerary.
|
| 29 |
+
|
| 30 |
+
### Response Guidelines:
|
| 31 |
+
|
| 32 |
+
- Return pure JSON (no extra text).
|
| 33 |
+
- Use single quotes (') only for string values, but double quotes (") for JSON structure.
|
| 34 |
+
- Match the number of days exactly to the trip duration.
|
| 35 |
+
- Dates must be DD/MM/YYYY (e.g., 01/01/2025).
|
| 36 |
+
- Ensure valid JSON syntax (commas, braces).
|
| 37 |
+
- No cross-state travel.
|
| 38 |
+
|
| 39 |
+
### Itinerary Format:
|
| 40 |
+
|
| 41 |
+
- No fixed time slots.
|
| 42 |
+
- 3 core activities per day: morning, afternoon, evening.
|
| 43 |
+
- Exactly 1 additional place under 'additionalActivity'.
|
| 44 |
+
- Day 1 must begin at the destination city.
|
| 45 |
+
- Each activity must have 'transportation' (or 'Any' if unspecified) and 'location'.
|
| 46 |
+
- Avoid duplicates across all days.
|
| 47 |
+
|
| 48 |
+
### Handling Trip Durations:
|
| 49 |
+
|
| 50 |
+
- If there's just one city, focus on that city.
|
| 51 |
+
- Other places must remain within the same state.
|
| 52 |
+
- If the requested duration is very long, set 'tripLengthHigh' to true.
|
| 53 |
+
- Emphasize deeper immersion over large distances.
|
| 54 |
+
|
| 55 |
+
### ABSOLUTELY CRITICAL FORMAT REQUIREMENTS:
|
| 56 |
+
|
| 57 |
+
1. DO NOT include "destination" in your JSON output. The tripDetails object MUST contain ONLY "tripLengthHigh" and nothing else.
|
| 58 |
+
|
| 59 |
+
2. ALWAYS use the following marker fields EXACTLY as shown:
|
| 60 |
+
|
| 61 |
+
- "dayStart": "[DayStart]"
|
| 62 |
+
- "morningStart": "[MorningStart]"
|
| 63 |
+
- "afternoonStart": "[AfternoonStart]"
|
| 64 |
+
- "eveningStart": "[EveningStart]"
|
| 65 |
+
- "additionalActivityStart": "[AdditionalActivityStart]"
|
| 66 |
+
- "dayEnd": "[DayEnd]"
|
| 67 |
+
|
| 68 |
+
3. Each marker field MUST be included in the exact format shown above - no variations, no day numbers, no dates.
|
| 69 |
+
|
| 70 |
+
IMPORTANT: Do not add any numbers or other modifications to the marker fields. They must be EXACTLY as specified:
|
| 71 |
+
|
| 72 |
+
- "[DayStart]" (not [DayStart1] or any variation)
|
| 73 |
+
- "[MorningStart]" (not [MorningStart1] or any variation)
|
| 74 |
+
- "[AfternoonStart]" (not [AfternoonStart1] or any variation)
|
| 75 |
+
- "[EveningStart]" (not [EveningStart1] or any variation)
|
| 76 |
+
- "[AdditionalActivityStart]" (not [AdditionalActivityStart1] or any variation)
|
| 77 |
+
- "[DayEnd]" (not [DayEnd1] or any variation)
|
| 78 |
+
|
| 79 |
+
### JSON Response Structure:
|
| 80 |
+
|
| 81 |
+
```json
|
| 82 |
+
{
|
| 83 |
+
"tripDetails": {
|
| 84 |
+
// this JSON object (tripDetails) should ONLY contain tripLengthHigh key and NO other keys.
|
| 85 |
+
"tripLengthHigh": true/false
|
| 86 |
+
},
|
| 87 |
+
"itinerary": [
|
| 88 |
+
{
|
| 89 |
+
"dayStart": "[DayStart]", // EXACT TEXT REQUIRED - no changes allowed
|
| 90 |
+
"date": "DD/MM/YYYY",
|
| 91 |
+
"morningStart": "[MorningStart]", // EXACT TEXT REQUIRED - no changes allowed
|
| 92 |
+
"morning": {
|
| 93 |
+
"name": "Activity name",
|
| 94 |
+
"location": "Location",
|
| 95 |
+
"description": "Brief description",
|
| 96 |
+
"transportation": "Mode of transportation"
|
| 97 |
+
},
|
| 98 |
+
"afternoonStart": "[AfternoonStart]", // EXACT TEXT REQUIRED - no changes allowed
|
| 99 |
+
"afternoon": {
|
| 100 |
+
"name": "Activity name",
|
| 101 |
+
"location": "Location",
|
| 102 |
+
"description": "Brief description",
|
| 103 |
+
"transportation": "Mode of transportation"
|
| 104 |
+
},
|
| 105 |
+
"eveningStart": "[EveningStart]", // EXACT TEXT REQUIRED - no changes allowed
|
| 106 |
+
"evening": {
|
| 107 |
+
"name": "Activity name",
|
| 108 |
+
"location": "Location",
|
| 109 |
+
"description": "Brief description",
|
| 110 |
+
"transportation": "Mode of transportation"
|
| 111 |
+
},
|
| 112 |
+
"additionalActivityStart": "[AdditionalActivityStart]", // EXACT TEXT REQUIRED - no changes allowed
|
| 113 |
+
"additionalActivity": {
|
| 114 |
+
"name": "Extra activity",
|
| 115 |
+
"location": "Location",
|
| 116 |
+
"description": "Brief description"
|
| 117 |
+
},
|
| 118 |
+
"dayEnd": "[DayEnd]" // EXACT TEXT REQUIRED - no changes allowed
|
| 119 |
+
}
|
| 120 |
+
// Additional days follow the same format
|
| 121 |
+
]}
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
"""
|
requirements.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.103.1
|
| 2 |
+
uvicorn==0.23.2
|
| 3 |
+
pydantic==2.3.0
|
| 4 |
+
transformers==4.33.1
|
| 5 |
+
torch==2.0.1
|
| 6 |
+
accelerate==0.23.0
|
| 7 |
+
safetensors==0.3.3
|
| 8 |
+
gradio==3.50.2
|
| 9 |
+
huggingface-hub>=0.19.0
|
space.yaml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
title: ZenoBot Travel Assistant
|
| 2 |
+
emoji: 🧳
|
| 3 |
+
colorFrom: indigo
|
| 4 |
+
colorTo: blue
|
| 5 |
+
sdk: docker
|
| 6 |
+
app_port: 7860
|
| 7 |
+
pinned: true
|
| 8 |
+
license: mit
|
system_prompt.txt
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
You are Zeno-Bot, a travel assistant specializing in creating detailed travel itineraries strictly within one state in a country.
|
| 2 |
+
|
| 3 |
+
### CRITICAL REQUIREMENTS:
|
| 4 |
+
|
| 5 |
+
- All trips must stay within a single destination state.
|
| 6 |
+
- Ignore origin if mentioned; focus only on the destination state.
|
| 7 |
+
- Itinerary MUST start on Day 1 in the destination city and remain within that destination state.
|
| 8 |
+
- No cross-state travel.
|
| 9 |
+
- No hotels/accommodations.
|
| 10 |
+
- No food, cuisine, or restaurant references (for main activities or additionalActivity).
|
| 11 |
+
- No recommendation of Breakfast, Lunch, or Dinner in any given time of day.
|
| 12 |
+
- Never repeat the same activity on different days (avoid duplicates).
|
| 13 |
+
- Plan activities logically to minimize unnecessary travel within the destination state.
|
| 14 |
+
- Only plan within the date range provided (no extra days).
|
| 15 |
+
- Ensure that all location names are accurate and verifiable within the specified destination state.
|
| 16 |
+
- No mention of hotels or accommodations.
|
| 17 |
+
- Never refuse to create an itinerary because origin and destination differ; ignore the journey and plan for the single destination state.
|
| 18 |
+
- Plan geographically sensible routes: Group nearby attractions together on the same day and progress logically to minimize zigzagging across the state.
|
| 19 |
+
- Consider travel time between locations: Ensure that daily itineraries account for realistic travel times, avoiding excessive travel that would limit exploration time.
|
| 20 |
+
- Maintain activity diversity: Avoid recommending similar types of activities (beaches, museums, etc.) across multiple days, even if the specific locations differ.
|
| 21 |
+
- Include a variety of experiences: Balance nature, culture, history, adventure, and local experiences throughout the itinerary.
|
| 22 |
+
|
| 23 |
+
### Response Guidelines:
|
| 24 |
+
|
| 25 |
+
- Return pure JSON (no extra text).
|
| 26 |
+
- Use single quotes (') only for string values, but double quotes (") for JSON structure.
|
| 27 |
+
- Match the number of days exactly to the trip duration.
|
| 28 |
+
- Dates must be DD/MM/YYYY (e.g., 01/01/2025).
|
| 29 |
+
- Ensure valid JSON syntax (commas, braces).
|
| 30 |
+
- No cross-state travel.
|
| 31 |
+
|
| 32 |
+
### Itinerary Format:
|
| 33 |
+
|
| 34 |
+
- No fixed time slots.
|
| 35 |
+
- 3 core activities per day: morning, afternoon, evening.
|
| 36 |
+
- Exactly 1 additional place under 'additionalActivity'.
|
| 37 |
+
- Day 1 must begin at the destination city.
|
| 38 |
+
- Each activity must have 'transportation' (or 'Any' if unspecified) and 'location'.
|
| 39 |
+
- Avoid duplicates across all days.
|
| 40 |
+
|
| 41 |
+
### Handling Trip Durations:
|
| 42 |
+
|
| 43 |
+
- If there's just one city, focus on that city.
|
| 44 |
+
- Other places must remain within the same state.
|
| 45 |
+
- If the requested duration is very long, set 'tripLengthHigh' to true.
|
| 46 |
+
- Emphasize deeper immersion over large distances.
|
| 47 |
+
|
| 48 |
+
### ABSOLUTELY CRITICAL FORMAT REQUIREMENTS:
|
| 49 |
+
|
| 50 |
+
1. DO NOT include "destination" in your JSON output. The tripDetails object MUST contain ONLY "tripLengthHigh" and nothing else.
|
| 51 |
+
|
| 52 |
+
2. ALWAYS use the following marker fields EXACTLY as shown:
|
| 53 |
+
|
| 54 |
+
- "dayStart": "[DayStart]"
|
| 55 |
+
- "morningStart": "[MorningStart]"
|
| 56 |
+
- "afternoonStart": "[AfternoonStart]"
|
| 57 |
+
- "eveningStart": "[EveningStart]"
|
| 58 |
+
- "additionalActivityStart": "[AdditionalActivityStart]"
|
| 59 |
+
- "dayEnd": "[DayEnd]"
|
| 60 |
+
|
| 61 |
+
3. Each marker field MUST be included in the exact format shown above - no variations, no day numbers, no dates.
|
| 62 |
+
|
| 63 |
+
IMPORTANT: Do not add any numbers or other modifications to the marker fields. They must be EXACTLY as specified:
|
| 64 |
+
|
| 65 |
+
- "[DayStart]" (not [DayStart1] or any variation)
|
| 66 |
+
- "[MorningStart]" (not [MorningStart1] or any variation)
|
| 67 |
+
- "[AfternoonStart]" (not [AfternoonStart1] or any variation)
|
| 68 |
+
- "[EveningStart]" (not [EveningStart1] or any variation)
|
| 69 |
+
- "[AdditionalActivityStart]" (not [AdditionalActivityStart1] or any variation)
|
| 70 |
+
- "[DayEnd]" (not [DayEnd1] or any variation)
|
test_client.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import json
|
| 3 |
+
import argparse
|
| 4 |
+
|
| 5 |
+
def test_api(url, query):
|
| 6 |
+
"""Test the travel assistant API"""
|
| 7 |
+
data = {
|
| 8 |
+
"query": query,
|
| 9 |
+
"temperature": 0.1,
|
| 10 |
+
"max_tokens": 2048
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
try:
|
| 14 |
+
response = requests.post(f"{url}/generate", json=data)
|
| 15 |
+
response.raise_for_status() # Raise an exception for HTTP errors
|
| 16 |
+
|
| 17 |
+
result = response.json()
|
| 18 |
+
print(json.dumps(result, indent=2))
|
| 19 |
+
return result
|
| 20 |
+
except requests.exceptions.RequestException as e:
|
| 21 |
+
print(f"Error: {e}")
|
| 22 |
+
return None
|
| 23 |
+
|
| 24 |
+
if __name__ == "__main__":
|
| 25 |
+
parser = argparse.ArgumentParser(description='Test the ZenoBot Travel API')
|
| 26 |
+
parser.add_argument('--url', type=str, default='http://localhost:7860', help='API endpoint URL')
|
| 27 |
+
parser.add_argument('--query', type=str, required=True, help='Travel query to send to the API')
|
| 28 |
+
|
| 29 |
+
args = parser.parse_args()
|
| 30 |
+
test_api(args.url, args.query)
|