fix: 运营端改价同步compute服务models表,修复实际计费仍用旧价的问题
This commit is contained in:
@@ -15,6 +15,7 @@ import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import select, and_
|
||||
@@ -22,6 +23,7 @@ from sqlalchemy import select, and_
|
||||
from ..dependencies import get_db, get_current_user
|
||||
from ...rbac import write_audit
|
||||
from ...domain.rules import role_allowed
|
||||
from ...config import COMPUTE_BASE_URL, COMPUTE_ADMIN_TOKEN, COMPUTE_TIMEOUT
|
||||
from ...infrastructure.models import (
|
||||
ParkTenant, ParkCompany, CompanyMember, User,
|
||||
TenantDiscount, TenantUserDiscount,
|
||||
@@ -219,11 +221,66 @@ async def admin_update_standard_price(
|
||||
user: dict = Depends(get_current_user),
|
||||
):
|
||||
check_role(user, ["operator"])
|
||||
STANDARD_PRICES[model] = max(1, int(body.price_per_1k))
|
||||
new_price = max(1, int(body.price_per_1k))
|
||||
STANDARD_PRICES[model] = new_price
|
||||
|
||||
# 同步更新 compute 服务 models 表价格(实际计费以此为准)
|
||||
# 单位转换:分/1000token → 元/百万token = price * 10
|
||||
compute_price_yuan_per_m = round(new_price * 10, 4)
|
||||
synced = await _sync_compute_model_price(model, compute_price_yuan_per_m)
|
||||
|
||||
await write_audit(db, action="compute.standard_price_update", resource="standard_price",
|
||||
resource_id=model, detail=f"price={body.price_per_1k}",
|
||||
resource_id=model, detail=f"price={new_price}, compute_synced={synced}",
|
||||
user=user, request=request)
|
||||
return {"ok": True, "model": model, "price_per_1k": STANDARD_PRICES[model]}
|
||||
return {"ok": True, "model": model, "price_per_1k": STANDARD_PRICES[model],
|
||||
"compute_synced": synced}
|
||||
|
||||
|
||||
async def _sync_compute_model_price(model_name: str, price_yuan_per_m: float) -> bool:
|
||||
"""同步价格到 compute 服务 models 表(input_price = output_price = 统一价)。
|
||||
|
||||
返回是否同步成功;失败不影响 server-core 内存价格更新,仅记录日志。
|
||||
"""
|
||||
if not COMPUTE_BASE_URL or not COMPUTE_ADMIN_TOKEN:
|
||||
logger.warning("compute 服务地址或 token 未配置,跳过价格同步")
|
||||
return False
|
||||
headers = {"Authorization": f"Bearer {COMPUTE_ADMIN_TOKEN}",
|
||||
"Content-Type": "application/json"}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=COMPUTE_TIMEOUT) as client:
|
||||
# 1. 查模型列表,按 model_name 匹配 id
|
||||
resp = await client.get(f"{COMPUTE_BASE_URL}/admin/models",
|
||||
params={"page_size": 200}, headers=headers)
|
||||
if resp.status_code != 200:
|
||||
logger.warning(f"compute 模型列表查询失败: {resp.status_code}")
|
||||
return False
|
||||
data = resp.json()
|
||||
items = data.get("data", {}).get("items", data.get("data", []))
|
||||
if isinstance(items, dict):
|
||||
items = items.get("items", [])
|
||||
target = None
|
||||
for m in items:
|
||||
if m.get("model_name") == model_name or m.get("name") == model_name:
|
||||
target = m
|
||||
break
|
||||
if target is None:
|
||||
logger.info(f"compute 服务中未找到模型 {model_name},跳过同步")
|
||||
return False
|
||||
# 2. 更新价格
|
||||
mid = target.get("id")
|
||||
resp = await client.put(f"{COMPUTE_BASE_URL}/admin/models",
|
||||
json={"id": mid,
|
||||
"input_price": price_yuan_per_m,
|
||||
"output_price": price_yuan_per_m},
|
||||
headers=headers)
|
||||
if resp.status_code == 200:
|
||||
logger.info(f"compute 模型 {model_name}(id={mid}) 价格已同步为 {price_yuan_per_m} 元/百万token")
|
||||
return True
|
||||
logger.warning(f"compute 模型价格更新失败: {resp.status_code} {resp.text}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.warning(f"compute 价格同步异常: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user