交互式数据可视化与AI大模型集成,在智慧旅游、智能推荐、数据分析等领域具有广泛应用。这类应用通常需要将数据处理、图形展示与外部AI服务无缝衔接,为用户提供直观、智能的交互体验。本章使用Streamlit框架快速搭建Web应用界面,利用Pandas完成景区Excel数据的清洗与缓存,通过Plotly绘制收入对比与游客量趋势等动态图表,并借助Folium嵌入高德地图实现景区地理位置可视化。在AI能力方面,采用腾讯MaaS提供的youtu‑vita多模态模型进行景区标志物图像识别,同时接入阿里云通义千问(Qwen‑Turbo)大语言模型,通过构造包含景区真实信息的系统提示,实现景区介绍生成、游玩建议推荐以及智能导游问答。对于AI集成,通常有两种实现方式:一种是调用云端多模态API直接对上传图片进行理解与描述,无需本地部署模型;另一种是基于大语言模型API构建对话接口,将领域知识融入上下文,使生成内容兼具专业性与准确性。本章将详细介绍这两种集成方式在广西景区旅游综合分析平台中的具体应用。下面将从案例背景、案例目标及实现思路、数据获取与探索、核心功能实现、需求分析与界面设计等方面展开说明。

1.1 案例背景

        随着广西文旅产业的蓬勃发展,游客对景区信息的获取方式正从传统的文字介绍向智能化、个性化转变。广西拥有桂林漓江、北海银滩、龙脊梯田、德天跨国瀑布等众多优质旅游资源,但各景区数据分散、导览形式单一,游客难以在短时间内获取全面、动态的景区分析。本案例利用Streamlit框架,结合多模态大模型与自然语言处理技术,构建一个集景区数据可视化、图像识别、智能问答于一体的旅游综合分析平台。

        平台以广西全量景区Excel数据为基础,集成了腾讯MaaS的多模态模型(youtu‑vita)实现景区标志物图像识别,并接入阿里云通义千问(Qwen‑Turbo)大模型,动态生成景区介绍、游玩建议并实现智能导游问答。系统采用多页面路由设计,首页提供搜索、收入与游客量趋势分析、AI图像识别等功能;详情页展示景区基本信息、AI生成内容、高德地图定位及AI导游交互。通过本案例,可以掌握Streamlit多页面开发、外部AI API集成以及交互式数据可视化的方法。

1.2 案例目标及实现思路

        主要目标包括: 

(1) 掌握使用Pandas读取和处理Excel景区数据的方法; 

(2) 掌握Streamlit多页面路由、组件布局及状态管理; 

(3) 掌握调用腾讯MaaS多模态模型进行图像识别,并集成到Web应用中; 

(4) 掌握阿里云通义千问API的调用方法,实现上下文感知的智能问答; 

(5) 能够利用Plotly构建交互式收入与游客量趋势图表,并嵌入Folium地图。

基本实现思路如下图所示:

图1广西景区旅游综合分析平台实现思路

1.3 数据获取与数据处理

        景区原始数据存储在Excel文件“广西各景点数据表.xlsx”中,包含字段:景区名称、等级、地址、city、lng_wgs84、lat_wgs84等。平台使用Pandas读取数据后进行清洗:剔除经纬度缺失的记录,删除重名景区(保留第一条),确保数据质量。代码通过@st.cache_data装饰器缓存加载结果,避免每次交互都重复读取文件,提升响应速度。示例代码如下:

@st.cache_data

def load_scenic_data():

    df = pd.read_excel("广西各景点数据表.xlsx")

    df.columns = df.columns.str.strip()

    df['lng_wgs84'] = pd.to_numeric(df['lng_wgs84'], errors='coerce')

    df['lat_wgs84'] = pd.to_numeric(df['lat_wgs84'], errors='coerce')

    df = df.dropna(subset=['lng_wgs84', 'lat_wgs84'])

    df = df.drop_duplicates(subset=['景区名称'], keep='first').reset_index(drop=True)

    return df


SCENIC_DF = load_scenic_data()

 

        执行后,SCENIC_DF 包含全量有效景区数据,可通过 SCENIC_DF['景区名称'] 进行检索。

1.4 核心功能实现

        本平台的核心“模型”并非单一的机器学习模型,而是多个AI服务的集成与调用模式。本节介绍两部分:多模态图像识别模型和语言大模型问答服务。

1.4.1 多模态图像识别

模型原理:

        多模态大模型是一种能够同时处理图像和文本输入的深度学习模型,它通常由视觉编码器(如 ViT)和大语言模型解码器组成。在训练阶段,模型会学习将图像特征与语义描述对齐,从而在看到新图片时,能根据给定的文本提示生成相应的自然语言描述。本案例调用的youtu‑vita模型正是此类多模态模型,它在海量图文数据上进行了预训练,具备理解景区景物、建筑物并输出其名称、位置等信息的能力。

模型设计:

        图像识别功能采用腾讯MaaS提供的youtu‑vita多模态模型。该模型可以同时接收图片和文本提示,生成关于图片内容的自然语言描述。在平台中,用户上传景区标志物图片,系统将图片转为Base64编码,拼接为data URL,与提示词一起发送至腾讯MaaS的Chat Completions接口,获得识别结果。

        在平台中,图像识别功能被设计为一个独立的服务函数 tencent_image_recognition。当用户在首页上传景区标志物图片后,系统将执行以下流程:

        1、将上传的图片字节流转换为 Base64 编码,并拼接为标准 data URL(如 data:image/jpeg;base64,...);

        2、构造符合 OpenAI Chat Completions 格式的请求体,其中 messages 既包含图片的 image_url 字段,又包含一条文本提示:“请详细描述这张图片中的景区或建筑物,并给出名称、位置等关键信息”;

        3、通过 POST 请求将数据发送至腾讯 MaaS 接口(https://tokenhub.tencentmaas.com/v1/chat/completions),并附带 API Key 进行认证;

        4、解析响应 JSON,提取 choices[0].message.content 中的文本描述,展示给用户。

这样的设计完全屏蔽了底层模型细节,只需网络请求即可获得识别结果,适合轻量级 Web 应用。

关键实现代码如下:

def tencent_image_recognition(uploaded_file):
   
    if TENCENT_API_KEY.startswith("sk-请替换"):
        return "⚠️ 演示模式:请在代码中配置真实的腾讯 API Key 后使用。"

    try:
        # 读取图片文件并转为 Base64
        img_bytes = uploaded_file.read()
        img_base64 = base64.b64encode(img_bytes).decode('utf-8')

        # 获取 MIME 类型,例如 image/jpeg, image/png
        mime_type = uploaded_file.type if hasattr(uploaded_file, 'type') else 'image/jpeg'
        data_url = f"data:{mime_type};base64,{img_base64}"

        # 构造请求头
        headers = {
            'Authorization': f'Bearer {TENCENT_API_KEY}',
            'Content-Type': 'application/json'
        }

        # 构造请求体
        payload = {
            "model": "youtu-vita",
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "image_url",
                            "image_url": {
                                "url": data_url
                            }
                        },
                        {
                            "type": "text",
                            "text": "请描述这张图片的内容"
                        }
                    ]
                }
            ],
            "stream": False
        }

        # 发送请求
        response = requests.post(TENCENT_BASE_URL, headers=headers, json=payload)
        response.raise_for_status()
        result = response.json()

        # 提取返回的文本描述
        if 'choices' in result and len(result['choices']) > 0:
            description = result['choices'][0]['message']['content']
            return f"识别成功:{description}"
        else:
            return f"未识别到内容,API 返回:{result}"

    except Exception as e:
        return f"识别接口调用失败: {str(e)}"

        模型返回的JSON中choices[0].message.content即识别描述文本,系统直接展示给用户。通过调整提示词,可以让识别结果更聚焦于广西景区信息。该实现将图像作为对话的一部分发送给模型,模型直接返回可读的景区描述,极大简化了传统图像识别中“特征提取+分类器”的复杂流程。

1.4.2 语言大模型导游服务

模型原理:

        通义千问 Qwen‑Turbo 是一种基于 Transformer 解码器架构的自回归语言模型,通过在海量文本语料上预训练,获得了强大的语言理解和生成能力。在提示词(Prompt)工程的支持下,可以通过设定系统角色、注入领域知识来控制模型的行为和输出内容。本案例通过在系统提示中植入景区真实数据,使模型在回答时能够围绕指定景区的真实信息展开,避免了“幻觉”现象。

模型设计:

        智能问答模块基于阿里云通义千问(Qwen‑Turbo)模型。系统通过OpenAI兼容接口调用,为每个景区构建系统提示词,包含景区名称、等级、地址、坐标等真实信息,确保回答基于可靠数据。用户提问时,请求体中拼接系统提示和用户问题,获得AI回复。智能导游问答功能由qwen_api_query函数实现,其设计思路如下:

        1、为每个景区构建一条系统提示,包含景区名称、等级、所在城市、详细地址和经纬度坐标,要求模型“基于以上真实信息热情专业地回答用户问题”;

        2、将用户问题与系统提示一起打包为 messages 列表,通过 OpenAI 兼容接口发送到通义千问服务(https://dashscope.aliyuncs.com/compatible-mode/v1);

        3、接收模型返回的 completion.choices[0].message.content,如果内容为 None 则根据终止原因给出提示;

        4、在详情页中,景点介绍和游玩建议的结果会被缓存到 st.session_state 中,避免重复调用 API,提升响应速度并节约资源。

关键实现代码如下:

def qwen_api_query(question, scenic_name, scenic_info=""):

    client = OpenAI(

        api_key=DASH_SCOPE_API_KEY,

        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",

        http_client=httpx.Client(timeout=30.0)

    )

    system_prompt = f"你是一个广西景区旅游专家。以下是【{scenic_name}】的基础信息:\n{scenic_info}\n请基于以上真实信息热情专业地回答。"

    completion = client.chat.completions.create(

        model="qwen-turbo",

        messages=[

            {"role": "system", "content": system_prompt},

            {"role": "user", "content": question}

        ]

    )

    return completion.choices[0].message.content

 

        平台利用Session State缓存已生成的介绍和游玩建议,避免重复API调用。景区详情页的AI智能导游问答模块支持快捷提问和自定义问题,实时调用模型生成回复,并通过聊天气泡样式展示。

总结:

        本章构建了一个基于Streamlit的广西景区旅游综合分析平台。通过Pandas管理景区数据,利用Plotly实现收入与游客量趋势可视化,借助腾讯MaaS多模态模型完成图像识别,并通过阿里云通义千问实现智能导游功能。平台采用了组件化、路由化的设计,具有较好的可扩展性,为用户提供了一个直观、智能的旅游信息获取入口。

1.5系统需求分析

        在前文中,我们详细介绍了平台的数据处理与AI集成方法。为了让普通用户能直观、便捷地使用这些功能,需要设计一个可视化交互系统。表2-1给出了广西景区旅游综合分析平台的功能需求列表。

表2广西景区旅游综合分析平台需求分析

1.6 系统设计与开发

        本节以“广西景区旅游网”为例,详细介绍Streamlit多页面应用的开发流程,包括页面配置、数据管理、组件交互与AI集成。

1.6.1设置页面配置

        导入必要库后,首先使用st.set_page_config()设置页面标题(“🌴 广西景区旅游网”)和宽屏模式,使图表能够充分利用横向空间。

st.set_page_config(page_title="广西景区旅游网", layout="wide", page_icon="🌴")

        主脚本文件假设为app.py,在终端中执行:

streamlit run main.py

        运行后浏览器自动打开默认地址(http://localhost:8501),显示平台主页。执行结果如图所示:

图2

图3

1.6.2数据加载与缓存

        为了高效管理景区数据,定义全局函数load_scenic_data(),使用@st.cache_data装饰器。该函数读取Excel文件,统一列名,将经纬度字段转换为数值型,剔除缺失坐标的行,并对同名景区去重。处理后的DataFrame保存在全局变量SCENIC_DF中,供所有页面复用。关键代码参见1.3节。

1.6.3页面路由与状态管理

        平台采用手动路由模式,在st.session_state中维护page变量(初始值'home')。首页和详情页分别由show_home_page()和show_detail_page()函数渲染,主程序根据st.session_state.page的值决定调用哪个函数。

if st.session_state.page == 'home':

    show_home_page()

else:

    show_detail_page()

 

        搜索组件被点击时,若匹配到景区,将page设为'detail'并保存selected_scenic,再调用st.rerun()重新执行脚本,实现页面跳转。

图4

图5

1.6.4首页功能实现

        首页集成了搜索、轮播图、数据可视化、图像识别、旅游知识五个核心模块,全部在一个长页面中组合显示。

图6

景区搜索:

        使用st.text_input和st.button组合,输入关键词后点击搜索,通过SCENIC_DF['景区名称'].str.contains()进行模糊匹配,匹配成功则跳转至详情页,否则显示警告信息。如图4、5

轮播图:

        轮播图数据定义在字典HOME_CAROUSEL中,包含图片路径、名称和描述。通过st.session_state.carousel_index记录当前索引,左右按钮修改索引值并st.rerun()。页面使用st.columns布局,中间显示当前图片,底部显示圆点指示器。

图7

收入与游客量分析:

        虽然景区全量数据来自Excel,但首页可视化区域为了快速展示,采用了硬编码的模拟数据(核心景区2022‑2024年收入和游客量)。利用Plotly Express绘制分组柱状图和折线图,颜色区分景区,图表高度自适应。用户可通过下拉框选择统计年份,图表实时更新。

图8

AI图像识别:

        图像识别入口位于首页右侧栏,提供st.file_uploader组件,类型限制为jpg/png。用户上传图片后,点击“开始AI识别”按钮,触发tencent_image_recognition函数,内部将图片转为Base64后发送至腾讯MaaS接口,结果以成功消息形式展示。

图9

旅游小知识:

        利用st.expander折叠面板展示景区统计(通过SCENIC_DF实时计算)、广西美食和最佳旅游季节。这些内容为静态文案,提升平台亲和力。

图10

1.6.5详情页功能实现

        详情页根据st.session_state.selected_scenic从SCENIC_DF中提取对应行数据,展示景区概况表格、AI生成介绍与游玩建议、高德地图以及AI智能问答。

图11

景区概况与AI生成内容:

        概况表格使用Markdown表格直接渲染景区等级、城市、地址和坐标。景区介绍和游玩建议通过qwen_api_query函数动态生成,为防止重复调用,使用st.session_state缓存(键名如intro_景点名)。首次访问时显示加载提示,之后直接展示缓存文本,提高效率。如图11。

高德地图定位:

        使用folium库创建地图对象,添加高德地图瓦片层(http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&...)和红色标记点,通过st_folium组件嵌入页面,实现景区位置直观展示。

图12

AI智能导游问答:

        问答区域提供快捷提问下拉框和自定义输入框,用户可选择预设问题或输入个性化问题。点击“向AI提问”后,调用qwen_api_query,将系统提示(含景区真实信息)和用户问题发送至通义千问,返回内容以st.chat_message("assistant")展示。同时,页面底部提供热门问答推荐,帮助新用户快速上手。

图13

1.7 AI使用说明

        在本次课程设计开发过程中,利用AI对话工具(DeepSeek-v4-pro)辅助编写了多个核心功能模块。下面说明AI的使用方式、迭代过程和最终优化结果。

场景一:Streamlit 页面路由与 Session State 管理

使用AI的位置

                为了在单页应用中实现“首页”与“详情页”的切换,需要借助 st.session_state 管理当前页面状态和选中的景区名称。初始时对 Streamlit 的路由模式不熟悉,向 AI 提出了结构设计问题。

提问示例

        我需要在 Streamlit 中实现两个页面(首页和详情页),通过按钮点击切换,同时保持之前的状态,应该如何设计?

AI 初始回复

        在 Streamlit 中实现“首页”和“详情页”的按钮切换,同时保持所有用户输入和程序状态,核心思路是:利用 st.session_state 记录当前页面,并让所有交互组件的值自动保存在 st.session_state 中。由于 Streamlit 的每次交互都会从头重新执行脚本,只要状态没有显式重置,它就会在多次运行时持久保留。下面是一种清晰、可维护的设计方式。

        整体逻辑

定义一个 st.session_state 变量(如 page)表示当前页面,初始值为 "home"(首页)。

在脚本开头放置切换按钮,点击后修改 page 的值。

根据 page 的值,用 if/elif 渲染不同的页面内容。

所有需要保持状态的组件(输入框、选择器、滑块等)都直接绑定到 st.session_state 的某个键上,这样即使页面切换,值也不会丢失。

迭代与优化过程

        1、第一版代码仅实现了基础的路由切换,但未处理浏览器后退或重复点击按钮导致的状态混乱。 

        2、向 AI 追加提问:“如何确保 selected_scenic 变量在页面切换后仍然保留?” AI 提示同样使用 st.session_state.selected_scenic 存储,并在搜索按钮的回调中赋值。 

        3、测试发现,在详情页点击“返回首页”后又立即搜索,有时会触发两次 rerun,导致页面闪烁。AI 建议在按钮回调中直接修改状态后调用 st.rerun(),避免在 if 块内嵌套额外逻辑。 

        4、最终代码中,首页搜索和详情页返回按钮均采用统一模式:先更新 st.session_state,再执行 st.rerun(),形成稳定路由。

最终代码片段

if st.button("搜索景区", key="search_btn"):

    if search_query.strip():

        matched = SCENIC_DF[SCENIC_DF['景区名称'].str.contains(search_query.strip())]

        if not matched.empty:

            st.session_state.selected_scenic = matched.iloc[0]['景区名称']

            st.session_state.page = 'detail'

            st.rerun()

 

截图辅助说明

        截图1:向AI提问的对话界面,显示问题与AI给出的初始代码:

        截图2:修改迭代过程中的第二版代码:

截图3:最终运行效果,点击搜索后成功跳转到详情页,且 selected_scenic 正确显示:

场景二:腾讯 MaaS 多模态图像识别函数开发

使用AI的位置 

        需要调用腾讯云 youtu‑vita 多模态模型实现图片识别,但完全不了解其 API 格式和请求构造方法。

提问示例 

        请帮我写一个 Python 函数,接收用户上传的图片文件,使用腾讯 MaaS 的 youtu‑vita 模型进行识别,要求返回对图片中景区或建筑物的文字描述。API 地址是 https://tokenhub.tencentmaas.com/v1/chat/completions,认证方式为 Bearer Token。

AI 初始回复 

        AI 提供了基本函数框架,包括将图片转为 base64、构造 data URL、编写 messages 结构、发送 POST 请求并解析 JSON。同时提示需要在代码中替换 API Key。

迭代与优化过程 

        1、首次运行时,因 Authorization 头部拼写错误导致 401 认证失败,AI 协助修正为 "Authorization": f"Bearer {api_key}"。 

        2、提示词最初为 “识别这张图片”,返回结果常包含无关描述。通过向 AI 提问如何优化提示词,得到更具体的文本:“请详细描述这张图片中的景区或建筑物,并给出名称、位置等关键信息。” 替换后识别质量明显提升。 

        3、错误处理方面,AI 帮助完善了 try/except 块,覆盖文件读取失败、HTTP 异常和网络超时等。

最终代码片段(对应 tencent_image_recognition 函数) 

payload = {

    "model": "youtu-vita",

    "messages": [{

        "role": "user",

        "content": [

            {"type": "image_url", "image_url": {"url": data_url}},

            {"type": "text", "text": "请详细描述这张图片中的景区或建筑物,并给出名称、位置等关键信息。"}

        ]

    }],

    "stream": False

}

headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}

resp = requests.post(url, headers=headers, json=payload)

if resp.status_code == 200:

    data = resp.json()

    return data["choices"][0]["message"]["content"]

 

截图辅助说明 

        截图1:向AI提问“腾讯 MaaS 多模态 API 调用代码”的对话,AI 返回初始函数骨架:   

        截图2:向 AI 追问修正意见的对话:

场景三:阿里云通义千问大模型智能问答接口开发

使用AI的位置 

        需要基于 OpenAI SDK 调用通义千问 API 实现景区智能问答,但对如何构造系统提示、处理空返回等问题经验不足。

提问示例 

        使用 openai Python 库调用阿里云 DashScope 的通义千问 qwen‑turbo 模型,实现一个导游问答函数。该函数需要接收景区信息作为系统提示,让模型只根据提示回答,避免编造。请给出完整代码,并加入异常处理。

AI 初始回复 

        AI 提供了一段代码,包含 OpenAI 客户端初始化、messages 列表构造和 completion 的获取,并建议在系统提示中加入“不要编造虚假数据”的指令。同时提示需要安装 openai 和 httpx 库。

迭代与优化过程 

        1、第一次测试时,由于未设置 http_client 的超时时间,网络波动时程序卡死。AI 建议创建 httpx.Client 并指定 timeout=30.0 传给 OpenAI 客户端。 

        2、为提升用户体验,AI 还帮助设计了快捷提问列表和热门问答折叠面板,这些代码也经过多轮对话微调(如按钮对齐、样式美化等)。

最终代码片段(对应 qwen_api_query 函数及调用处) 

system_prompt = f"""你是一个广西景区旅游专家。以下是【{scenic_name}】的基础信息:

{scenic_info}

请基于以上真实信息,热情专业地回答用户问题。如果基础信息中没有相关内容,请结合广西旅游常识给出合理建议,不要编造虚假数据。


completion = client.chat.completions.create(

    model="qwen-turbo",

    messages=[

        {"role": "system", "content": system_prompt},

        {"role": "user", "content": question}

    ]

 

截图辅助说明 

        截图1:向AI提问“通义千问 API 调用示例”的对话,AI 返回基础代码:

        截图2:优化代码:

        截图3:最终版界面,AI 成功生成景区介绍且未出现编造内容,同时缓存生效,二次打开立即显示:

        通过上述三个场景,可以看出 AI 在本系统开发中主要扮演了代码生成器、调试助手和优化顾问的角色。利用 AI 辅助,大幅缩短了陌生 API 的学习时间,并帮助迅速定位和解决了多个运行时问题。所有 AI 生成的代码都在理解其逻辑的基础上进行了适应性调整,并非简单复制粘贴,确保了最终项目的可控性和可靠性。

总结

        本项目成功设计并实现了一个基于AI大模型的广西景区旅游综合分析平台,有效解决了传统旅游信息获取方式分散、导览形式单一及缺乏个性化交互等痛点。平台以Streamlit为前端框架,深度融合了数据处理、交互式可视化与多模态人工智能技术,构建了集数据洞察、图像识别与智能导览于一体的智慧旅游应用范式。

平台演示

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐