fix(ai): 统一模型传输与页面配置,公式列设计不再绕过组织设置

This commit is contained in:
Jayway Liu
2026-11-01 10:54:51 +08:00
parent 7be8854104
commit 31e59a426d
7 changed files with 460 additions and 39 deletions
+10 -32
View File
@@ -8,32 +8,18 @@ from django.db.models import Q
from django.http import FileResponse, JsonResponse
from django.utils import timezone
from .ai import extract_output_text, request_response, resolve, validate_messages
from .analysis import METRICS, context, dimensions
from .formula_columns import available_metrics, ensure_available_metrics, validate_column
from .models import Dataset, FormulaDefinition, FormulaExport
from .views import APIError, audit, body, dataset, endpoint, limit
def design_column(messages, ds, ctx):
if not (settings.AI_ENABLED and settings.OPENAI_API_KEY and settings.OPENAI_MODEL):
def design_column(messages, ds, ctx, cfg=None):
cfg = cfg or resolve(ds.organization)
if not cfg:
raise APIError("尚未配置外部 AI 服务", 503)
if not isinstance(messages, list) or not 1 <= len(messages) <= 12:
raise APIError("对话消息格式无效")
if any(
not isinstance(item, dict)
or set(item) != {"role", "content"}
or item["role"] not in ("user", "assistant")
or not isinstance(item["content"], str)
or len(item["content"]) > 1000
for item in messages
):
raise APIError("对话消息内容无效")
if (
messages[0]["role"] != "user"
or messages[-1]["role"] != "user"
or any(left["role"] == right["role"] for left, right in zip(messages, messages[1:]))
):
raise APIError("对话消息必须按用户描述、助手追问、用户补充的顺序提交")
messages = validate_messages(messages)
available = available_metrics(ds)
@@ -117,9 +103,9 @@ def design_column(messages, ds, ctx):
)
)
payload = {
"model": settings.OPENAI_MODEL,
"model": cfg["model"],
"store": False,
"max_output_tokens": 1400,
"max_output_tokens": 2000,
"input": [{"role": "system", "content": system}, *messages],
"text": {
"format": {
@@ -131,17 +117,9 @@ def design_column(messages, ds, ctx):
},
}
try:
with httpx.Client(timeout=30) as client:
response = client.post(
"https://api.openai.com/v1/responses",
headers={"Authorization": f"Bearer {settings.OPENAI_API_KEY}"},
json=payload,
)
response.raise_for_status()
result = response.json()
if not isinstance(result, dict) or result.get("status") != "completed":
raise ValueError("incomplete response")
text = next(c["text"] for o in result["output"] for c in o["content"] if c["type"] == "output_text")
text = extract_output_text(request_response(cfg, payload, timeout=30))
if text.startswith("```"):
text = text.removeprefix("```json").removeprefix("```").removesuffix("```").strip()
design = json.loads(text)
if (
set(design) != {"complete", "questions", "column"}