feat: 前后台静态资源路径冲突修复 + 用户管理功能
- 修改 admin/vite.config.js 添加 base: '/admin/' 解决静态资源路径问题 - 修复后台 index.html 资源引用从 /assets/ → /admin/assets/ - 更新优化器默认 API 地址为服务器地址 - 添加友链管理相关代码 - 修复多处分类管理页面
This commit is contained in:
+2
-2
@@ -25,8 +25,8 @@ def parse_args():
|
||||
parser.add_argument(
|
||||
"--api-url",
|
||||
type=str,
|
||||
default=os.getenv("API_URL", "http://localhost:8001"),
|
||||
help="API 地址(默认: http://localhost:8001)",
|
||||
default=os.getenv("API_URL", "http://39.104.58.51"),
|
||||
help="API 地址(默认: http://39.104.58.51)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--username",
|
||||
|
||||
+77
-33
@@ -120,30 +120,34 @@ class Optimizer:
|
||||
# === Stage 1: 质量检测 ===
|
||||
def quality_check(self, content: str) -> dict:
|
||||
"""判断笑话是否有笑点,返回 {"has_punchline": bool, "reason": str}"""
|
||||
resp = self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": QUALITY_CHECK_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": QUALITY_CHECK_USER_PROMPT.format(content=content[:2000])},
|
||||
],
|
||||
temperature=0.3,
|
||||
max_tokens=200,
|
||||
)
|
||||
def _call():
|
||||
return self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": QUALITY_CHECK_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": QUALITY_CHECK_USER_PROMPT.format(content=content[:2000])},
|
||||
],
|
||||
temperature=0.3,
|
||||
max_tokens=200,
|
||||
)
|
||||
resp = self._safe_api_call(_call)
|
||||
raw = resp.choices[0].message.content.strip()
|
||||
return self._parse_json(raw, {"has_punchline": True, "reason": ""})
|
||||
|
||||
# === Stage 2: AI 润色 ===
|
||||
def polish(self, content: str) -> str:
|
||||
"""润色笑话内容"""
|
||||
resp = self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": POLISH_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": POLISH_USER_PROMPT.format(content=content)},
|
||||
],
|
||||
temperature=0.8,
|
||||
max_tokens=1024,
|
||||
)
|
||||
def _call():
|
||||
return self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": POLISH_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": POLISH_USER_PROMPT.format(content=content)},
|
||||
],
|
||||
temperature=0.8,
|
||||
max_tokens=1024,
|
||||
)
|
||||
resp = self._safe_api_call(_call)
|
||||
return resp.choices[0].message.content.strip()
|
||||
|
||||
# === Stage 3: 评价分类 ===
|
||||
@@ -152,19 +156,21 @@ class Optimizer:
|
||||
type_names = [t.get("name", "") for t in self.types]
|
||||
crowd_names = [c.get("name", "") for c in self.crowds]
|
||||
|
||||
resp = self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": EVALUATE_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": EVALUATE_USER_PROMPT.format(
|
||||
content=content[:2000],
|
||||
known_types=", ".join(type_names),
|
||||
known_crowds=", ".join(crowd_names),
|
||||
)},
|
||||
],
|
||||
temperature=0.3,
|
||||
max_tokens=300,
|
||||
)
|
||||
def _call():
|
||||
return self.ai_client.chat.completions.create(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{"role": "system", "content": EVALUATE_SYSTEM_PROMPT},
|
||||
{"role": "user", "content": EVALUATE_USER_PROMPT.format(
|
||||
content=content[:2000],
|
||||
known_types=", ".join(type_names),
|
||||
known_crowds=", ".join(crowd_names),
|
||||
)},
|
||||
],
|
||||
temperature=0.3,
|
||||
max_tokens=300,
|
||||
)
|
||||
resp = self._safe_api_call(_call)
|
||||
raw = resp.choices[0].message.content.strip()
|
||||
result = self._parse_json(raw, {"types": [], "crowds": [], "score": 5, "comment": ""})
|
||||
# Backward compatibility: if LLM returns old single format, convert to array
|
||||
@@ -175,6 +181,27 @@ class Optimizer:
|
||||
return result
|
||||
|
||||
# === 辅助方法 ===
|
||||
def _safe_api_call(self, func, *args, max_retries: int = 3, **kwargs):
|
||||
"""带重试的 API 调用,自动处理限流"""
|
||||
import time as time_module
|
||||
last_error = None
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
last_error = e
|
||||
error_str = str(e)
|
||||
# 检查是否是限流错误
|
||||
if "429" in error_str or "rate" in error_str.lower():
|
||||
wait_time = (attempt + 1) * 30 # 30, 60, 90 秒
|
||||
print(f" [!] API 限流,等待 {wait_time} 秒后重试 ({attempt+1}/{max_retries})...")
|
||||
time_module.sleep(wait_time)
|
||||
else:
|
||||
# 其他错误,直接重试一次
|
||||
if attempt < max_retries - 1:
|
||||
time_module.sleep(5)
|
||||
raise last_error
|
||||
|
||||
def _parse_json(self, raw: str, default: dict) -> dict:
|
||||
"""安全解析 LLM 返回的 JSON"""
|
||||
try:
|
||||
@@ -266,12 +293,28 @@ class Optimizer:
|
||||
crowd_names = []
|
||||
score = None
|
||||
|
||||
# 根据评分计算 AI 等级
|
||||
ai_level = None
|
||||
if score is not None:
|
||||
if score >= 8:
|
||||
ai_level = "excellent"
|
||||
elif score >= 6:
|
||||
ai_level = "good"
|
||||
elif score >= 4:
|
||||
ai_level = "ordinary"
|
||||
else:
|
||||
ai_level = "poor"
|
||||
|
||||
# 保存更新
|
||||
try:
|
||||
update = {
|
||||
"polished_content": polished,
|
||||
"status": "approved" if (score or 5) >= 4 else "pending",
|
||||
}
|
||||
if score is not None:
|
||||
update["ai_score"] = float(score)
|
||||
if ai_level:
|
||||
update["ai_level"] = ai_level
|
||||
if type_names:
|
||||
update["type_ids"] = []
|
||||
for n in type_names:
|
||||
@@ -325,9 +368,10 @@ class Optimizer:
|
||||
print(f" [!] 处理异常: {e}")
|
||||
self.stats["skipped"] += 1
|
||||
|
||||
# 每条间稍等,避免 API 限流
|
||||
# 每条间稍等,避免 API 限流(每次请求间隔 2-3 秒)
|
||||
if idx < len(jokes) - 1:
|
||||
time.sleep(1)
|
||||
import time
|
||||
time.sleep(2)
|
||||
|
||||
# 输出统计
|
||||
print(f"\n{'='*40}")
|
||||
|
||||
Reference in New Issue
Block a user