# 02 · 工具清单与官方链接

> **想先搞懂「为什么选这些工具、怎么用」？** 请读专题文档：[06-工具选型与使用说明.md](./06-工具选型与使用说明.md)  
> 本文侧重：**官方原链接、请求参数、返回格式**等技术细节。

本文列出本项目**实际调用**的所有外部能力：大模型接口、四个业务工具、以及它们对应的**官方文档与原链接**。

---

## 总览表

| 类别 | 名称 | 是否需 API Key | 代码位置 |
|------|------|----------------|----------|
| 大模型 | DashScope `qwen-plus` | 是 | `src/lib/dashscope.ts` |
| 工具 1 | `get_current_datetime` | 否 | `src/lib/tools.ts` |
| 工具 2 | `calculate` | 否 | `src/lib/tools.ts` |
| 工具 3 | `get_weather` | 否 | `src/lib/tools.ts` |
| 工具 4 | `get_exchange_rate` | 否 | `src/lib/tools.ts` |

---

## 一、大模型：阿里云 DashScope

### 用途

- 理解用户问题
- 决定是否调用工具（Function Calling）
- 根据工具结果生成最终回答

### 本项目使用的接口

| 项目 | 值 |
|------|-----|
| 模型 | `qwen-plus` |
| 调用方式 | OpenAI 兼容模式 Chat Completions |
| 开发环境请求路径 | `/api/dashscope/compatible-mode/v1/chat/completions` |
| 实际转发目标 | `https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions` |

### 官方链接

| 说明 | 链接 |
|------|------|
| 百炼控制台（获取 API Key） | https://bailian.console.aliyun.com/ |
| DashScope API 参考（中文） | https://help.aliyun.com/zh/model-studio/qwen-api-via-dashscope |
| Function Calling 文档（中文） | https://help.aliyun.com/zh/model-studio/qwen-function-calling |
| OpenAI 兼容模式说明 | https://help.aliyun.com/zh/model-studio/compatibility-of-openai-with-dashscope |

### 请求示例（简化）

```http
POST /compatible-mode/v1/chat/completions
Authorization: Bearer sk-xxxxxxxx
Content-Type: application/json

{
  "model": "qwen-plus",
  "messages": [...],
  "tools": [...],
  "tool_choice": "auto"
}
```

### 代理配置

开发时由 Vite 把浏览器请求转发到 DashScope，避免 CORS 问题。见 `vite.config.ts`：

```ts
proxy: {
  '/api/dashscope': {
    target: 'https://dashscope.aliyuncs.com',
    changeOrigin: true,
    rewrite: (path) => path.replace(/^\/api\/dashscope/, ''),
  },
}
```

---

## 二、工具 1：`get_current_datetime`

### 用途

回答「现在几点」「今天星期几」等需要**当前时刻**的问题。

### 数据来源

- **不调用外部 HTTP API**
- 使用浏览器 / Node 运行环境的 `Date` 对象 + `toLocaleString`
- 按 IANA 时区格式化（默认 `Asia/Shanghai`）

### 参数

| 参数 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `timezone` | string | IANA 时区名 | `Asia/Shanghai` |

### 参考链接

| 说明 | 链接 |
|------|------|
| IANA 时区数据库 | https://www.iana.org/time-zones |
| MDN：Date.prototype.toLocaleString | https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString |

### 返回示例

```text
时区 Asia/Shanghai 的当前时间：2026/06/09 星期二 14:30:25
```

---

## 三、工具 2：`calculate`

### 用途

精确数学计算，避免大模型心算错误（如 `12345 × 6789`）。

### 数据来源

- **本地计算**，不访问网络
- 在 `tools.ts` 的 `safeCalculate()` 中执行
- 仅允许数字和 `+ - * / ^ % ( )`，防止注入

### 参数

| 参数 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `expression` | string | 数学表达式 | `12345 * 6789` |

### 返回示例

```text
12345 * 6789 = 83810205
```

---

## 四、工具 3：`get_weather`

### 用途

查询指定城市的**实时天气**（温度、湿度、风速、天气状况）。

### 数据来源

调用 **Open-Meteo** 免费公开 API，分两步：

#### 步骤 A：城市 → 经纬度（地理编码）

| 项目 | 值 |
|------|-----|
| 原链接模板 | `https://geocoding-api.open-meteo.com/v1/search?name={城市}&count=1&language=zh&format=json` |
| 示例 | https://geocoding-api.open-meteo.com/v1/search?name=深圳&count=1&language=zh&format=json |

#### 步骤 B：经纬度 → 实时天气

| 项目 | 值 |
|------|-----|
| 原链接模板 | `https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current=temperature_2m,weather_code,relative_humidity_2m,wind_speed_10m&timezone=auto` |

### 官方链接

| 说明 | 链接 |
|------|------|
| Open-Meteo 首页 | https://open-meteo.com/ |
| 天气预报 API 文档 | https://open-meteo.com/en/docs |
| 地理编码 API 文档 | https://open-meteo.com/en/docs/geocoding-api |

### 参数

| 参数 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `city` | string | 城市名称 | `深圳` |

### 返回示例

```text
深圳（中国）当前天气：多云
温度：25.2°C
湿度：78%
风速：12.5 km/h
```

---

## 五、工具 4：`get_exchange_rate`

### 用途

查询两种货币之间的**实时汇率**并换算金额。

### 数据来源

调用 **Frankfurter** 免费公开 API（欧洲央行参考汇率）。

| 项目 | 值 |
|------|-----|
| 原链接模板 | `https://api.frankfurter.app/latest?from={FROM}&to={TO}` |
| 示例 | https://api.frankfurter.app/latest?from=USD&to=CNY |

### 官方链接

| 说明 | 链接 |
|------|------|
| Frankfurter 首页 | https://www.frankfurter.app/ |
| API 文档 | https://www.frankfurter.app/docs/ |
| GitHub 开源仓库 | https://github.com/lineofflight/frankfurter |

### 参数

| 参数 | 类型 | 必填 | 说明 | 示例 |
|------|------|------|------|------|
| `from_currency` | string | 是 | 源货币代码 | `USD` |
| `to_currency` | string | 是 | 目标货币代码 | `CNY` |
| `amount` | string | 否 | 换算金额，默认 1 | `100` |

### 返回示例

```text
汇率日期：2026-06-08
1 USD = 6.7819 CNY
100 USD = 678.1900 CNY
```

---

## 六、示例问题与推荐工具对照

| 示例问题 | 预期调用的工具 |
|----------|----------------|
| 深圳现在的天气怎么样？ | `get_weather` |
| 请计算 12345 × 6789 等于多少？ | `calculate` |
| 现在北京时间是几点？星期几？ | `get_current_datetime` |
| 100 美元现在能换多少人民币？ | `get_exchange_rate` |
| 用一句话解释什么是 ReAct？ | 无（纯知识回答） |

预设问题定义在 `src/data/questions.ts`。

---

## 七、命令行自测脚本

不打开浏览器也可验证工具是否正常：

```bash
# 测试四个业务工具（无需 DashScope Key）
node scripts/test-tools.mjs

# 测试完整 ReAct + 普通模式（需环境变量 DASHSCOPE_API_KEY）
node scripts/test-react.mjs
```

---

## 八、随堂检查

1. 哪个工具需要 DashScope API Key？
2. `get_weather` 实际访问了哪两个 Open-Meteo 接口？
3. `calculate` 为什么要在本地算，而不是让模型直接算？

<details>
<summary>参考答案</summary>

1. 只有大模型接口（qwen-plus）需要 Key；四个业务工具中的天气/汇率 API 免费无需 Key。
2. 地理编码 `geocoding-api.open-meteo.com` + 天气预报 `api.open-meteo.com`。
3. 大数运算模型容易出错，本地计算结果确定、可验证。

</details>

---

下一篇：[03-开发思路与项目架构.md](./03-开发思路与项目架构.md)
