update:AliAppLLM流式接口改造

This commit is contained in:
3030332422
2025-08-28 16:32:00 +08:00
parent a79d8d61e3
commit f6f240bc4b
@@ -1,8 +1,10 @@
from config.logger import setup_logging from config.logger import setup_logging
from http import HTTPStatus from http import HTTPStatus
import dashscope
from dashscope import Application from dashscope import Application
from core.providers.llm.base import LLMProviderBase from core.providers.llm.base import LLMProviderBase
from core.utils.util import check_model_key from core.utils.util import check_model_key
import time
TAG = __name__ TAG = __name__
logger = setup_logging() logger = setup_logging()
@@ -15,6 +17,7 @@ class LLMProvider(LLMProviderBase):
self.base_url = config.get("base_url") self.base_url = config.get("base_url")
self.is_No_prompt = config.get("is_no_prompt") self.is_No_prompt = config.get("is_no_prompt")
self.memory_id = config.get("ali_memory_id") self.memory_id = config.get("ali_memory_id")
self.streaming_chunk_size = config.get("streaming_chunk_size", 3) # 每次流式返回的字符数
check_model_key("AliBLLLM", self.api_key) check_model_key("AliBLLLM", self.api_key)
def response(self, session_id, dialogue): def response(self, session_id, dialogue):
@@ -32,6 +35,8 @@ class LLMProvider(LLMProviderBase):
"app_id": self.app_id, "app_id": self.app_id,
"session_id": session_id, "session_id": session_id,
"messages": dialogue, "messages": dialogue,
# 开启SDK原生流式
"stream": True,
} }
if self.memory_id != False: if self.memory_id != False:
# 百练memory需要prompt参数 # 百练memory需要prompt参数
@@ -42,25 +47,63 @@ class LLMProvider(LLMProviderBase):
f"【阿里百练API服务】处理后的prompt: {prompt}" f"【阿里百练API服务】处理后的prompt: {prompt}"
) )
# 可选地设置自定义API基地址(若配置为兼容模式URL则忽略)
if self.base_url and ("/api/" in self.base_url):
dashscope.base_http_api_url = self.base_url
responses = Application.call(**call_params) responses = Application.call(**call_params)
if responses.status_code != HTTPStatus.OK:
logger.bind(tag=TAG).error( # 流式处理(SDK在stream=True时返回可迭代对象;否则返回单次响应对象)
f"code={responses.status_code}, " logger.bind(tag=TAG).debug(
f"message={responses.message}, " f"【阿里百练API服务】构造参数: {dict(call_params, api_key='***')}"
f"请参考文档:https://help.aliyun.com/zh/model-studio/developer-reference/error-code" )
)
yield "【阿里百练API服务响应异常】" last_text = ""
else: try:
logger.bind(tag=TAG).debug( for resp in responses:
f"【阿里百练API服务】构造参数: {call_params}" if resp.status_code != HTTPStatus.OK:
) logger.bind(tag=TAG).error(
yield responses.output.text f"code={resp.status_code}, message={resp.message}, 请参考文档:https://help.aliyun.com/zh/model-studio/developer-reference/error-code"
)
continue
current_text = getattr(getattr(resp, "output", None), "text", None)
if current_text is None:
continue
# SDK流式为增量覆盖,计算差量输出
if len(current_text) >= len(last_text):
delta = current_text[len(last_text):]
else:
# 避免偶发回退
delta = current_text
if delta:
yield delta
last_text = current_text
except TypeError:
# 非流式回落(一次性返回)
if responses.status_code != HTTPStatus.OK:
logger.bind(tag=TAG).error(
f"code={responses.status_code}, message={responses.message}, 请参考文档:https://help.aliyun.com/zh/model-studio/developer-reference/error-code"
)
yield "【阿里百练API服务响应异常】"
else:
full_text = getattr(getattr(responses, "output", None), "text", "")
logger.bind(tag=TAG).info(
f"【阿里百练API服务】完整响应长度: {len(full_text)}"
)
for i in range(0, len(full_text), self.streaming_chunk_size):
chunk = full_text[i:i + self.streaming_chunk_size]
if chunk:
yield chunk
except Exception as e: except Exception as e:
logger.bind(tag=TAG).error(f"【阿里百练API服务】响应异常: {e}") logger.bind(tag=TAG).error(f"【阿里百练API服务】响应异常: {e}")
yield "【LLM服务响应异常】" yield "【LLM服务响应异常】"
def response_with_functions(self, session_id, dialogue, functions=None): def response_with_functions(self, session_id, dialogue, functions=None):
logger.bind(tag=TAG).error( # 阿里百练当前未支持原生的 function call。为保持兼容,这里回退到普通文本流式输出。
f"阿里百练暂未实现完整的工具调用(function call),建议使用其他意图识别" # 上层会按 (content, tool_calls) 的形式消费,这里始终返回 (token, None)
logger.bind(tag=TAG).warning(
"阿里百练未实现原生 function call,已回退为纯文本流式输出"
) )
for token in self.response(session_id, dialogue):
yield token, None