lyp 3 weeks ago
parent b9eb74f3a5
commit c41e90df0b

@ -0,0 +1 @@
Subproject commit 117a5a171ecb20f3821ba4e502f17671109e47e2

@ -0,0 +1,432 @@
from flask import Flask, render_template, request, jsonify, session
import json
import requests
import os
from datetime import datetime
app = Flask(__name__)
app.secret_key = 'your-secret-key-here'
# 大模型API配置
LLM_CONFIG = {
"deepseek": {
"api_key": os.getenv("DEEPSEEK_API_KEY", "your-deepseek-api-key"),
"base_url": "https://api.deepseek.com/v1"
}
}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/ai')
def ai():
return render_template('ai.html')
# 新增大模型行程规划API
@app.route('/api/generate_itinerary', methods=['POST'])
def generate_itinerary():
try:
data = request.json
user_input = {
"destination": data.get('destination'),
"days": data.get('days'),
"trip_type": data.get('trip_type'),
"travelers": data.get('travelers'),
"budget": data.get('budget'),
"special_needs": data.get('special_needs', '')
}
# 调用大模型生成行程
itinerary = call_llm_for_itinerary(user_input)
return jsonify({
"success": True,
"itinerary": itinerary,
"title": f"{user_input['destination']}{user_input['days']}{user_input['trip_type']}之旅"
})
except Exception as e:
return jsonify({
"success": False,
"error": str(e)
}), 500
# 新增语音对话API
@app.route('/api/voice_chat', methods=['POST'])
def voice_chat():
try:
data = request.json
user_message = data.get('message')
conversation_history = data.get('history', [])
# 调用大模型进行对话
response = call_llm_for_chat(user_message, conversation_history)
return jsonify({
"success": True,
"response": response
})
except Exception as e:
return jsonify({
"success": False,
"error": str(e)
}), 500
def call_llm_for_itinerary(user_input):
"""调用大模型生成行程"""
prompt = f"""
作为专业的旅行规划专家请为以下需求生成详细的旅行行程
目的地{user_input['destination']}
天数{user_input['days']}
旅行类型{user_input['trip_type']}
人数{user_input['travelers']}
预算{user_input['budget']}
特殊需求{user_input['special_needs']}
请按以下格式回复
## 行程概览
- 总天数{user_input['days']}
- 主题特色{user_input['trip_type']}
## 每日详细安排
**第1天**
- 🕘 上午[活动1] + [详细说明] + [时长]
- 🕐 下午[活动2] + [详细说明] + [时长]
- 🕖 晚上[活动3] + [详细说明] + [时长]
- 🍽 餐饮推荐[餐厅1] [特色] [预算]
## 实用贴士
- 交通建议
- 注意事项
- 省钱技巧
请确保行程合理考虑景点开放时间交通距离体力分配等因素
"""
# 实际项目中调用大模型API
# 这里先用模拟数据
return generate_mock_itinerary(user_input)
def call_llm_for_chat(message, history):
"""调用大模型进行对话"""
# 构建对话上下文
messages = [
{"role": "system", "content": "你是一个专业的旅行助手,帮助用户规划行程、推荐目的地、提供旅行建议。回复要友好、专业、简洁。"}
]
# 添加历史对话
for msg in history[-6:]: # 只保留最近6轮对话
messages.append(msg)
# 添加当前消息
messages.append({"role": "user", "content": message})
# 实际项目中调用大模型API
# 这里先用模拟回复
return generate_mock_chat_response(message)
def generate_mock_itinerary(user_input):
"""生成模拟行程数据"""
# 这里可以扩展更多目的地和行程类型
base_itineraries = {
'日本东京': [
{
'day': 1,
'title': '抵达东京 - 浅草寺与东京塔',
'schedule': [
{'time': '上午', 'content': '抵达成田机场,乘坐成田特快到市区,办理酒店入住', 'duration': '09:00-12:00'},
{'time': '中午', 'content': '浅草寺周边午餐,推荐尝试天妇罗或荞麦面', 'duration': '12:30-14:00'},
{'time': '下午', 'content': '参观浅草寺,仲见世商店街购买纪念品', 'duration': '14:30-17:00'},
{'time': '晚上', 'content': '登上东京塔,欣赏夜景并拍照', 'duration': '18:30-20:30'}
]
}
]
}
destination = user_input['destination']
days = int(user_input['days'])
# 获取基础行程或默认行程
itinerary = base_itineraries.get(destination, base_itineraries['日本东京'])
# 补充不足的天数
while len(itinerary) < days:
day_index = len(itinerary) + 1
itinerary.append({
'day': day_index,
'title': f'自由探索 - 深度体验{destination}',
'schedule': [
{'time': '上午', 'content': '根据兴趣自由安排,推荐前往当地小众景点', 'duration': '09:00-12:00'},
{'time': '中午', 'content': '尝试当地特色美食,建议询问民宿老板推荐', 'duration': '12:30-14:00'},
{'time': '下午', 'content': '休闲活动(如咖啡馆看书、河边散步)', 'duration': '14:30-17:00'}
]
})
return itinerary[:days] # 只返回所需天数的行程
def generate_mock_chat_response(message):
"""生成模拟聊天回复"""
responses = {
'推荐': '根据您的喜好,我推荐以下几个目的地:\n\n1. **日本京都** - 适合文化体验,有丰富的寺庙和传统建筑\n2. **泰国清迈** - 适合美食和放松,物价相对较低\n3. **云南丽江** - 国内首选,自然风光和纳西文化都很棒',
'预算': '预算规划建议:\n\n- **经济型** (¥3000以下):选择青旅、当地交通、街边小吃\n- **舒适型** (¥3000-8000):商务酒店、部分出租车、餐厅用餐\n- **豪华型** (¥8000以上):星级酒店、包车、高端餐厅',
'天气': '请告诉我具体的目的地和出行时间,我可以为您查询当地的天气情况和最佳旅行季节。',
'签证': '签证信息因目的地而异:\n\n- **泰国**:落地签或提前办理\n- **日本**:需要提前办理签证\n- **欧洲**:申根签证,需要较长时间准备材料'
}
# 简单的关键词匹配
for keyword, response in responses.items():
if keyword in message:
return response
return '我主要专注于旅行规划相关的问题,比如目的地推荐、行程安排、预算规划、签证信息等。如果您有具体的旅行问题,我很乐意为您提供帮助!'
if __name__ == '__main__':
app.run(debug=True, port=5000)
from flask import Flask, render_template, request, jsonify, session, redirect, url_for, flash
import json
import os
import requests
from datetime import datetime
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
# 确保上传目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# 模拟用户数据(实际项目中使用数据库)
users = {
'test@example.com': {
'password': '123456',
'username': '测试用户',
'avatar': 'https://picsum.photos/id/1005/200/200'
}
}
# 主页路由
@app.route('/')
def index():
return render_template('index.html')
# 登录页路由
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = users.get(email)
if user and user['password'] == password:
session['user'] = {
'email': email,
'username': user['username'],
'avatar': user['avatar']
}
flash('登录成功!', 'success')
return redirect(url_for('index'))
else:
flash('邮箱或密码错误', 'error')
return render_template('login.html')
# 注册页路由
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
confirm_password = request.form.get('confirm_password')
if password != confirm_password:
flash('两次输入的密码不一致', 'error')
elif email in users:
flash('该邮箱已被注册', 'error')
else:
users[email] = {
'password': password,
'username': email.split('@')[0],
'avatar': 'https://picsum.photos/id/1005/200/200'
}
flash('注册成功,请登录', 'success')
return redirect(url_for('login'))
return render_template('register.html')
# 退出登录
@app.route('/logout')
def logout():
session.pop('user', None)
flash('已退出登录', 'info')
return redirect(url_for('index'))
# 个人中心
@app.route('/profile')
def profile():
if 'user' not in session:
flash('请先登录', 'error')
return redirect(url_for('login'))
return render_template('profile.html')
# AI行程规划页
@app.route('/ai')
def ai():
return render_template('ai.html')
# 打卡页面
@app.route('/checkin')
def checkin():
if 'user' not in session:
flash('请先登录', 'error')
return redirect(url_for('login'))
return render_template('checkin.html')
# 发表笔记页面
@app.route('/postnote')
def postnote():
if 'user' not in session:
flash('请先登录', 'error')
return redirect(url_for('login'))
return render_template('postnote.html')
# API路由 - 生成行程
@app.route('/api/generate_itinerary', methods=['POST'])
def generate_itinerary():
try:
data = request.json
user_input = {
"destination": data.get('destination'),
"days": data.get('days'),
"trip_type": data.get('trip_type'),
"travelers": data.get('travelers'),
"budget": data.get('budget'),
"special_needs": data.get('special_needs', '')
}
# 调用大模型生成行程
itinerary = call_llm_for_itinerary(user_input)
return jsonify({
"success": True,
"itinerary": itinerary,
"title": f"{user_input['destination']}{user_input['days']}{user_input['trip_type']}之旅"
})
except Exception as e:
return jsonify({
"success": False,
"error": str(e)
}), 500
# API路由 - AI对话
@app.route('/api/ai_chat', methods=['POST'])
def ai_chat():
try:
data = request.json
user_message = data.get('message')
# 调用大模型进行对话
response = call_llm_for_chat(user_message)
return jsonify({
"success": True,
"response": response
})
except Exception as e:
return jsonify({
"success": False,
"error": str(e)
}), 500
# 大模型调用函数
def call_llm_for_itinerary(user_input):
"""调用大模型生成行程"""
# 这里使用模拟数据实际项目中调用真实API
return generate_mock_itinerary(user_input)
def call_llm_for_chat(message):
"""调用大模型进行对话"""
# 这里使用模拟回复实际项目中调用真实API
return generate_mock_chat_response(message)
def generate_mock_itinerary(user_input):
"""生成模拟行程数据"""
destination = user_input['destination']
days = int(user_input['days'])
base_itineraries = {
'日本东京': [
{
'day': 1,
'title': '抵达东京 - 浅草寺与东京塔',
'schedule': [
{'time': '上午', 'content': '抵达成田机场,乘坐成田特快到市区,办理酒店入住', 'duration': '09:00-12:00'},
{'time': '中午', 'content': '浅草寺周边午餐,推荐尝试天妇罗或荞麦面', 'duration': '12:30-14:00'},
{'time': '下午', 'content': '参观浅草寺,仲见世商店街购买纪念品', 'duration': '14:30-17:00'},
{'time': '晚上', 'content': '登上东京塔,欣赏夜景并拍照', 'duration': '18:30-20:30'}
]
},
{
'day': 2,
'title': '上野公园 - 秋叶原动漫体验',
'schedule': [
{'time': '上午', 'content': '上野公园散步,参观东京国立博物馆', 'duration': '09:30-12:30'},
{'time': '中午', 'content': '上野公园周边鳗鱼饭午餐', 'duration': '13:00-14:30'},
{'time': '下午', 'content': '秋叶原电器街体验动漫文化,逛免税店', 'duration': '15:00-18:00'}
]
}
],
'云南丽江': [
{
'day': 1,
'title': '抵达丽江 - 古城初体验',
'schedule': [
{'time': '上午', 'content': '抵达丽江三义机场,乘车到古城,办理民宿入住', 'duration': '09:00-12:00'},
{'time': '中午', 'content': '古城内尝试纳西族特色菜(腊排骨火锅)', 'duration': '12:30-14:00'},
{'time': '下午', 'content': '丽江古城石板路漫步,参观四方街、大水车', 'duration': '14:30-17:30'},
{'time': '晚上', 'content': '古城酒吧街体验民谣演出', 'duration': '19:00-21:00'}
]
}
]
}
# 获取基础行程或默认行程
itinerary = base_itineraries.get(destination, base_itineraries['日本东京'])
# 补充不足的天数
while len(itinerary) < days:
day_index = len(itinerary) + 1
itinerary.append({
'day': day_index,
'title': f'自由探索 - 深度体验{destination}',
'schedule': [
{'time': '上午', 'content': '根据兴趣自由安排,推荐前往当地小众景点', 'duration': '09:00-12:00'},
{'time': '中午', 'content': '尝试当地特色美食,建议询问民宿老板推荐', 'duration': '12:30-14:00'},
{'time': '下午', 'content': '休闲活动(如咖啡馆看书、河边散步)', 'duration': '14:30-17:00'}
]
})
return itinerary[:days]
def generate_mock_chat_response(message):
"""生成模拟聊天回复"""
responses = {
'推荐': '根据您的喜好,我推荐以下几个目的地:\n\n1. **日本京都** - 适合文化体验,有丰富的寺庙和传统建筑\n2. **泰国清迈** - 适合美食和放松,物价相对较低\n3. **云南丽江** - 国内首选,自然风光和纳西文化都很棒',
'预算': '预算规划建议:\n\n- **经济型** (¥3000以下):选择青旅、当地交通、街边小吃\n- **舒适型** (¥3000-8000):商务酒店、部分出租车、餐厅用餐\n- **豪华型** (¥8000以上):星级酒店、包车、高端餐厅',
'天气': '请告诉我具体的目的地和出行时间,我可以为您查询当地的天气情况和最佳旅行季节。',
'签证': '签证信息因目的地而异:\n\n- **泰国**:落地签或提前办理\n- **日本**:需要提前办理签证\n- **欧洲**:申根签证,需要较长时间准备材料'
}
# 简单的关键词匹配
for keyword, response in responses.items():
if keyword in message:
return response
return '我主要专注于旅行规划相关的问题,比如目的地推荐、行程安排、预算规划、签证信息等。如果您有具体的旅行问题,我很乐意为您提供帮助!'
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
Loading…
Cancel
Save