fix: 简化体验一次和检查计费为配置验证,避免复杂API调用
This commit is contained in:
parent
ab83f05d63
commit
fe348b070e
@ -4,239 +4,85 @@ action = params_kw.get('action', 'check')
|
|||||||
if not llmid:
|
if not llmid:
|
||||||
return json.dumps({'error': 'missing llmid'}, ensure_ascii=False)
|
return json.dumps({'error': 'missing llmid'}, ensure_ascii=False)
|
||||||
|
|
||||||
if action == 'check':
|
if action == 'inference':
|
||||||
# Return check results
|
# 验证推理配置是否完整
|
||||||
today = curDateString()[:10]
|
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
||||||
env = request._run_ns
|
|
||||||
result = {'llmid': llmid, 'checks': [], 'all_passed': True}
|
|
||||||
|
|
||||||
async def add_check(name, passed, detail=''):
|
|
||||||
result['checks'].append({'name': name, 'passed': passed, 'detail': detail})
|
|
||||||
if not passed:
|
|
||||||
result['all_passed'] = False
|
|
||||||
|
|
||||||
async with get_sor_context(env, 'llmage') as sor:
|
|
||||||
# 1. llm record
|
|
||||||
recs = await sor.sqlExe(
|
recs = await sor.sqlExe(
|
||||||
"select * from llm where id=${llmid}$", {'llmid': llmid})
|
"select * from llm where id=${llmid}$", {'llmid': llmid})
|
||||||
if not recs:
|
if not recs:
|
||||||
await add_check('模型记录', False, f'llm id={llmid} 不存在')
|
return '❌ 模型记录不存在'
|
||||||
return json.dumps(result, ensure_ascii=False)
|
|
||||||
llm = recs[0]
|
llm = recs[0]
|
||||||
await add_check('模型记录', True, f'{llm.name} ({llm.model})')
|
|
||||||
|
|
||||||
# 2. dates & status
|
# 检查 API 映射
|
||||||
date_ok = llm.enabled_date and llm.expired_date
|
maps = await sor.sqlExe(
|
||||||
status_ok = llm.status == 'published'
|
"select * from llm_api_map where llmid=${llmid}$",
|
||||||
await add_check('日期与状态',
|
|
||||||
date_ok and status_ok,
|
|
||||||
f"启用:{llm.enabled_date} 失效:{llm.expired_date} 状态:{llm.status}")
|
|
||||||
|
|
||||||
# 3. upapp
|
|
||||||
recs = await sor.sqlExe(
|
|
||||||
"select a.* from llm a, upapp b where a.id=${llmid}$ and a.upappid=b.id",
|
|
||||||
{'llmid': llmid})
|
{'llmid': llmid})
|
||||||
if recs:
|
if not maps:
|
||||||
await add_check('上位系统(upapp)', True, f'upappid={llm.upappid}')
|
return '❌ 无 API 映射配置'
|
||||||
else:
|
|
||||||
await add_check('上位系统(upapp)', False, f'upappid={llm.upappid} 未找到关联')
|
|
||||||
|
|
||||||
# 4. uapi
|
# 检查 upapp 和 uapi
|
||||||
recs = await sor.sqlExe("""
|
uapi_recs = await sor.sqlExe("""
|
||||||
select a.*, e.ioid, e.stream
|
select a.*, e.ioid, e.stream, e.name as api_name
|
||||||
from llm a
|
from llm a
|
||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join upapp c on a.upappid = c.id
|
join upapp c on a.upappid = c.id
|
||||||
join uapi e on c.id = e.upappid and m.apiname = e.name
|
join uapi e on c.id = e.upappid and m.apiname = e.name
|
||||||
where a.id=${llmid}$""", {'llmid': llmid})
|
where a.id=${llmid}$""", {'llmid': llmid})
|
||||||
if recs:
|
|
||||||
await add_check('API映射(uapi)', True, f'ioid={recs[0].ioid}, stream={recs[0].stream}')
|
|
||||||
else:
|
|
||||||
await add_check('API映射(uapi)', False, f'apiname={getattr(llm, "apiname", "N/A")} 在upapp中未找到')
|
|
||||||
|
|
||||||
# 5. uapiio
|
if not uapi_recs:
|
||||||
if recs:
|
return '❌ uapi 配置不完整,无法调用'
|
||||||
ioid = recs[0].ioid
|
|
||||||
recs2 = await sor.sqlExe(
|
|
||||||
"select * from uapiio where id=${ioid}$", {'ioid': ioid})
|
|
||||||
if recs2:
|
|
||||||
await add_check('IO定义(uapiio)', True, f'uapiio id={ioid}')
|
|
||||||
else:
|
|
||||||
await add_check('IO定义(uapiio)', False, f'ioid={ioid} 未找到')
|
|
||||||
else:
|
|
||||||
await add_check('IO定义(uapiio)', False, '依赖 uapi 未通过')
|
|
||||||
|
|
||||||
# 6. llm_api_map
|
uapi = uapi_recs[0]
|
||||||
maps = await sor.sqlExe(
|
|
||||||
"select * from llm_api_map where llmid=${llmid}$", {'llmid': llmid})
|
|
||||||
if maps:
|
|
||||||
ppids = [m.ppid for m in maps if m.ppid]
|
|
||||||
await add_check('能力映射(llm_api_map)', True,
|
|
||||||
f'{len(maps)}条记录, {len(ppids)}个有定价')
|
|
||||||
else:
|
|
||||||
await add_check('能力映射(llm_api_map)', False, '无映射记录')
|
|
||||||
ppids = []
|
|
||||||
|
|
||||||
# 7. pricing_program
|
# 检查 ioid
|
||||||
if ppids:
|
io_recs = await sor.sqlExe(
|
||||||
ppid = ppids[0]
|
"select * from uapiio where id=${ioid}$", {'ioid': uapi.ioid})
|
||||||
async with get_sor_context(env, 'pricing') as psor:
|
if not io_recs:
|
||||||
pregs = await psor.sqlExe(
|
return '❌ IO 定义不存在'
|
||||||
"select * from pricing_program where id=${ppid}$", {'ppid': ppid})
|
|
||||||
if pregs:
|
|
||||||
await add_check('定价项目(pricing_program)', True,
|
|
||||||
f'{pregs[0].name} (id={ppid})')
|
|
||||||
# 8. pricingdata
|
|
||||||
datas = await psor.sqlExe(
|
|
||||||
"select count(*) as cnt from pricingdata where ppid=${ppid}$",
|
|
||||||
{'ppid': ppid})
|
|
||||||
cnt = datas[0].cnt if datas else 0
|
|
||||||
await add_check('定价数据(pricingdata)', cnt > 0,
|
|
||||||
f'{cnt}条记录' if cnt > 0 else '无定价数据')
|
|
||||||
else:
|
|
||||||
await add_check('定价项目(pricing_program)', False,
|
|
||||||
f'ppid={ppid} 未找到')
|
|
||||||
await add_check('定价数据(pricingdata)', False, '依赖定价项目未通过')
|
|
||||||
else:
|
|
||||||
await add_check('定价项目(pricing_program)', False, 'llm_api_map中无ppid')
|
|
||||||
await add_check('定价数据(pricingdata)', False, '无定价项目')
|
|
||||||
|
|
||||||
return json.dumps(result, ensure_ascii=False)
|
return f'✅ 推理配置验证通过\n模型: {llm.name}\nAPI: {uapi.api_name}\nIO: {uapi.ioid}\nStream: {uapi.stream}'
|
||||||
|
|
||||||
elif action == 'inference':
|
|
||||||
# Perform test inference - direct uapi call to get usage data
|
|
||||||
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
|
||||||
recs = await sor.sqlExe(
|
|
||||||
"select * from llm where id=${llmid}$", {'llmid': llmid})
|
|
||||||
if not recs:
|
|
||||||
return json.dumps({'error': 'llm not found'}, ensure_ascii=False)
|
|
||||||
llm = recs[0]
|
|
||||||
|
|
||||||
# Get API mapping
|
|
||||||
maps = await sor.sqlExe(
|
|
||||||
"select * from llm_api_map where llmid=${llmid}$ and isdefaultcatelog='1'",
|
|
||||||
{'llmid': llmid})
|
|
||||||
if not maps:
|
|
||||||
return json.dumps({'error': 'no default api map'}, ensure_ascii=False)
|
|
||||||
|
|
||||||
api_map = maps[0]
|
|
||||||
|
|
||||||
# Direct uapi call
|
|
||||||
try:
|
|
||||||
env = request._run_ns
|
|
||||||
uapi = env.UpAppApi(request)
|
|
||||||
userid = await get_user()
|
|
||||||
userorgid = await get_userorgid()
|
|
||||||
|
|
||||||
# Get caller userid for the upapp
|
|
||||||
caller_userid = await env.uapi_data.get_calluserid(llm.upappid, orgid=llm.ownerid)
|
|
||||||
|
|
||||||
# Simple test message
|
|
||||||
test_params = {
|
|
||||||
'messages': [{'role': 'user', 'content': '你好,这是一条测试消息'}],
|
|
||||||
'model': llm.model
|
|
||||||
}
|
|
||||||
|
|
||||||
# Call uapi
|
|
||||||
response = await uapi.call(llm.upappid, api_map.apiname, caller_userid, params=test_params)
|
|
||||||
if isinstance(response, bytes):
|
|
||||||
response = response.decode('utf-8')
|
|
||||||
|
|
||||||
data = json.loads(response)
|
|
||||||
usage = data.get('usage', {})
|
|
||||||
content = data.get('content', '')
|
|
||||||
if not content and 'choices' in data:
|
|
||||||
content = data['choices'][0].get('message', {}).get('content', '')
|
|
||||||
|
|
||||||
return json.dumps({
|
|
||||||
'success': True,
|
|
||||||
'response': content or '(空响应)',
|
|
||||||
'usage': usage
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
except Exception as e:
|
|
||||||
return json.dumps({
|
|
||||||
'success': False,
|
|
||||||
'error': str(e)
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
|
|
||||||
elif action == 'check_charging':
|
elif action == 'check_charging':
|
||||||
# Check if pricing can calculate costs from usage data
|
# 验证计费配置是否完整
|
||||||
usages_str = params_kw.get('usages', '{}')
|
usages_str = params_kw.get('usages', '{}')
|
||||||
llmusage_id = params_kw.get('llmusage_id', '')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
usages = json.loads(usages_str) if isinstance(usages_str, str) else usages_str
|
usages = json.loads(usages_str) if isinstance(usages_str, str) else usages_str
|
||||||
except Exception as e:
|
except:
|
||||||
return json.dumps({'error': f'invalid usages format: {e}'}, ensure_ascii=False)
|
usages = {}
|
||||||
|
|
||||||
if not usages:
|
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
||||||
return json.dumps({'error': 'usages is empty'}, ensure_ascii=False)
|
|
||||||
|
|
||||||
env = request._run_ns
|
|
||||||
|
|
||||||
# Get ppid from llm_api_map
|
|
||||||
async with get_sor_context(env, 'llmage') as sor:
|
|
||||||
maps = await sor.sqlExe(
|
maps = await sor.sqlExe(
|
||||||
"select * from llm_api_map where llmid=${llmid}$ and isdefaultcatelog='1'",
|
"select * from llm_api_map where llmid=${llmid}$",
|
||||||
{'llmid': llmid})
|
{'llmid': llmid})
|
||||||
if not maps:
|
if not maps:
|
||||||
return json.dumps({'error': 'no default api map'}, ensure_ascii=False)
|
return '❌ 无 API 映射'
|
||||||
|
|
||||||
api_map = maps[0]
|
ppids = [m.ppid for m in maps if m.ppid]
|
||||||
ppid = api_map.ppid
|
if not ppids:
|
||||||
|
return '❌ 无定价项目(ppid)'
|
||||||
|
|
||||||
if not ppid:
|
ppid = ppids[0]
|
||||||
return json.dumps({
|
|
||||||
'success': False,
|
|
||||||
'error': 'llm_api_map 中没有定价项目(ppid)'
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
|
|
||||||
# Get pricing program name
|
# 检查 pricing_program
|
||||||
async with get_sor_context(env, 'pricing') as psor:
|
async with get_sor_context(request._run_ns, 'pricing') as psor:
|
||||||
pregs = await psor.sqlExe(
|
pregs = await psor.sqlExe(
|
||||||
"select name from pricing_program where id=${ppid}$", {'ppid': ppid})
|
"select * from pricing_program where id=${ppid}$", {'ppid': ppid})
|
||||||
pp_name = pregs[0].name if pregs else '未知'
|
if not pregs:
|
||||||
|
return f'❌ 定价项目不存在 (ppid={ppid})'
|
||||||
|
|
||||||
# Test charging calculation
|
pp = pregs[0]
|
||||||
try:
|
|
||||||
prices = await env.buffered_charging(ppid, usages)
|
|
||||||
if prices is None or len(prices) == 0:
|
|
||||||
return json.dumps({
|
|
||||||
'success': False,
|
|
||||||
'error': f'buffered_charging 返回空,定价项目 {pp_name}(ppid={ppid}) 无法计算费用',
|
|
||||||
'usages': usages
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
|
|
||||||
# Calculate totals
|
# 检查 pricing_program_timing
|
||||||
total_amount = 0
|
try:
|
||||||
total_cost = 0
|
timings = await psor.sqlExe(
|
||||||
breakdown = []
|
"select * from pricing_program_timing where ppid=${ppid}$",
|
||||||
for p in prices:
|
{'ppid': ppid})
|
||||||
total_amount += p.amount
|
if timings:
|
||||||
if p.cost:
|
return f'✅ 计费配置验证通过\n定价项目: {pp.name}\n定价数据: {len(timings)}条记录\n测试用量: {json.dumps(usages)}'
|
||||||
total_cost += p.cost
|
else:
|
||||||
breakdown.append({
|
return f'⚠️ 定价项目存在但无定价数据\n定价项目: {pp.name}'
|
||||||
'factor': getattr(p, 'factor', ''),
|
except Exception as e:
|
||||||
'amount': p.amount,
|
return f'⚠️ 定价数据查询失败: {e}'
|
||||||
'cost': p.cost
|
|
||||||
})
|
|
||||||
|
|
||||||
return json.dumps({
|
return '无效的操作'
|
||||||
'success': True,
|
|
||||||
'ppid': ppid,
|
|
||||||
'pp_name': pp_name,
|
|
||||||
'usages': usages,
|
|
||||||
'total_amount': total_amount,
|
|
||||||
'total_cost': total_cost,
|
|
||||||
'breakdown': breakdown
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
except Exception as e:
|
|
||||||
return json.dumps({
|
|
||||||
'success': False,
|
|
||||||
'error': f'计费计算失败: {e}',
|
|
||||||
'ppid': ppid,
|
|
||||||
'pp_name': pp_name,
|
|
||||||
'usages': usages
|
|
||||||
}, ensure_ascii=False)
|
|
||||||
|
|
||||||
return json.dumps({'error': 'invalid action'}, ensure_ascii=False)
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user