# 运行指南

程序在课程服务器运行，网页通过 SSH 转发在自己的浏览器打开。

## 准备个人目录

在已连接服务器的终端中执行：

```bash
mkdir -p ~/homework1
cd ~/homework1
```

把资料包的 `app.py` 复制到这里。使用 VS Code 时，确认编辑的是服务器文件；在本机保存同名文件不会自动更新服务器。已有程序先留副本，再开始修改。

## 两个终端与浏览器

| 位置 | 用途 |
| --- | --- |
| 终端 A：服务器 Bash | 设置配置、运行 Python、查看报错 |
| 终端 B：本机终端 | 保持 SSH 端口转发 |
| 本机浏览器 | 显示页面、发送问题 |

在终端 A 检查环境，再启动程序。若课程服务器提供以下 pubpy 路径，执行：

```bash
/opt/miniconda/envs/pubpy/bin/python -c \
  "import flask, requests; print('环境就绪')"
/opt/miniconda/envs/pubpy/bin/python app.py
```

实际路径不同时按课程说明替换；导入失败先检查环境，不要自行修改公共环境。骨架使用 Flask，后续还会使用 Requests。

在终端 B 执行以下命令。如果你平时用 `ssh test_stu` 登录服务器，就把命令最后的 `你的SSH别名` 替换成 `test_stu`。请使用自己账号对应的连接名称：

```bash
ssh -N -L 127.0.0.1:18500:127.0.0.1:8500 你的SSH别名
```

浏览器打开 **http://127.0.0.1:18500/**。本机 18500 通过 SSH 转到服务器 8500。起始页面只能演示回复，此时不需要 API Key。

两个终端保持运行是正常现象。**修改 Python 后，在终端 A 按 Ctrl+C 停止旧程序，再重新启动。** 仅刷新网页不会重载代码；端口不变时，终端 B 可以保持运行。

服务器 8500 被占用时，同时改 `app.py` 的 `port` 和转发命令最后的远端端口；本机 18500 被占用时，改前面的本机端口及浏览器地址。结束后，在两个终端分别按 Ctrl+C。

## 模型配置

接入模型前，在终端 A 停止程序，然后在**同一个服务器 Bash 终端**执行：

```bash
export LLM_API_URL="https://api.deepseek.com/chat/completions"
export LLM_MODEL="你实际使用的模型名称"
read -r -s -p '请输入 API Key: ' LLM_API_KEY
export LLM_API_KEY
printf '\n'
```

示例是 [DeepSeek Chat Completions](https://api-docs.deepseek.com/api/create-chat-completion/) 的完整请求地址。使用课程网关时，改用课程提供的对应地址、模型和 Key，不要只填官网或基础地址。

Key 在提示后输入，不显示字符。这些是 Bash 命令，不能直接在 Windows PowerShell 中执行，也不是 Python 代码。

配置好后，从同一终端启动 `app.py`；换终端需重新设置，修改配置需重启。只有按教程加入读取代码后，程序才会使用这些变量。不要将真实 Key 写入代码、README、截图或提交文件。

## 常见问题

| 现象 | 优先检查 |
| --- | --- |
| 网页打不开或仍是旧页面 | 两个终端、端口、服务器文件是否已保存和重启 |
| 语法或缩进错误 | 报错行及前一行的引号、括号、冒号和缩进 |
| 参数数量错误 | 函数定义与所有调用是否同步修改 |
| 提交后出现 405 | 路由是否允许 POST，表单地址是否正确 |
| 仍显示演示回复 | 是否删除了演示用的提前 return |
| 401、403、404 | 认证、权限、完整请求地址和模型 |
| 429 或超时 | 额度、频率、网络和服务状态 |
| 第二段会话发回第一段 | action 和成功跳转是否带当前 chat 编号 |

程序错误要到终端 A 查看具体行号，再结合正在修改的函数排查。