1. 从一句需求到线上应用:Vibe Coding 到底能做什么
Vibe Coding 这个词最近在开发者圈子里出现得越来越频繁,它的核心思路很简单:你用自然语言描述想要什么,AI 帮你把代码写出来,你负责判断和调整方向。听起来像是“许愿式编程”,但实际用下来,它确实能把一个想法从零到可访问的线上 Demo 压缩到一两个小时以内。
这篇文章要做的,是一个天气预报智能体。它能做什么?你用中文问“上海明天天气怎么样”,它会自动把城市名转成英文、调用地理编码接口拿到经纬度、再请求天气 API 取回温度湿度和降水概率,最后用自然语言把结果整理给你。适合谁?适合想快速验证 AI 应用想法、又不想从零手写前后端和工具调用逻辑的开发者,也适合刚接触 MCP 协议、想找一个完整可跑案例来理解“大模型怎么调工具”的朋友。
整个流程分四段:在 Qoder 里用自然语言生成 Gradio 界面和 MCP 工具调用逻辑,本地跑通验证,然后部署到 ModelScope 创空间,最后拿到一个公网可访问的链接。我会把每一步的提示词、配置文件、部署参数都写清楚,你跟着做就能复现。
技术栈方面,界面用 Gradio 5.x,大模型走 ModelScope 的推理 API(Qwen3-Next-80B-A3B-Instruct),工具调用协议用 MCP,天气数据源用 Open-Meteo 的免费接口,异步请求用 httpx。Python 版本建议 3.11,操作系统 Windows / macOS / Linux 都行。
有一点需要提前说明:MCP 在这里的角色是“标准化工具调用协议”。你可以把它理解成一个插座标准——大模型不需要知道天气 API 的具体 URL 和参数格式,它只需要知道“有一个叫 get_hourly_forecast_by_datetime_range 的工具,接受经纬度和日期范围”,MCP 服务端负责把参数翻译成实际的 HTTP 请求。这样换数据源的时候,只需要改服务端,客户端和提示词都不用动。
2. 前置准备:Qoder 项目初始化与 ModelScope API Key 获取
2.1 环境检查
在开始之前,确认你的开发环境满足以下条件:
| 项目 | 要求 |
|---|---|
| Python 版本 | 3.11(3.10 也可,但 3.11 对 asyncio 支持更好) |
| 操作系统 | Windows / macOS / Linux |
| 必需工具 | Qoder IDE |
| 网络要求 | 能访问 ModelScope API 和 Open-Meteo API |
| 依赖包 | gradio、openai、mcp、httpx |
如果你还没有 Qoder,去官网下载安装即可。安装完成后打开,点击“打开项目”,在本地新建一个目录(比如weather-agent),用 Qoder 打开这个空目录。
2.2 获取 ModelScope API Key
大模型调用需要 ModelScope 的访问令牌。操作路径:
- 登录 ModelScope 账号
- 访问
https://www.modelscope.cn/my/myaccesstoken - 复制你的 Access Token(格式类似
ms-xxxxxxxx)
这个 Token 后面会用在两个地方:本地client.py里的api_key参数,以及创空间的环境变量MODELSCOPE_API_KEY。注意不要把它硬编码到会公开的代码里,后面部署那一步我会讲怎么用环境变量替代。
2.3 创建项目文件
在 Qoder 左侧资源管理器里新建三个文件:server.py、client.py、app.py。前两个是 MCP 服务端和客户端,第三个是 Gradio 应用入口。
server.py负责定义 MCP 工具,核心是三个@mcp.tool装饰的函数:
get_all_coordinates(city):调 Open-Meteo 地理编码 API,把城市名转成经纬度get_hourly_forecast_by_datetime_range(...):调预报 API 拿指定日期范围的逐小时天气get_hourly_observe_by_datetime_range(...):调历史 API 拿实况天气
每个工具都用Annotated和Field标注参数说明,这些说明会直接暴露给大模型,所以写清楚很重要。比如city参数要注明“非英文名称要转换为英文”,否则模型可能直接把“北京”传给 API 导致查不到。
client.py是 MCP 客户端,负责连接服务端、收集工具列表、把工具定义转成 OpenAI function calling 格式、处理多轮工具调用循环。关键逻辑在process_query方法里:它维护一个messages列表,每次请求后检查message.tool_calls,如果有工具调用就执行、把结果追加到消息里、再次请求模型,直到模型给出最终文本回答。
app.py是 Gradio 界面,把client.py的process_query包装成聊天回调。这部分我建议直接用 Qoder 生成,提示词如下:
请参考 server.py 和 client.py,编写一个 app.py 脚本,利用 Gradio 技术实现一个天气预报智能体。 要求: 1. 使用 gr.Blocks 构建界面,左侧显示功能介绍,右侧是聊天窗口 2. 聊天窗口用 gr.Chatbot,输入框用 gr.Textbox,发送和清空按钮放在同一列 3. 首次查询时自动初始化 MCP 工具连接 4. api_key 从环境变量 MODELSCOPE_API_KEY 读取,默认值留空 5. 支持多轮对话,显示工具调用过程Qoder 会生成一个完整的app.py,你检查一下api_key那行是不是从环境变量读的,如果不是就手动改一下。
3. 可复制配置:MCP 服务端、客户端与 Gradio 界面参数
3.1 server.py 关键配置
MCP 服务端的核心是工具定义。以下是get_hourly_forecast_by_datetime_range的参数配置片段,你可以直接复制到server.py:
@mcp.tool(description="获取指定经纬度位置在指定日期范围内的预报天气信息") async def get_hourly_forecast_by_datetime_range( latitude: Annotated[float, Field(description="纬度坐标,例如: 31.2304")], longitude: Annotated[float, Field(description="经度坐标,例如: 121.4737")], start_date: Annotated[str, Field(description="开始日期,格式为YYYY-MM-DD")], end_date: Annotated[str, Field(description="结束日期,格式为YYYY-MM-DD")], location_name: Annotated[str, Field(description="位置名称,用于结果展示")] = "", timezone: Annotated[str, Field(description="时区名称,例如: Asia/Singapore")] = "Asia/Singapore", model: Annotated[str, Field(description="天气预报模型,例如: icon_seamless")] = "", weather_variables: Annotated[str, Field( description="要获取的天气要素,用逗号分隔,例如: 'temperature_2m,relative_humidity_2m,precipitation'" )] = "temperature_2m" ) -> Annotated[str, Field(description="给定位置和日期范围内每小时天气数据的摘要。")]:注意weather_variables的默认值是temperature_2m,如果你想让模型默认返回更多要素,可以改成temperature_2m,relative_humidity_2m,precipitation_probability,weather_code。但不要把所有要素都塞进去,否则返回的 JSON 会很大,模型处理起来慢。
服务端启动方式在文件末尾:
if __name__ == "__main__": mcp.run(transport="stdio")stdio表示通过标准输入输出通信,适合本地进程间调用。部署到创空间后也是这个模式,Gradio 进程会以子进程方式启动 MCP 服务端。
3.2 client.py 的 API 配置
client.py里需要改两个地方。第一个是 OpenAI 客户端的初始化:
self.client = OpenAI( base_url='https://api-inference.modelscope.cn/v1', api_key='ms-xxx', # 替换为你的 ModelScope Access Token )第二个是模型名称:
response = self.client.chat.completions.create( model="Qwen/Qwen3-Next-80B-A3B-Instruct", messages=messages, tools=available_tools, stream=False )如果你用的是其他模型,把model参数换成对应的 Model ID 即可。但要注意,不是所有模型都支持 function calling,选之前确认一下模型卡片里有没有标注工具调用能力。
3.3 app.py 的 Gradio 组件配置
Gradio 界面部分,Qoder 生成的代码结构大概是这样的:
with gr.Blocks(title="天气预报智能体") as demo: with gr.Row(): with gr.Column(scale=1): gr.Markdown(""" # 天气预报智能体 ## 功能特性 - 全球天气查询 - 自然语言交互 - MCP工具调用 ## 使用示例 - "查询北京的天气" - "上海明天的温度和降水概率" """) with gr.Column(scale=2): chatbot = gr.Chatbot(label="对话窗口", height=500) with gr.Row(): with gr.Column(): msg = gr.Textbox(label="输入你的问题", placeholder="例如:查询北京的天气") with gr.Row(): submit_btn = gr.Button("发送", variant="primary") clear_btn = gr.Button("清空对话")scale=1和scale=2控制左右两栏的宽度比例,左边占 1/3,右边占 2/3。height=500是聊天窗口的固定高度,避免消息多了之后页面被撑得太长。
3.4 requirements.txt
创空间部署需要这个文件来安装依赖:
gradio openai mcp httpx版本号可以不写,创空间会自动装最新版。但如果遇到兼容性问题,可以锁定版本,比如gradio==5.0.0。
4. 验证请求:本地预览与线上访问的完整步骤
4.1 本地启动
在 Qoder 的终端里运行:
python app.py如果一切正常,你会看到类似这样的输出:
Running on local URL: http://127.0.0.1:7860打开浏览器访问这个地址,就能看到 Gradio 界面。首次查询时,系统会初始化 MCP 工具连接,可能需要几秒钟。你可以在输入框里输入“查询北京的天气”,观察右侧聊天窗口的回复。
4.2 验证工具调用是否生效
一个完整的查询流程应该包含以下步骤:
- 模型收到“查询北京的天气”
- 模型判断需要调用
get_all_coordinates,参数city="Beijing" - MCP 服务端请求地理编码 API,返回北京的经纬度(39.9042, 116.4074)
- 模型拿到经纬度后,调用
get_hourly_forecast_by_datetime_range,传入经纬度和日期 - MCP 服务端请求天气 API,返回逐小时数据
- 模型把数据整理成自然语言回复
你可以在终端里看到工具调用的日志,比如:
[调用工具 get_all_coordinates,参数: {'city': 'Beijing'}] 工具返回: 找到 1 个坐标结果: 1. Beijing - 纬度: 39.9042, 经度: 116.4074, 国家: China, 省份: Beijing, 时区: Asia/Shanghai如果日志里只有模型回复、没有工具调用,说明模型没有正确识别工具。检查一下tools参数是不是传进去了,以及工具描述是不是足够清晰。
4.3 部署到 ModelScope 创空间
本地跑通后,就可以部署上线了。步骤如下:
步骤 1:创建创空间
进入 ModelScope 创空间页面,点击右上角“我要创建”。填写基本信息:
- 空间名称:
weatherforecast(建议用英文) - 空间标题:
天气预报智能体 - 可见性:公开
- SDK 类型:Gradio
步骤 2:修改 app.py 适配云端环境
把api_key改成从环境变量读取:
import os api_key = os.getenv('MODELSCOPE_API_KEY', '') self.client = OpenAI( base_url='https://api-inference.modelscope.cn/v1', api_key=api_key, )步骤 3:准备部署文件
确保项目目录包含以下文件:
app.py:主程序client.py:MCP 客户端server.py:MCP 服务端requirements.txt:依赖列表README.md:项目说明
步骤 4:配置 README.md
在README.md头部添加部署配置:
--- deployspec: entry_file: app.py ---步骤 5:上传文件
在创空间管理页面点击“空间文件”,把所有文件上传上去。
步骤 6:配置环境变量
点击右上角“设置” → “环境变量管理”,添加:
- 变量名:
MODELSCOPE_API_KEY - 变量值:你的 ModelScope Access Token
- 可见性:私有
步骤 7:上线发布
点击“上线”按钮,系统会自动安装依赖、启动应用、分配公网地址。等待几分钟后,你就能通过创空间提供的 URL 访问了。
4.4 线上验证
访问创空间地址,测试几个查询:
- “查询上海的天气”
- “纽约2025年11月15日到11月17日的天气预报”
- “东京明天的温度和降水概率”
如果返回结果正常,说明部署成功。你可以在创空间页面看到访问量统计。
5. 本篇常见错误排查:401、local proxy failed、reading choices 与 OAuth 报错
5.1 401 Unauthorized
报错信息:
openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Invalid API key', 'type': 'invalid_request_error'}}原因:api_key不对或没传。
排查步骤:
- 检查
client.py里的api_key是不是ms-开头 - 如果部署到创空间,检查环境变量
MODELSCOPE_API_KEY是否配置正确 - 确认 Token 没有过期,重新生成一个试试
5.2 local proxy failed
报错信息:
httpx.ConnectError: [Errno 111] Connection refused或者:
openai.APIConnectionError: Connection error.原因:网络请求被拦截或代理配置有问题。
排查步骤:
- 确认本机网络能正常访问
api-inference.modelscope.cn - 如果用了系统代理,检查
httpx是否走了代理。可以在代码里显式设置:
import httpx async with httpx.AsyncClient(proxy=None) as client: ...- 创空间环境一般不需要代理,如果本地需要,确保代理地址正确
5.3 reading choices 报错
报错信息:
KeyError: 'choices'或者:
IndexError: list index out of range原因:模型返回的 JSON 结构不符合预期,通常是 API 返回了错误信息而不是正常的 completion 结果。
排查步骤:
- 在
response = self.client.chat.completions.create(...)后面加一行print(response),看看实际返回了什么 - 如果返回的是错误信息,检查
model参数是不是正确的 Model ID - 确认模型支持 function calling,不支持的话
tools参数会被忽略或报错
5.4 OAuth 相关报错
报错信息:
openai.BadRequestError: Error code: 400 - {'error': {'message': 'Invalid request format', 'type': 'invalid_request_error'}}原因:请求格式不对,常见于messages列表结构有问题。
排查步骤:
- 检查
messages里每条消息是否有role和content字段 - 工具调用后追加的
assistant消息要包含tool_calls字段 - 工具返回的消息要包含
tool_call_id和name字段
正确的消息结构:
messages.append({ "role": "assistant", "content": "", "tool_calls": [ { "id": call.id, "type": "function", "function": { "name": call.function.name, "arguments": call.function.arguments } } ] })5.5 工具调用不生效
现象:模型直接回复“我无法查询天气”,没有调用工具。
排查步骤:
- 检查
tools参数是不是传进去了 - 检查工具描述是不是足够清晰,模型需要知道这个工具能做什么
- 在 system prompt 里明确告诉模型“如果是天气相关问题,请调用工具”
5.6 创空间部署后无法访问
现象:上线后页面打不开,或者显示“应用启动失败”。
排查步骤:
- 检查
README.md里的entry_file是不是app.py - 检查
requirements.txt里的依赖是不是都装了 - 查看创空间的日志,看看有没有报错信息
- 确认环境变量
MODELSCOPE_API_KEY配置正确
如果日志里显示ModuleNotFoundError,说明依赖没装全,把缺失的包加到requirements.txt里重新上线。
6. 从本地到云端:把天气智能体接入你的日常工具链
这个天气智能体跑通之后,你可以把它当成一个模板,替换掉天气 API 和工具定义,就能快速做出其他类型的智能体。比如把 Open-Meteo 换成某个数据库查询接口,把 Gradio 换成飞书机器人,核心逻辑不用动。
如果你想让模型调用更稳定,可以在client.py的 system prompt 里加一句“如果用户没有指定日期,默认查询今天和明天”。这样模型就不会因为缺少参数而反复询问。
另外,MCP 服务端的工具描述尽量写详细,包括参数格式、取值范围、默认值。模型看到的信息越完整,调用越准确。我试过把weather_variables的可选值全部列在 description 里,模型就能根据用户问题自动选择合适的要素,比如问“会下雨吗”就只取precipitation_probability,问“冷不冷”就取temperature_2m和apparent_temperature。
部署到创空间后,你可以把公网地址分享给朋友测试。如果访问量不大,免费额度完全够用。需要 GPU 加速的话,创空间也支持付费升级。
最后提醒一点:ModelScope 的 Access Token 不要提交到公开仓库。如果代码要开源,用环境变量或者.env文件管理密钥,.env记得加到.gitignore里。