import requests
import json

# API URL 和 API 密钥
api_url = 'https://api.dify.ai/v1/chat-messages'
api_key = 'app-w1Vp06M9L2gYfeNjhcxDyBAx'  # 请替换为你的实际 API 密钥

# 请求数据
data = {
    "inputs": {},
    "query": "hi",
    "response_mode": "streaming",
    "conversation_id": "",
    "user": "abc-123",
}

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

# 发送 POST 请求
response = requests.post(api_url, headers=headers, data=json.dumps(data), stream=True)

# 处理响应
if response.status_code == 200:
    for line in response.iter_lines(decode_unicode=True):
        if line:
            try:
                # 去掉前缀 "data: " 然后解析 JSON 数据
                if line.startswith("data: "):
                    line = line[6:]  # 去除前缀
                event_data = json.loads(line)
                event = event_data.get("event")
                
                if event == "message":
                    # 拼接回答
                    answer = event_data.get("answer", "")
                    print(answer, end='', flush=True)
                elif event == "message_end":
                    # 输出回答结束信息
                    print("\nMessage ended.")
                    metadata = event_data.get("metadata", {})
                    print("Metadata:", json.dumps(metadata, indent=2))
                elif event == "tts_message":
                    # 输出 TTS 消息
                    print("\nTTS Message:", event_data)
                elif event == "tts_message_end":
                    # 输出 TTS 消息结束
                    print("TTS Message ended.")

            except json.JSONDecodeError:
                # 如果不是 JSON 格式的行,跳过
                print(f"Non-JSON line: {line}")
else:
    print(f"Request failed with status code {response.status_code}")
步骤:
  1. 创建虚拟环境:

    1python3 -m venv venv

  2. 激活虚拟环境:

    source venv/bin/activate

  3. 在虚拟环境中安装依赖:

    pip install -r requirements.txt

  4. 启动应用时,确保使用虚拟环境中的 Python 和 Uvicorn:

    venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000

  5. 如果需要退出虚拟环境,可以运行:

    deactivate

1. 检查服务器防火墙(错误点,一定注意)

默认情况下,Ubuntu 的防火墙可能会阻止外部访问某些端口(如 8000)。您需要确保防火墙允许 8000 端口的流量。

步骤:
  1. 检查防火墙状态:

    sudo ufw status
  2. 如果防火墙启用但未开放 8000 端口,请运行以下命令开放端口:

    sudo ufw allow 8000

  3. 再次检查防火墙状态,确认 8000 端口已开放:

    sudo ufw status


2. 检查云服务器安全组规则

如果您使用的是阿里云 ECS 实例,还需要检查安全组规则是否允许外部访问 8000 端口。

步骤:
  1. 登录 阿里云控制台

  2. 找到您的 ECS 实例,点击实例 ID。

  3. 在左侧导航栏中,选择 安全组

  4. 检查安全组规则,确保有如下入方向规则:

    • 协议:TCP
    • 端口范围:8000
    • 授权对象:0.0.0.0/0(或指定前端所在的 IP 地址)
  5. 如果没有相关规则,请添加一条新规则。


3. 检查 Uvicorn 绑定地址

Uvicorn 默认绑定到 127.0.0.1,这意味着它只接受本地请求。您已经使用了 --host 0.0.0.0 参数,这表示 Uvicorn 应该监听所有网络接口。请确保命令正确无误。

验证:

在服务器上运行以下命令,测试本地是否可以访问:

1curl http://127.0.0.1:8000

如果返回 FastAPI 的默认页面或 API 文档,则说明服务正常运行。


4. 检查前端 WebSocket 连接地址

确保前端代码中的 WebSocket 地址正确。例如,如果您的服务器公网 IP 是 123.456.789.0,前端代码应如下:

1const socket = new WebSocket('ws://123.456.789.0:8000/api/chat');
注意事项:
  • 如果您使用了域名,请确保域名解析正确,并且指向服务器的公网 IP。
  • 如果您配置了反向代理(如 Nginx),请确保代理规则正确。

5. 检查跨域问题

FastAPI 应用中已经配置了 CORS 中间件,允许所有来源的请求:

app.add_middleware( 2 CORSMiddleware, 3 allow_origins=["*"], 4 allow_methods=["*"], 5 allow_headers=["*"], 6)

因此,跨域问题通常不会导致连接失败。但如果前端仍然报错,请检查浏览器开发者工具中的网络请求,查看是否有 CORS 相关的错误。


6. 检查日志输出

如果以上步骤均未解决问题,请查看 Uvicorn 的日志输出,寻找可能的错误信息。例如:

  • 是否有异常抛出?
  • 是否有请求到达服务器?

您还可以在代码中添加更多日志,帮助定位问题。例如,在 WebSocket 处理函数中打印更多信息:

@app.websocket("/api/chat") 2async def websocket_endpoint(websocket: WebSocket): 3 print("New WebSocket connection attempt") 4 await manager.connect(websocket) 5 try: 6 while True: 7 prompt = await websocket.receive_text() 8 print(f"Received message: {prompt}") 9 # 其他逻辑... 10 except WebSocketDisconnect: 11 print("WebSocket disconnected") 12 manager.disconnect(websocket)


7. 测试 WebSocket 连接

您可以使用在线工具(如 WebSocket Test Client)或命令行工具(如 websocat)测试 WebSocket 连接。

使用 websocat 测试:
  1. 安装 websocat

    sudo apt install websocat
  2. 测试连接:

    websocat ws://<服务器IP>:8000/api/chat
  3. 发送消息并观察响应。


8. 检查外部 API 调用

您的应用依赖于外部 API(https://api.dify.ai/v1/chat-messages)。如果外部 API 不可用或返回错误,可能导致应用无法正常工作。

验证外部 API:
  1. 在服务器上直接测试外部 API 请求:

    curl -X POST https://api.dify.ai/v1/chat-messages \ 2 -H "Authorization: Bearer app-j5Ye40hwA5feVjrHEz8Tv16T" \ 3 -H "Content-Type: application/json" \ 4 -d '{"inputs": {}, "query": "Hello", "response_mode": "streaming", "conversation_id": "", "user": "abc-123"}'
  2. 检查返回结果是否符合预期。


总结

通过以上步骤,您可以逐步排查问题并找到原因。常见的问题包括:

  1. 防火墙未开放端口。
  2. 安全组规则未配置。
  3. 前端 WebSocket 地址错误。
  4. 跨域配置问题。
  5. 外部 API 不可用。

根据您提供的信息,Uvicorn 服务已经成功启动并在端口 `8000` 上监听。如果前端无法访问,可能是以下原因之一导致的:

---

### **1. 防火墙配置问题**
Ubuntu 系统默认启用了防火墙(`ufw`),可能会阻止外部访问 `8000` 端口。

#### 解决方法:
运行以下命令开放 `8000` 端口:
```bash
sudo ufw allow 8000
```
然后检查防火墙状态:
```bash
sudo ufw status
```
确保 `8000` 端口已允许访问。

---

### **2. ECS 安全组规则未开放端口**
如果您使用的是阿里云 ECS 实例,安全组规则可能未开放 `8000` 端口。

#### 解决方法:
1. 登录 [阿里云控制台](https://ecs.console.aliyun.com/)。
2. 找到对应的 ECS 实例,进入 **安全组** 配置。
3. 添加一条入方向规则,允许 `8000` 端口的流量:
   - 协议:TCP
   - 端口范围:8000
   - 授权对象:`0.0.0.0/0`(或指定 IP 范围以提高安全性)

---

### **3. 前端访问地址错误**
请确认您在浏览器中访问的地址是否正确。例如:
- 如果是本地访问,使用 `http://127.0.0.1:8000`。
- 如果是远程访问,使用 `http://<ECS公网IP>:8000`。

确保 `<ECS公网IP>` 是正确的 ECS 公网 IP 地址。

---

### **4. Uvicorn 绑定地址问题**
虽然日志显示 Uvicorn 已绑定到 `0.0.0.0:8000`,但某些情况下可能存在绑定失败的情况。

#### 检查方法:
运行以下命令查看是否有进程监听 `8000` 端口:
```bash
sudo netstat -tuln | grep 8000
```
如果未看到 `0.0.0.0:8000` 或 `:::8000`,说明绑定失败。

#### 解决方法:
尝试重新启动 Uvicorn:
```bash
uvicorn main:app --host 0.0.0.0 --port 8000
```

---

### **5. 前端与后端跨域问题**
如果前端和后端部署在不同的域名或端口上,可能会触发浏览器的跨域限制。

#### 解决方法:
在后端代码中启用 CORS 支持。例如,在 FastAPI 中可以添加以下代码:
```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 允许所有来源访问(仅用于测试环境)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
```

---

### **6. Docker 容器网络问题(如果使用 Docker)**
如果您在 Docker 容器中运行 Uvicorn,容器的网络配置可能导致外部无法访问。

#### 解决方法:
确保容器使用 `--network host` 模式运行,或者将容器端口映射到宿主机:
```bash
docker run -p 8000:8000 your_image_name
```

---

### **总结**
请按照以下步骤逐一排查:
1. 检查防火墙是否开放 `8000` 端口。
2. 确保 ECS 安全组规则允许 `8000` 端口的流量。
3. 确认访问地址是否正确。
4. 检查 Uvicorn 是否成功绑定到 `0.0.0.0:8000`。
5. 如果涉及跨域问题,启用 CORS 支持。
6. 如果使用 Docker,检查容器网络配置。

如果以上方法仍无法解决问题,请提供更多详细信息(如访问地址、错误提示等),以便进一步分析。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐