70 lines
3.0 KiB
Python
70 lines
3.0 KiB
Python
"""DeepSeek HTTP calls; callers retain their streaming/compression/followup deadlines."""
|
|
|
|
import json
|
|
import re
|
|
import requests
|
|
from requests.exceptions import RequestException, Timeout
|
|
|
|
from .config import get_setting
|
|
|
|
|
|
def post_completion(body, *, timeout, stream=False):
|
|
return requests.post(
|
|
get_setting('MODEL_URL'),
|
|
headers={'Authorization': f"Bearer {get_setting('DEEPSEEK_API_KEY')}",
|
|
'Content-Type': 'application/json'},
|
|
json=body, stream=stream, timeout=timeout,
|
|
)
|
|
|
|
|
|
|
|
EN_COMPRESS_RULE = '原文是英文,压缩后的结果必须仍然使用英文(English),不得翻译成中文。'
|
|
|
|
|
|
def has_chinese(t):
|
|
return any(('一' <= ch <= '龥' for ch in t))
|
|
|
|
|
|
def compress_answer(text, limit=get_setting('MAX_ANSWER_CHARS')):
|
|
"""回答超长时,让模型压缩到规定字数内;失败则原样返回"""
|
|
if len(text) <= limit:
|
|
return text
|
|
r = None
|
|
try:
|
|
body = {'model': get_setting('MODEL_NAME'), 'messages': [{'role': 'system', 'content': (EN_COMPRESS_RULE if has_chinese(text) is False else '') + f'你是文字精简助手。把用户给的内容压缩到 {limit} 字以内(必须严格满足,超出即为不合格),必须保留所有数字、金额、时效和渠道名称,删除重复表述、客套话和次要说明,结构保持不变。'}, {'role': 'user', 'content': text}], 'stream': False, 'max_tokens': 800}
|
|
r = post_completion(body, timeout=(5, 30))
|
|
if r.status_code == 200:
|
|
short = r.json()['choices'][0]['message']['content'].strip()
|
|
print(f'[压缩] {len(text)} 字 -> {len(short)} 字')
|
|
return short
|
|
print(f'[压缩失败] 状态码 {r.status_code}')
|
|
except Exception as e:
|
|
print(f'[压缩异常] {e}')
|
|
finally:
|
|
if r is not None:
|
|
r.close()
|
|
return text
|
|
|
|
|
|
def gen_followups(user_msg, answer_text):
|
|
"""根据本轮问答,生成 3 个客户可能接着问的问题(失败返回空列表,不影响主流程)"""
|
|
if not get_setting('DEEPSEEK_API_KEY'):
|
|
return []
|
|
r = None
|
|
try:
|
|
body = {'model': get_setting('MODEL_NAME'), 'messages': [{'role': 'system', 'content': '你是物流客服助手。根据用户问题和你的回答,生成3个客户最可能接着问的简短问题(每个不超过20字),只输出JSON字符串数组,不要任何解释。'}, {'role': 'user', 'content': f'用户问:{user_msg}\n你的回答:{answer_text[:500]}\n\n请生成3个追问:'}], 'stream': False, 'max_tokens': 200}
|
|
r = post_completion(body, timeout=(5, 15))
|
|
if r.status_code != 200:
|
|
return []
|
|
text = r.json()['choices'][0]['message']['content'].strip()
|
|
m = re.search('\\[.*\\]', text, re.S)
|
|
if m:
|
|
arr = json.loads(m.group(0))
|
|
return [str(x).strip() for x in arr if str(x).strip()][:3]
|
|
except Exception:
|
|
pass
|
|
finally:
|
|
if r is not None:
|
|
r.close()
|
|
return []
|