📖 Docs: Add documentation for serv00 deployment steps.
Browse files
README.md
CHANGED
@@ -188,12 +188,67 @@ The `hours` parameter in `/stats?hours=48` allows you to control how many hours
|
|
188 |
|
189 |
There are other statistical data that you can query yourself by writing SQL in the database. Other data includes: first token time, total processing time for each request, whether each request was successful, whether each request passed content moderation, the text content of each request, the API key for each request, the number of input tokens, and the number of output tokens for each request.
|
190 |
|
191 |
-
## Vercel
|
192 |
|
193 |
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fyym68686%2Funi-api%2Ftree%2Fmain&env=CONFIG_URL,DISABLE_DATABASE&project-name=uni-api-vercel&repository-name=uni-api-vercel)
|
194 |
|
195 |
After clicking the one-click deployment button, set the environment variable `CONFIG_URL` to the direct link of the configuration file, and set `DISABLE_DATABASE` to true, then click Create to create the project.
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
## Docker local deployment
|
198 |
|
199 |
Start the container
|
|
|
188 |
|
189 |
There are other statistical data that you can query yourself by writing SQL in the database. Other data includes: first token time, total processing time for each request, whether each request was successful, whether each request passed content moderation, the text content of each request, the API key for each request, the number of input tokens, and the number of output tokens for each request.
|
190 |
|
191 |
+
## Vercel remote deployment
|
192 |
|
193 |
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fyym68686%2Funi-api%2Ftree%2Fmain&env=CONFIG_URL,DISABLE_DATABASE&project-name=uni-api-vercel&repository-name=uni-api-vercel)
|
194 |
|
195 |
After clicking the one-click deployment button, set the environment variable `CONFIG_URL` to the direct link of the configuration file, and set `DISABLE_DATABASE` to true, then click Create to create the project.
|
196 |
|
197 |
+
## Serv00 remote deployment
|
198 |
+
|
199 |
+
First, log in to the panel, in Additional services click on the tab Run your own applications to enable the option to run your own programs, then go to the panel Port reservation to randomly open a port.
|
200 |
+
|
201 |
+
If you don't have your own domain name, go to the panel WWW websites and delete the default domain name provided. Then create a new domain with the Domain being the one you just deleted. After clicking Advanced settings, set the Website type to Proxy domain, and the Proxy port should point to the port you just opened. Do not select Use HTTPS.
|
202 |
+
|
203 |
+
ssh login to the serv00 server, execute the following command:
|
204 |
+
|
205 |
+
```bash
|
206 |
+
git clone --depth 1 -b main --quiet https://github.com/yym68686/uni-api.git
|
207 |
+
cd uni-api
|
208 |
+
python -m venv uni-api
|
209 |
+
tmux new -s uni-api
|
210 |
+
source uni-api/bin/activate
|
211 |
+
export CFLAGS="-I/usr/local/include"
|
212 |
+
export CXXFLAGS="-I/usr/local/include"
|
213 |
+
export CC=gcc
|
214 |
+
export CXX=g++
|
215 |
+
export MAX_CONCURRENCY=1
|
216 |
+
export CPUCOUNT=1
|
217 |
+
export MAKEFLAGS="-j1"
|
218 |
+
CMAKE_BUILD_PARALLEL_LEVEL=1 cpuset -l 0 pip install -vv -r requirements.txt
|
219 |
+
cpuset -l 0 pip install -r -vv requirements.txt
|
220 |
+
```
|
221 |
+
|
222 |
+
ctrl+b d to exit tmux, wait a few hours for the installation to complete, and after the installation is complete, execute the following command:
|
223 |
+
|
224 |
+
```bash
|
225 |
+
tmux attach -t uni-api
|
226 |
+
source uni-api/bin/activate
|
227 |
+
export CONFIG_URL=http://file_url/api.yaml
|
228 |
+
export DISABLE_DATABASE=true
|
229 |
+
# Modify the port, xxx is the port, modify it yourself, corresponding to the port opened in the panel Port reservation
|
230 |
+
sed -i '' 's/port=8000/port=xxx/' main.py
|
231 |
+
sed -i '' 's/reload=True/reload=False/' main.py
|
232 |
+
python main.py
|
233 |
+
```
|
234 |
+
|
235 |
+
Use ctrl+b d to exit tmux, allowing the program to run in the background. At this point, you can use uni-api in other chat clients. curl test script:
|
236 |
+
|
237 |
+
```bash
|
238 |
+
curl -X POST https://xxx.serv00.net/v1/chat/completions \
|
239 |
+
-H 'Content-Type: application/json' \
|
240 |
+
-H 'Authorization: Bearer sk-xxx' \
|
241 |
+
-d '{"model": "gpt-4o","messages": [{"role": "user","content": "Hello"}]}'
|
242 |
+
```
|
243 |
+
|
244 |
+
Reference document:
|
245 |
+
|
246 |
+
https://docs.serv00.com/Python/
|
247 |
+
|
248 |
+
https://linux.do/t/topic/201181
|
249 |
+
|
250 |
+
https://linux.do/t/topic/218738
|
251 |
+
|
252 |
## Docker local deployment
|
253 |
|
254 |
Start the container
|
README_CN.md
CHANGED
@@ -194,6 +194,61 @@ yym68686/uni-api:latest
|
|
194 |
|
195 |
点击上面的一键部署按钮后,设置环境变量 `CONFIG_URL` 为配置文件的直链, `DISABLE_DATABASE` 为 true,然后点击 Create 创建项目。
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
## Docker 本地部署
|
198 |
|
199 |
Start the container
|
|
|
194 |
|
195 |
点击上面的一键部署按钮后,设置环境变量 `CONFIG_URL` 为配置文件的直链, `DISABLE_DATABASE` 为 true,然后点击 Create 创建项目。
|
196 |
|
197 |
+
## serv00 远程部署
|
198 |
+
|
199 |
+
首先登录面板,Additional services 里面点击选项卡 Run your own applications 开启允许运行自己的程序,然后到面板 Port reservation 去随便开一个端口。
|
200 |
+
|
201 |
+
如果没有自己的域名,去面板 WWW websites 删掉默认给的域名,再新建一个域名 Domain 为刚才删掉的域名,点击 Advanced settings 后设置 Website type 为 Proxy 域名,Proxy port 指向你刚才开的端口,不要选中 Use HTTPS。
|
202 |
+
|
203 |
+
ssh 登陆到 serv00 服务器,执行下面的命令:
|
204 |
+
|
205 |
+
```bash
|
206 |
+
git clone --depth 1 -b main --quiet https://github.com/yym68686/uni-api.git
|
207 |
+
cd uni-api
|
208 |
+
python -m venv uni-api
|
209 |
+
tmux new -s uni-api
|
210 |
+
source uni-api/bin/activate
|
211 |
+
export CFLAGS="-I/usr/local/include"
|
212 |
+
export CXXFLAGS="-I/usr/local/include"
|
213 |
+
export CC=gcc
|
214 |
+
export CXX=g++
|
215 |
+
export MAX_CONCURRENCY=1
|
216 |
+
export CPUCOUNT=1
|
217 |
+
export MAKEFLAGS="-j1"
|
218 |
+
CMAKE_BUILD_PARALLEL_LEVEL=1 cpuset -l 0 pip install -vv -r requirements.txt
|
219 |
+
cpuset -l 0 pip install -r -vv requirements.txt
|
220 |
+
```
|
221 |
+
|
222 |
+
ctrl+b d 退出 tmux 等待几个小时安装完成,安装完成后执行下面的命令:
|
223 |
+
|
224 |
+
```bash
|
225 |
+
tmux attach -t uni-api
|
226 |
+
source uni-api/bin/activate
|
227 |
+
export CONFIG_URL=http://file_url/api.yaml
|
228 |
+
export DISABLE_DATABASE=true
|
229 |
+
# 修改端口,xxx 为端口,自行修改,对应刚刚在面板 Port reservation 开的端口
|
230 |
+
sed -i '' 's/port=8000/port=xxx/' main.py
|
231 |
+
sed -i '' 's/reload=True/reload=False/' main.py
|
232 |
+
python main.py
|
233 |
+
```
|
234 |
+
|
235 |
+
使用 ctrl+b d 退出 tmux,即可让程序后台运行。此时就可以在其他聊天客户端使用 uni-api 了。curl 测试脚本:
|
236 |
+
|
237 |
+
```bash
|
238 |
+
curl -X POST https://xxx.serv00.net/v1/chat/completions \
|
239 |
+
-H 'Content-Type: application/json' \
|
240 |
+
-H 'Authorization: Bearer sk-xxx' \
|
241 |
+
-d '{"model": "gpt-4o","messages": [{"role": "user","content": "你好"}]}'
|
242 |
+
```
|
243 |
+
|
244 |
+
参考文档:
|
245 |
+
|
246 |
+
https://docs.serv00.com/Python/
|
247 |
+
|
248 |
+
https://linux.do/t/topic/201181
|
249 |
+
|
250 |
+
https://linux.do/t/topic/218738
|
251 |
+
|
252 |
## Docker 本地部署
|
253 |
|
254 |
Start the container
|
main.py
CHANGED
@@ -89,24 +89,11 @@ async def lifespan(app: FastAPI):
|
|
89 |
# print("\nFrontend router routes:")
|
90 |
# for route in frontend_router.routes:
|
91 |
# print(f"Route: {route.path}, methods: {route.methods}")
|
|
|
92 |
# 启动时的代码
|
93 |
if not DISABLE_DATABASE:
|
94 |
await create_tables()
|
95 |
|
96 |
-
TIMEOUT = float(os.getenv("TIMEOUT", 100))
|
97 |
-
timeout = httpx.Timeout(connect=15.0, read=TIMEOUT, write=30.0, pool=30.0)
|
98 |
-
default_headers = {
|
99 |
-
"User-Agent": "curl/7.68.0", # 模拟 curl 的 User-Agent
|
100 |
-
"Accept": "*/*", # curl 的默认 Accept 头
|
101 |
-
}
|
102 |
-
app.state.client = httpx.AsyncClient(
|
103 |
-
timeout=timeout,
|
104 |
-
headers=default_headers,
|
105 |
-
http2=True, # 禁用 HTTP/2
|
106 |
-
verify=True, # 保持 SSL 验证(如需禁用,设为 False,但不建议)
|
107 |
-
follow_redirects=True, # 自动跟随重定向
|
108 |
-
)
|
109 |
-
|
110 |
yield
|
111 |
# 关闭时的代码
|
112 |
await app.state.client.aclose()
|
|
|
89 |
# print("\nFrontend router routes:")
|
90 |
# for route in frontend_router.routes:
|
91 |
# print(f"Route: {route.path}, methods: {route.methods}")
|
92 |
+
|
93 |
# 启动时的代码
|
94 |
if not DISABLE_DATABASE:
|
95 |
await create_tables()
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
yield
|
98 |
# 关闭时的代码
|
99 |
await app.state.client.aclose()
|
utils.py
CHANGED
@@ -111,6 +111,23 @@ def update_config(config_data):
|
|
111 |
|
112 |
# 读取YAML配置文件
|
113 |
async def load_config(app=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
from ruamel.yaml import YAML, YAMLError
|
115 |
yaml = YAML()
|
116 |
yaml.preserve_quotes = True
|
@@ -122,19 +139,19 @@ async def load_config(app=None):
|
|
122 |
if conf:
|
123 |
config, api_keys_db, api_list = update_config(conf)
|
124 |
else:
|
125 |
-
|
126 |
-
config, api_keys_db, api_list =
|
127 |
except FileNotFoundError:
|
128 |
logger.error("'api.yaml' not found. Please check the file path.")
|
129 |
-
config, api_keys_db, api_list =
|
130 |
except YAMLError as e:
|
131 |
logger.error("配置文件 'api.yaml' 格式不正确。请检查 YAML 格式。%s", e)
|
132 |
-
config, api_keys_db, api_list =
|
133 |
except OSError as e:
|
134 |
logger.error(f"open 'api.yaml' failed: {e}")
|
135 |
-
config, api_keys_db, api_list =
|
136 |
|
137 |
-
if config !=
|
138 |
return config, api_keys_db, api_list
|
139 |
|
140 |
import os
|
@@ -152,10 +169,10 @@ async def load_config(app=None):
|
|
152 |
config, api_keys_db, api_list = update_config(config_data)
|
153 |
else:
|
154 |
logger.error(f"Error fetching or parsing config from {config_url}")
|
155 |
-
config, api_keys_db, api_list =
|
156 |
except Exception as e:
|
157 |
logger.error(f"Error fetching or parsing config from {config_url}: {str(e)}")
|
158 |
-
config, api_keys_db, api_list =
|
159 |
return config, api_keys_db, api_list
|
160 |
|
161 |
def ensure_string(item):
|
|
|
111 |
|
112 |
# 读取YAML配置文件
|
113 |
async def load_config(app=None):
|
114 |
+
|
115 |
+
if app and not hasattr(app.state, 'client'):
|
116 |
+
import os
|
117 |
+
TIMEOUT = float(os.getenv("TIMEOUT", 100))
|
118 |
+
timeout = httpx.Timeout(connect=15.0, read=TIMEOUT, write=30.0, pool=30.0)
|
119 |
+
default_headers = {
|
120 |
+
"User-Agent": "curl/7.68.0", # 模拟 curl 的 User-Agent
|
121 |
+
"Accept": "*/*", # curl 的默认 Accept 头
|
122 |
+
}
|
123 |
+
app.state.client = httpx.AsyncClient(
|
124 |
+
timeout=timeout,
|
125 |
+
headers=default_headers,
|
126 |
+
http2=True, # 禁用 HTTP/2
|
127 |
+
verify=True, # 保持 SSL 验证(如需禁用,设为 False,但不建议)
|
128 |
+
follow_redirects=True, # 自动跟随重定向
|
129 |
+
)
|
130 |
+
|
131 |
from ruamel.yaml import YAML, YAMLError
|
132 |
yaml = YAML()
|
133 |
yaml.preserve_quotes = True
|
|
|
139 |
if conf:
|
140 |
config, api_keys_db, api_list = update_config(conf)
|
141 |
else:
|
142 |
+
logger.error("配置文件 'api.yaml' 为空。请检查文件内容。")
|
143 |
+
config, api_keys_db, api_list = {}, {}, []
|
144 |
except FileNotFoundError:
|
145 |
logger.error("'api.yaml' not found. Please check the file path.")
|
146 |
+
config, api_keys_db, api_list = {}, {}, []
|
147 |
except YAMLError as e:
|
148 |
logger.error("配置文件 'api.yaml' 格式不正确。请检查 YAML 格式。%s", e)
|
149 |
+
config, api_keys_db, api_list = {}, {}, []
|
150 |
except OSError as e:
|
151 |
logger.error(f"open 'api.yaml' failed: {e}")
|
152 |
+
config, api_keys_db, api_list = {}, {}, []
|
153 |
|
154 |
+
if config != {}:
|
155 |
return config, api_keys_db, api_list
|
156 |
|
157 |
import os
|
|
|
169 |
config, api_keys_db, api_list = update_config(config_data)
|
170 |
else:
|
171 |
logger.error(f"Error fetching or parsing config from {config_url}")
|
172 |
+
config, api_keys_db, api_list = {}, {}, []
|
173 |
except Exception as e:
|
174 |
logger.error(f"Error fetching or parsing config from {config_url}: {str(e)}")
|
175 |
+
config, api_keys_db, api_list = {}, {}, []
|
176 |
return config, api_keys_db, api_list
|
177 |
|
178 |
def ensure_string(item):
|