103 lines
3.2 KiB
Python
103 lines
3.2 KiB
Python
"""
|
||
GLM AI 服务
|
||
使用智谱 GLM-4.7-Flash 生成标题和标签
|
||
"""
|
||
|
||
import json
|
||
import re
|
||
import httpx
|
||
from loguru import logger
|
||
|
||
|
||
class GLMService:
|
||
"""GLM AI 服务"""
|
||
|
||
API_URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
|
||
API_KEY = "5915240ea48d4e93b454bc2412d1cc54.e054ej4pPqi9G6rc"
|
||
|
||
async def generate_title_tags(self, text: str) -> dict:
|
||
"""
|
||
根据口播文案生成标题和标签
|
||
|
||
Args:
|
||
text: 口播文案
|
||
|
||
Returns:
|
||
{"title": "标题", "tags": ["标签1", "标签2", ...]}
|
||
"""
|
||
prompt = f"""根据以下口播文案,生成一个吸引人的短视频标题和3个相关标签。
|
||
|
||
口播文案:
|
||
{text}
|
||
|
||
要求:
|
||
1. 标题要简洁有力,能吸引观众点击,不超过10个字
|
||
2. 标签要与内容相关,便于搜索和推荐,只要3个
|
||
|
||
请严格按以下JSON格式返回(不要包含其他内容):
|
||
{{"title": "标题", "tags": ["标签1", "标签2", "标签3"]}}"""
|
||
|
||
try:
|
||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||
response = await client.post(
|
||
self.API_URL,
|
||
headers={
|
||
"Content-Type": "application/json",
|
||
"Authorization": f"Bearer {self.API_KEY}"
|
||
},
|
||
json={
|
||
"model": "glm-4-flash",
|
||
"messages": [{"role": "user", "content": prompt}],
|
||
"max_tokens": 500,
|
||
"temperature": 0.7
|
||
}
|
||
)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
|
||
# 提取生成的内容
|
||
content = data["choices"][0]["message"]["content"]
|
||
logger.info(f"GLM response: {content}")
|
||
|
||
# 解析 JSON
|
||
result = self._parse_json_response(content)
|
||
return result
|
||
|
||
except httpx.HTTPError as e:
|
||
logger.error(f"GLM API request failed: {e}")
|
||
raise Exception(f"AI 服务请求失败: {str(e)}")
|
||
except Exception as e:
|
||
logger.error(f"GLM service error: {e}")
|
||
raise Exception(f"AI 生成失败: {str(e)}")
|
||
|
||
def _parse_json_response(self, content: str) -> dict:
|
||
"""解析 GLM 返回的 JSON 内容"""
|
||
# 尝试直接解析
|
||
try:
|
||
return json.loads(content)
|
||
except json.JSONDecodeError:
|
||
pass
|
||
|
||
# 尝试提取 JSON 块
|
||
json_match = re.search(r'\{[^{}]*"title"[^{}]*"tags"[^{}]*\}', content, re.DOTALL)
|
||
if json_match:
|
||
try:
|
||
return json.loads(json_match.group())
|
||
except json.JSONDecodeError:
|
||
pass
|
||
|
||
# 尝试提取 ```json 代码块
|
||
code_match = re.search(r'```(?:json)?\s*(\{.*?\})\s*```', content, re.DOTALL)
|
||
if code_match:
|
||
try:
|
||
return json.loads(code_match.group(1))
|
||
except json.JSONDecodeError:
|
||
pass
|
||
|
||
logger.error(f"Failed to parse GLM response: {content}")
|
||
raise Exception("AI 返回格式解析失败")
|
||
|
||
|
||
# 全局服务实例
|
||
glm_service = GLMService()
|