Skip to content

Commit 168744f

Browse files
committed
COST_ON_INLET feature test passed
1 parent 1bec245 commit 168744f

File tree

9 files changed

+45
-28
lines changed

9 files changed

+45
-28
lines changed

.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ API_KEY=your-api-key-here # Used for authentication when sending requests to Mon
1111
# DEFAULT_MODEL_OUTPUT_PRICE=60 # Default output price for models
1212
# DEFAULT_MODEL_PER_MSG_PRICE=-1 # Default price per message for models, -1 means charging by tokens
1313
# INIT_BALANCE=0 # Initial balance for users, optional
14+
# COST_ON_INLET=0 # Pre-deduction amount on inlet, can be a fixed number (e.g. 0.1) or model-specific (e.g. gpt-4:0.32,gpt-3.5:0.01)
1415

1516
# PostgreSQL Database Configuration (Optional, configure these if using external database)
1617
# POSTGRES_HOST=

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ sudo docker compose up -d
4343

4444
### Optional
4545

46-
| Variable Name | Description | Default Value |
47-
| --------------------------- | ----------------------------------------------------- | ------------- |
48-
| DEFAULT_MODEL_INPUT_PRICE | Default model input price, in USD per million tokens | `60` |
49-
| DEFAULT_MODEL_OUTPUT_PRICE | Default model output price, in USD per million tokens | `60` |
50-
| DEFAULT_MODEL_PER_MSG_PRICE | Default model price for each message, in USD | `-1` |
51-
| INIT_BALANCE | Initial user balance | `0` |
46+
| Variable Name | Description | Default Value |
47+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
48+
| DEFAULT_MODEL_INPUT_PRICE | Default model input price, in USD per million tokens | `60` |
49+
| DEFAULT_MODEL_OUTPUT_PRICE | Default model output price, in USD per million tokens | `60` |
50+
| DEFAULT_MODEL_PER_MSG_PRICE | Default model price for each message, in USD | `-1` |
51+
| INIT_BALANCE | Initial user balance | `0` |
52+
| COST_ON_INLET | Pre-deduction amount on inlet. Can be a fixed number for all models (e.g. `0.1`), or model-specific format (e.g. `gpt-4:0.32,gpt-3.5:0.01`) | `0` |
5253

5354
<h2>Gallery</h2>
5455

5556
![](https://github.com/user-attachments/assets/63f23bfd-f271-41e8-a71c-2016be1d501a)
56-

app/api/v1/outlet/route.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { encode } from "gpt-tokenizer/model/gpt-4";
33
import { Pool, PoolClient } from "pg";
44
import { createClient } from "@vercel/postgres";
55
import { query, getClient } from "@/lib/db/client";
6+
import { getModelInletCost } from "@/lib/utils/inlet-cost";
67

78
const isVercel = process.env.VERCEL === "1";
89

@@ -128,10 +129,12 @@ export async function POST(req: Request) {
128129
}
129130

130131
// 获取 inlet 时预扣的费用
131-
const inletCost = data.inlet_cost || 0;
132+
const inletCost = getModelInletCost(modelId);
133+
console.log("outlet时获取inletCost:", inletCost);
132134

133135
// 实际需要扣除的费用 = 总费用 - 预扣费用
134136
const actualCost = totalCost - inletCost;
137+
console.log("outlet时实际需要扣除的费用:", actualCost);
135138

136139
// 获取并更新用户余额
137140
const userResult = await query(
@@ -150,7 +153,7 @@ export async function POST(req: Request) {
150153
}
151154

152155
const newBalance = Number(userResult.rows[0].balance);
153-
156+
console.log("outlet时获取newBalance:", newBalance);
154157
if (newBalance > 999999.9999) {
155158
throw new Error("Balance exceeds maximum allowed value");
156159
}

docker-compose.yml

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
services:
22
app:
3-
image: docker.io/variantconst/openwebui-monitor:latest
3+
#image: docker.io/variantconst/openwebui-monitor:latest
4+
build: .
45
ports:
56
- "7878:3000"
7+
env_file:
8+
- .env
69
environment:
710
- POSTGRES_HOST=${POSTGRES_HOST:-db}
811
- POSTGRES_PORT=${POSTGRES_PORT:-5432}
912
- POSTGRES_USER=${POSTGRES_USER:-postgres}
1013
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-openwebui}
1114
- POSTGRES_DATABASE=${POSTGRES_DATABASE:-openwebui_monitor}
12-
- OPENWEBUI_DOMAIN=${OPENWEBUI_DOMAIN}
13-
- OPENWEBUI_API_KEY=${OPENWEBUI_API_KEY}
14-
- API_KEY=${API_KEY}
15-
- INIT_BALANCE=${INIT_BALANCE:-1}
16-
- ACCESS_TOKEN=${ACCESS_TOKEN}
1715
depends_on:
1816
db:
1917
condition: service_healthy

lib/utils/inlet-cost.ts

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ function parseInletCostConfig(config: string | undefined): ModelInletCost {
2929
}
3030

3131
export function getModelInletCost(modelId: string): number {
32+
if (!process.env.COST_ON_INLET) {
33+
return 0;
34+
}
3235
const costConfig = parseInletCostConfig(process.env.COST_ON_INLET);
3336
return costConfig[modelId] ?? costConfig["default"] ?? 0;
3437
}

middleware.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,30 @@ export async function middleware(request: NextRequest) {
1515
) {
1616
// API 请求验证
1717
if (!API_KEY) {
18-
console.error("未设置 API_KEY 环境变量");
19-
return NextResponse.json({ error: "服务器配置错误" }, { status: 500 });
18+
console.error("API Key is not set");
19+
return NextResponse.json(
20+
{ error: "Server configuration error" },
21+
{ status: 500 }
22+
);
2023
}
2124

2225
const authHeader = request.headers.get("authorization");
2326
const providedKey = authHeader?.replace("Bearer ", "");
2427

2528
if (!providedKey || providedKey !== API_KEY) {
26-
console.log("API密钥无效");
27-
return NextResponse.json({ error: "无效的API密钥" }, { status: 401 });
29+
console.log("Invalid API key");
30+
return NextResponse.json({ error: "Invalid API key" }, { status: 401 });
2831
}
2932

3033
return NextResponse.next();
3134
} else if (!pathname.startsWith("/api/")) {
3235
// 页面访问验证
3336
if (!ACCESS_TOKEN) {
34-
console.error("未设置 ACCESS_TOKEN 环境变量");
35-
return NextResponse.json({ error: "服务器配置错误" }, { status: 500 });
37+
console.error("ACCESS_TOKEN is not set");
38+
return NextResponse.json(
39+
{ error: "Server configuration error" },
40+
{ status: 500 }
41+
);
3642
}
3743

3844
// 如果是令牌验证页面,直接允许访问

resources/tutorials/en/deployment_guide.md

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ OpenWebUI Monitor is designed to work alongside [OpenWebUI](https://github.com/o
1818
- `API_KEY`: This is the key you'll use later in the OpenWebUI function plugin configuration as the `Api Key`. Use a strong password generator like [1Password](https://1password.com/) to create this. The length must be less than 56 characters.
1919
- `ACCESS_TOKEN`: A password required to access the OpenWebUI Monitor webpage.
2020
- `INIT_BALANCE` (optional): The initial balance for users, e.g., `1.14`.
21+
- `COST_ON_INLET` (optional): Pre-deduction amount when a chat starts. Can be configured as:
22+
- A fixed number for all models, e.g., `0.1`
23+
- Model-specific format, e.g., `gpt-4:0.32,gpt-3.5:0.01`
2124

2225
3. Navigate to the **Storage** section of the project and create or connect to a Neon Postgres database.
2326
<img width="1138" alt="image" src="https://github.com/user-attachments/assets/365e6dea-5d25-42ab-9421-766e2633f389">

resources/tutorials/zh-cn/README_zh.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ sudo docker compose up -d
4343

4444
### 可选
4545

46-
| 变量名 | 说明 | 默认值 |
47-
| --------------------------- | --------------------------------------------- | ------ |
48-
| DEFAULT_MODEL_INPUT_PRICE | 默认模型输入价格,单位为元/百万 tokens | `60` |
49-
| DEFAULT_MODEL_OUTPUT_PRICE | 默认模型输出价格,单位为元/百万 tokens | `60` |
50-
| DEFAULT_MODEL_PER_MSG_PRICE | 模型默认每条消息价格,设为负数将按 token 计费 | `-1` |
51-
| INIT_BALANCE | 用户初始余额 | `0` |
46+
| 变量名 | 说明 | 默认值 |
47+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------ |
48+
| DEFAULT_MODEL_INPUT_PRICE | 默认模型输入价格,单位为元/百万 tokens | `60` |
49+
| DEFAULT_MODEL_OUTPUT_PRICE | 默认模型输出价格,单位为元/百万 tokens | `60` |
50+
| DEFAULT_MODEL_PER_MSG_PRICE | 模型默认每条消息价格,设为负数将按 token 计费 | `-1` |
51+
| INIT_BALANCE | 用户初始余额 | `0` |
52+
| COST_ON_INLET | inlet 时的预扣费金额。可以是所有模型统一的固定数字(如 `0.1`),也可以是针对不同模型的配置(如 `gpt-4:0.32,gpt-3.5:0.01`| `0` |
5253

5354
<h2>Gallery</h2>
5455

5556
![](https://github.com/user-attachments/assets/2777c1fc-a8c6-4397-9665-a6a559d4bab1)
56-

resources/tutorials/zh-cn/deployment_guide_zh.md

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ OpenWebUI Monitor 是搭配 [OpenWebUI](https://github.com/open-webui/open-webui
1818
- `API_KEY`:这是你稍后要填写在 OpenWebUI 函数插件中 `Api Key` 的,用于向 OpenWebUI Monitor 服务器发送请求的鉴权。建议使用 [1Password](https://1password.com/) 生成一个少于 56 个字符的强密码。
1919
- `ACCESS_TOKEN`:访问 OpenWebUI Monitor 网页时要输入的访问密钥
2020
- `INIT_BALANCE`(可选):用户初始余额,例如 `1.14`
21+
- `COST_ON_INLET`(可选):开始对话时的预扣费金额。可以配置为:
22+
- 所有模型统一的固定数字,例如 `0.1`
23+
- 针对不同模型的配置,例如 `gpt-4:0.32,gpt-3.5:0.01`
2124

2225
3. 前往项目中的 Storage 选项,Create 或者 Connect 到一个 Neon Postgres 数据库<img width="1138" alt="image" src="https://github.com/user-attachments/assets/365e6dea-5d25-42ab-9421-766e2633f389">
2326

0 commit comments

Comments
 (0)