☰
【TIDE DIARY 6】用 Cursor 给 FastAPI + Streamlit 项目配 TaoToken:settings.json 与 config.toml 骨架一次跑通
2026/9/25 10:53:36 网站建设 项目流程

1. 为什么 FastAPI + Streamlit 联调时 Key 总是配得乱七八糟

做本地原型最舒服的组合之一,就是 FastAPI 当后端、Streamlit 当界面。后端负责调模型、跑链路,前端负责把输入框、按钮、结果区拼起来,改一行代码就能看到效果。但真正动手时,很多人卡在第一步:Key 和 API 通道到底放哪。

我见过最常见的三种写法。第一种是把 Key 硬编码在main.py里,前端app.py又复制一份,改一次要改两个文件。第二种是前端直接调模型,后端只做转发,结果两套 SDK、两套 base_url,日志对不上。第三种是环境变量在 PowerShell 里$env:设了,但 Cursor 的终端和 Streamlit 子进程读不到,报 401 还找不到原因。

这篇就聚焦一个目标:在 Cursor 里给 FastAPI + Streamlit 项目配一套统一的 Key 与 API 通道,让前后端只认一个入口。交付物是三样东西——项目级settings.json、后端config.toml骨架、以及启动 FastAPI、拉起 Streamlit、验证请求链路的三步动作。适合正在用 Cursor 做本地开发、想快速跑通原型的人。

核心思路很简单:Key 只存一份,通道只配一次,后端统一出口,前端只调本地接口。这样 Streamlit 永远不碰模型 Key,FastAPI 成为唯一调用方,排查问题时只看一个日志源。

2. TaoToken 前置:把统一通道先准备好

在写配置之前,先把「通道」这件事定下来。TaoToken 在这里扮演的角色是统一的模型调用入口,OpenAI 兼容协议,所以 FastAPI 里用openai或langchain-openai都能直接接。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api 。

你需要先拿到一个 API Key。进控制台创建即可,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,Key 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。创建后复制那串sk-开头的字符串,后面所有配置都围绕它展开。

这里有个关键决定:Key 不放前端,也不放 Cursor 的全局设置里,而是放项目根目录的.env。原因有三点。一是 Cursor 的settings.json是编辑器级配置,放 Key 容易在同步或分享时泄露;二是 Streamlit 重启频繁,环境变量注入不稳定;三是.env配合python-dotenv读取最可控,后端启动时加载一次,前端完全不需要知道。

如果你后面要做长期编码或 Agent 类任务,可以了解下 Coding Plan,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。原型阶段先用按量 Key 就够了。

3. 可复制配置:settings.json 与 config.toml 骨架

3.1 项目目录结构先定好

在 Cursor 里打开项目后,建议目录长这样,后端和前端分开,配置集中在根目录:

cursor_tide_fast/ ├── .env ├── .cursor/ │ └── settings.json ├── config.toml ├── requirements.txt ├── backend/ │ └── main.py └── frontend/ └── app.py

.env只放一行,注意不要提交到 git:

TAOTOKEN_API_KEY=sk-你的实际Key TAOTOKEN_BASE_URL=https://taotoken.net/api

3.2 Cursor 项目级 settings.json

Cursor 支持项目级配置,放在.cursor/settings.json。这里不放 Key,只放解释器路径和终端环境,保证 Cursor 内置终端启动时能读到虚拟环境:

{ "python.defaultInterpreterPath": "${workspaceFolder}/.venv/Scripts/python.exe", "python.terminal.activateEnvironment": true, "terminal.integrated.env.windows": { "PYTHONPATH": "${workspaceFolder}" }, "files.exclude": { "**/__pycache__": true, "**/.venv": true } }

python.terminal.activateEnvironment设为 true 后,你在 Cursor 里新开终端会自动激活.venv,不用每次手动敲激活命令。PYTHONPATH指向工作区根目录,这样backend和frontend之间互相 import 不会报模块找不到。

3.3 后端 config.toml 骨架

config.toml放在项目根目录,作为后端读取模型参数的唯一来源。Key 不写在这里,只写通道和模型名:

[api] base_url = "https://taotoken.net/api" timeout = 60 max_retries = 3 [model] default = "gpt-4o-mini" temperature = 0.7 max_tokens = 2048 [server] host = "127.0.0.1" port = 8012

这样设计的好处是:换模型只改config.toml一行,换 Key 只改.env一行,两者互不干扰。后端启动时用tomllib(Python 3.11+ 内置)读取,配合dotenv加载 Key。

3.4 后端 main.py 读取配置

import os import tomllib from pathlib import Path from dotenv import load_dotenv from fastapi import FastAPI from pydantic import BaseModel from openai import OpenAI load_dotenv() ROOT = Path(__file__).resolve().parent.parent with open(ROOT / "config.toml", "rb") as f: cfg = tomllib.load(f) client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url=cfg["api"]["base_url"], timeout=cfg["api"]["timeout"], ) app = FastAPI() class ChatIn(BaseModel): prompt: str @app.post("/chat") def chat(body: ChatIn): resp = client.chat.completions.create( model=cfg["model"]["default"], messages=[{"role": "user", "content": body.prompt}], temperature=cfg["model"]["temperature"], ) return {"reply": resp.choices[0].message.content}

注意base_url直接取自config.toml,没有在代码里写死。这样前端永远只调http://127.0.0.1:8012/chat,不接触任何模型 Key。

3.5 前端 app.py 只调本地接口

import streamlit as st import httpx st.title("TIDE DIARY 原型") prompt = st.text_area("输入内容", height=120) if st.button("发送") and prompt: with st.spinner("请求中..."): r = httpx.post( "http://127.0.0.1:8012/chat", json={"prompt": prompt}, timeout=60, ) st.write(r.json().get("reply", "无返回"))

Streamlit 这边完全没有openai依赖,也没有 Key。它只是一个 HTTP 客户端,指向本地 FastAPI。这就是「统一通道」的落地方式。

4. 三步动作:启动 FastAPI、拉起 Streamlit、验证链路

4.1 第一步:启动 FastAPI 后端

在 Cursor 里新开一个终端,确认虚拟环境已激活,然后启动:

python -m uvicorn backend.main:app --host 127.0.0.1 --port 8012 --reload

看到Uvicorn running on http://127.0.0.1:8012就说明后端起来了。--reload让你改main.py后自动重启,原型阶段很省事。

如果端口被占用,先查一下:

$tcp = Get-NetTCPConnection -LocalPort 8012 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 if ($tcp) { Stop-Process -Id $tcp.OwningProcess -Force }

4.2 第二步:拉起 Streamlit 前端

再开一个终端窗口,不要关掉后端那个:

streamlit run frontend/app.py --server.headless=true --server.port=8501

浏览器打开http://localhost:8501,能看到输入框和按钮就对了。--server.headless=true避免它自动弹浏览器,在 Cursor 里更干净。

4.3 第三步:验证请求链路

先用 curl 直接打后端,确认 FastAPI 到 TaoToken 这一段通:

curl -X POST http://127.0.0.1:8012/chat \ -H "Content-Type: application/json" \ -d "{\"prompt\":\"用一句话解释什么是 FastAPI\"}"

返回类似{"reply":"FastAPI 是一个基于 Python 类型注解的高性能 Web 框架。"}就说明后端链路正常。然后再去 Streamlit 页面点一次按钮,如果也能返回内容,说明前端到后端这一段也通了。

整条链路是:Streamlit → FastAPI → TaoToken → 模型 → 原路返回。任何一段出问题,都能通过这两次验证快速定位。

5. 本篇常见错排查

5.1 401 Unauthorized

最常见的原因是.env没被加载。检查两点:一是.env是否在项目根目录,二是load_dotenv()是否在读取os.environ之前调用。如果 Key 复制时带了空格或换行,也会 401,建议重新复制一次。

5.2 Connection refused 到 127.0.0.1:8012

说明 FastAPI 没起来,或者端口不对。先确认后端终端有没有报错,再看config.toml里的port和启动命令的--port是否一致。Streamlit 里写死的地址也要跟这个端口对齐。

5.3 Streamlit 报 ModuleNotFoundError

多半是虚拟环境没激活,或者PYTHONPATH没生效。在 Cursor 里确认终端提示符前面有(.venv),没有的话手动激活一次。项目级settings.json里的python.terminal.activateEnvironment就是解决这个的。

5.4 模型名报错 model not found

config.toml里的default要写通道支持的模型名。如果换了模型名报错,先用模型对话页面确认一下可用模型列表,地址是 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。确认后再改config.toml。

5.5 超时但没报错

原型阶段请求大模型偶尔会慢,config.toml里timeout = 60是秒数。如果经常超时,先确认网络到https://taotoken.net/api是否正常,再考虑调大 timeout。Streamlit 那边的httpx.post也要设同样的 timeout,否则前端先断。

6. 配置收尾与后续接入

这套骨架跑通后,你手里其实有了一个可复用的模板:.env管 Key,config.toml管通道和模型参数,settings.json管编辑器环境,FastAPI 做唯一出口,Streamlit 只做展示。后面加新接口,只需要在main.py里加路由,前端继续用 httpx 调本地,Key 和通道完全不用动。

如果你要接着做更复杂的接入,比如流式输出、多模型切换、或者把 FastAPI 接到别的客户端,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面把 base_url、鉴权头、请求格式都列清楚了。Key 管理和新建都在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。

最后提醒一个实操细节:.env一定要加进.gitignore,Cursor 的settings.json里也别放 Key。原型阶段图快,但 Key 泄露的代价比省那几秒大得多。把 Key 留在后端、通道写进 config、前端只认本地端口,这三条守住,后面怎么改都不会乱。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询