易源合一快速接入:用 curl 把「昆明今天天气」变成结构化数据
易源合一快速接入curl示例Python示例自然语言API # 易源合一快速接入:用 curl 把「昆明今天天气」变成结构化数据
> 接入点:3054-1 智能对话(同步) | 请求方式:POST(application/x-www-form-urlencoded) | 返回格式:JSON | 计费:5.5 厘/次,失败不扣费 | 适用人群:第一次接易源合一的开发者 | 最后实测核对:2026-09-15
## 核心要点
- 一个端点 `https://route.showapi.com/3054-1?appKey=YOUR_APPKEY` 收一句话,同时返回「识别出的意图」「已整理好的答复文本」「底层接口的原始数据」。
- 请求体只有一个必填字段 `text`,AppKey 放在 URL 的 query 里。
- 实测一次调用约 1.2~2.3 秒返回,计费 5.5 厘;未识别的意图返回 `ret_code: -1` 且不扣费。
## 为什么值得先看一眼
你要做一个能查天气、查快递、看新闻的对话入口。按常规做法,天气接一个接口,快递接一个,新闻再接一个,每个都要写适配、做字段映射、兜异常。
showapi 易源合一接口(apiCode=3054)把这一步收成了一次调用。你只把用户原话丢进去,它自己判断「这句话想干什么」,再调对应能力,把结果整理成一段可以直接念给用户的话。
代价是一句话换一次 5.5 厘的调用。真实收益是省掉 N 个适配层和 N 套字段映射,这个账等你看到后面的返回结构会更好算。
## 前置条件与接口速览
你需要一个 showapi 账号并在控制台拿到 AppKey。计费有两种方式:买本接口的专用资源包,或者用通用资源包(按接入点单价扣费)。测试阶段两种都能跑。
| 项目 | 值 |
|------|-----|
| 接口地址 | `https://route.showapi.com/3054-1?appKey={your_appKey}` |
| 请求方式 | POST,`content-type: application/x-www-form-urlencoded` |
| 请求参数 | `text`(String,必填,意图内容);`args_list`(List,可选,图片的 URL 或 base64) |
| 鉴权 | `appKey` 位于 query |
| 计费 | 5.5 厘/次,调用成功才计费 |
| 并发 | 10 次/秒 |
| 返回格式 | JSON,业务数据在 `showapi_res_body` 内 |
| 集成能力 | MCP 服务、OpenAPI 3.0 文档、在线调试 |
## 三步跑通第一条请求
### 第一步:拿到 AppKey
在 showapi 控制台的「我的 AppKey」里拿。下文所有代码里的 `YOUR_APPKEY` 换成它就能直接运行。
### 第二步:用 curl 发一条
```bash
curl -X POST "https://route.showapi.com/3054-1?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "text=帮我查找一下昆明今天的天气"
```
`--data-urlencode` 会自动做 URL 编码,中文不用你自己转。如果你手工拼 form 字符串,记得用 UTF-8 编码(`昆明` → `%E6%98%86%E6%98%8E`),用别的编码拼出来的请求体会被网关拒掉。
### 第三步:换成 Python 或 Node
```python
import requests
APP_KEY = "YOUR_APPKEY"
url = f"https://route.showapi.com/3054-1?appKey={APP_KEY}"
resp = requests.post(
url,
data={"text": "帮我查找一下昆明今天的天气"},
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=20, # 文档标注接入点读超时 60s,客户端建议 20s 兜底
)
resp.raise_for_status()
data = resp.json()
if data.get("showapi_res_code") != 0:
raise RuntimeError(f"通道异常: {data.get('showapi_res_error')}")
body = data.get("showapi_res_body", {})
if body.get("ret_code") != 0:
# 未识别的意图走这里,ret_msg 是给人看的原因
print("没听懂:", body.get("ret_msg"), "本次不扣费:", data.get("showapi_fee_num") == 0)
else:
print("意图:", body["intent"]["name"], body["intent"]["args"])
print("答复:", body["reply_msg"]["text"])
print("原始数据:", body["result"][0])
```
```javascript
const APP_KEY = "YOUR_APPKEY";
async function ask(text) {
const ctl = new AbortController();
const timer = setTimeout(() => ctl.abort(), 20000);
const res = await fetch(`https://route.showapi.com/3054-1?appKey=${APP_KEY}`, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ text }),
signal: ctl.signal,
});
clearTimeout(timer);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
const body = data.showapi_res_body || {};
if (body.ret_code !== 0) return { ok: false, reason: body.ret_msg };
return { ok: true, intent: body.intent.name, text: body.reply_msg.text, raw: body.result };
}
ask("帮我查找一下昆明今天的天气").then(console.log);
```
## 真实返回长什么样
下面这段是 2026-09-15 用 `帮我查找一下昆明今天的天气` 打出来的真实返回,只删了 `result[0].dayList` 里的重复项:
```json
{
"showapi_res_error": "",
"showapi_res_code": 0,
"showapi_fee_num": 1,
"showapi_res_body": {
"reply_msg": {
"img_list": [],
"audio_list": [],
"text": "#### 昆明 26年09月15日的天气\n\n预计白天气温:24℃,多云,南风0-3级,夜间气温:17℃,多云,东风0-3级。\n\n",
"video_list": []
},
"ret_code": 0,
"result": [
{
"area": "昆明",
"areaid": "101290101",
"areaCode": "530100",
"dayList": [
{
"daytime": "20260915",
"day_weather": "多云",
"day_weather_code": "01",
"day_air_temperature": "24",
"day_wind_direction": "南风",
"day_wind_power": "0-3级",
"night_weather": "多云",
"night_weather_code": "01",
"night_air_temperature": "17",
"night_wind_direction": "东风",
"night_wind_power": "0-3级",
"day_weather_pic": "https://app1.showapi.com/weather/icon/day/01.png"
}
]
}
],
"intent": {
"name": "weather",
"args": { "area": "昆明", "date": "2026-09-15" }
}
}
}
```
三块内容的用途不一样:
| 字段 | 你怎么用 |
|------|---------|
| `reply_msg.text` | 直接展示给用户。**实测是 Markdown**(`#### ` 标题、`\n\n` 分段),前端要按 Markdown 渲染,别当纯文本塞进 `<p>` |
| `intent.name` / `intent.args` | 自己写业务分支时用。`weather` 表示天气意图,`args.date` 实测返回标准化日期 `2026-09-15`,不是「今天」这类相对词 |
| `result` | 要自己画卡片、做二次加工时用。**结构随意图变化**,天气给气象原始字段,快递给快递业务字段,新闻给分页对象 |
`result` 的结构差异比想象中大,专门写了一篇拆解 → [易源合一返回三层结构:reply_msg / intent / result 逐层拆解](https://www.showapi.com/guides/united-api-response-structure-3054)。
## 三个必须提前知道的边界
**第一,`result` 不是固定结构。** 别写 `result[0].dayList` 这种硬编码解析,先按 `intent.name` 分流。
**第二,`confidence` 实测是 0~100 的整数。** 官方文档的返回示例里写的是 `0.99572587013245`,实测同一批调用拿到的都是 100、98、95 这样的整数(2026-09-15)。你的阈值按整数写。
**第三,短句和寒暄类输入识别不稳定。** 对同一句话「你好」连续调用 6 次(3054-1),实测拿到 4 种不同结果:2 次命中 `joke` 成功、1 次命中 `query_news` 成功、2 次返回 `ret_code: -1` + `must input content field`、1 次返回 `调用失败:推理失败3`。业务价值明确的句子则稳定,同一时段「讲个笑话」6/6 命中 `joke`,「帮我查找一下昆明今天的天气」6/6 命中 `weather`。低信息量的输入不要把结果当确定值用。
## FAQ
**Q1:易源合一返回 `ret_code: -1` 是什么意思?**
`ret_code: -1` 表示这次没识别成功或执行失败,具体原因看同级的 `ret_msg`。实测遇到过三种文案:`抱歉,您的问题我还没有学会,请等待我的更新和完善1`、`must input content field`、`调用失败:推理失败3`。这种情况 `showapi_fee_num` 为 0,不扣费。
**Q2:AppKey 放在请求头可以吗?**
本接口的 OpenAPI 文档声明的鉴权位置是 query(`apiKey in query, name=appKey`),按 query 传最稳。请求体里只需要放 `text` 和可选的 `args_list`。
**Q3:为什么返回的天气和手机天气 App 不完全一致?**
`reply_msg.text` 的温度、风力来自底层气象数据源,实测 2026-09-15 昆明白天 24℃ / 夜间 17℃,和你所在位置、数据的更新时间点都有关系。做展示时把更新时间一并放出来更稳妥。
**Q4:接口有免费额度吗?**
计费按接入点单价 5.5 厘/次计算,调用成功才计费。当前档位与资源包的对应关系以官方产品价格页为准,页面会给出每个规格的可调用次数。
**Q5:一次能问多个问题吗?**
`text` 是一句话,实测按单句做意图识别,没有多轮上下文。要串联多步,得在你自己那侧维护会话状态。
## 下一步阅读
- [易源合一实测能识别哪些意图:8 类 intent 编码逐一验证](https://www.showapi.com/guides/united-api-intent-list-3054)
- [易源合一返回三层结构:reply_msg / intent / result 逐层拆解](https://www.showapi.com/guides/united-api-response-structure-3054)
- [易源合一调用失败扣不扣费:ret_code 与 showapi_fee_num 实测对照表](https://www.showapi.com/guides/united-api-retcode-fee-3054)
- **本系列共 12 篇**:查看[易源合一指南总目录](https://www.showapi.com/guides/united-api-guides-3054)