File size: 6,578 Bytes
d741351 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
import gradio as gr
import plotly.graph_objects as go
import random
import numpy as np
import requests
import os
from huggingface_hub import InferenceClient
HF_TOKEN = os.environ.get("HF_TOKEN")
client = InferenceClient(api_key=HF_TOKEN)
def generate_response(system_prompt, user_prompt):
temperature, top_p = random.uniform(0.6, 0.75), random.uniform(0.7, 1.0)
completion = client.chat.completions.create(
model="mistralai/Mistral-Nemo-Instruct-2407",
messages=[{
"role": "system",
"content": system_prompt
}, {
"role": "user",
"content": user_prompt
}],
temperature=temperature,
max_tokens=1024,
top_p=top_p,
)
return completion.choices[0].message.content
def generate_location_recommendations(user_prompt):
system_prompt = """
你是一個專業的地點推薦助手,專門根據使用者的需求提供相關的知名景點或位置。當使用者詢問某個地點、旅遊目的或活動建議時,請根據指令找出適合的多個景點,並**務必滿足使用者的詢問需求**。回應需遵守以下規則:
1. **以條列式列出景點名稱**,每行一個景點名稱。
2. **不要提供任何額外描述、編號或其他與地點無關的文字**,僅列出名稱即可。
3. 提供的景點必須是**真實存在**的,而非虛構或杜撰的。
3. 所有回應須使用**繁體中文**。
4. **完全滿足**使用者的發問需求。
### 回應格式範例:
```
景點 1
景點 2
景點 3
```
請確保提供的景點與使用者查詢密切相關,並確認所有景點真實存在,且涵蓋足夠的選項以滿足使用者的需求。"""
completion = generate_response(system_prompt, user_prompt)
locations = []
for loc in completion.split('\n'):
lat_lon = fetch_location_coordinates(loc)
locations.append(lat_lon)
# 刪除找不到的地點
locations = np.array([loc for loc in locations if loc[1] is not None])
return user_prompt, locations
def generate_travel_summary(user_prompt, locations):
system_prompt = """
你是一個專業且富有魅力的旅遊與地點推薦助手。你的任務是根據**使用者的原始提問**和提供的**景點或地點清單**,生成一段專業、豐富且引人入勝的結論。這段結論應讓使用者感到興奮、滿足或有所啟發,並進一步激發他們的興趣。
請遵循以下指引:
1. **根據使用者的需求和目的**,適當總結景點或地點清單,並提供有趣的背景或亮點描述。
2. **保持語氣專業且富有吸引力**,可以適度加入生動的形容詞,讓建議更具畫面感和感染力。
3. **結尾可以提出鼓勵性或引導性的語句**,促使用者更期待他們的旅程或任務。
4. **回應須使用繁體中文**,並保持流暢易讀。
輸入格式:
使用者提問:「問題內容」
景點清單:
```
地點 1
地點 2
地點 3
```
輸出格式 (輸出內容**僅包含結論**,**無須重複**提問內容或其他無關的文字):
你的結論
"""
user_prompt = f"""使用者提問:「{user_prompt}」
景點清單:
```
{locations}
```\n\n"""
completion = generate_response(system_prompt, user_prompt)
return completion
def fetch_location_coordinates(location):
location_response = requests.get(
f"https://nominatim.openstreetmap.org/search?q={location}&format=json&limit=1",
headers={
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"Accept-Language": "zh-TW,zh;q=0.7",
"Cache-Control": "max-age=0",
"Priority": "u=0, i",
"Sec-Ch-Ua-Mobile": "?1",
"Sec-Ch-Ua-Platform": "\"Android\"",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Sec-Gpc": "1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36^"
}
)
if location_response.status_code == 200 and len(location_response.json()) > 0:
loc = location_response.json()[0]
loc = [location, float(loc['lat']), float(loc['lon'])]
return loc
else:
return [location, None, None]
def plot_locations(locations):
if len(locations) == 0:
return "No locations found. Please try another query."
names = locations[:, 0]
lats = locations[:, 1].astype(float)
lons = locations[:, 2].astype(float)
fig = go.Figure(go.Scattermapbox(
lat=lats,
lon=lons,
mode='markers',
marker=go.scattermapbox.Marker(size=14, color='red'),
text=names,
hoverinfo="text"
))
fig.update_layout(
mapbox_style="open-street-map",
mapbox=dict(
center=go.layout.mapbox.Center(
# 以台灣中心點為地圖中心
lat=23.905987823498418,
lon=121.08291334460809
),
zoom=6
),
margin={"r": 0, "t": 0, "l": 0, "b": 0}
)
return fig
def handle_user_request(text):
# 生成地點建議
suggestions = generate_location_recommendations(text)
if len(suggestions[1]) > 0:
# 若有找到地點,則使用這份清單,生成一段行程指引
output = generate_travel_summary(suggestions[0], "\n".join(suggestions[1][:, 0]))
map_figure = plot_locations(suggestions[1])
return output, map_figure
else:
return "No locations found for the given input. Please try another query.", "No locations found."
# Gradio 介面
with gr.Blocks() as app:
gr.Markdown("# 🌏 ChatMap: Your AI-Powered Map Companion 🌏")
with gr.Row():
text_input = gr.Textbox(label="Tell me your command", value="我要去宜蘭玩,請推薦我至少5個熱門景點")
submit_btn = gr.Button("Generate")
output_summary = gr.Textbox(label="Here’s what I’ve mapped out for you", interactive=False)
map_display = gr.Plot(label="Visualizing your journey on the map")
submit_btn.click(handle_user_request, inputs=text_input, outputs=[output_summary, map_display])
# 啟動應用
app.launch() |