mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-18 11:44:18 +00:00
支持阿里云百炼的通用模型和自定义大模型应用
This commit is contained in:
@@ -6,7 +6,7 @@ from . import entities, requester
|
|||||||
from ...core import app
|
from ...core import app
|
||||||
|
|
||||||
from . import token
|
from . import token
|
||||||
from .requesters import chatcmpl, anthropicmsgs, moonshotchatcmpl, deepseekchatcmpl, ollamachat, giteeaichatcmpl, xaichatcmpl, zhipuaichatcmpl, lmstudiochatcmpl, siliconflowchatcmpl
|
from .requesters import chatcmpl, anthropicmsgs, moonshotchatcmpl, deepseekchatcmpl, ollamachat, giteeaichatcmpl, xaichatcmpl, zhipuaichatcmpl, lmstudiochatcmpl, siliconflowchatcmpl, dashscopecmpl, qwenchatcmpl
|
||||||
|
|
||||||
FETCH_MODEL_LIST_URL = "https://api.qchatgpt.rockchin.top/api/v2/fetch/model_list"
|
FETCH_MODEL_LIST_URL = "https://api.qchatgpt.rockchin.top/api/v2/fetch/model_list"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import asyncio
|
||||||
|
import typing
|
||||||
|
import dashscope
|
||||||
|
|
||||||
|
from .. import entities, errors, requester
|
||||||
|
from ....core import entities as core_entities, app
|
||||||
|
from ... import entities as llm_entities
|
||||||
|
from ...tools import entities as tools_entities
|
||||||
|
|
||||||
|
#阿里云百炼平台的自定义应用支持资料引用,此函数可以将引用标签替换为参考资料
|
||||||
|
def replace_references(text, references_dict):
|
||||||
|
# 修正正则表达式,匹配 <ref>[index_id]</ref> 形式的字符串
|
||||||
|
pattern = re.compile(r'<ref>\[(.*?)\]</ref>')
|
||||||
|
|
||||||
|
def replacement(match):
|
||||||
|
ref_key = match.group(1) # 获取引用编号
|
||||||
|
if ref_key in references_dict:
|
||||||
|
return f"(参考资料来自:{references_dict[ref_key]})"
|
||||||
|
else:
|
||||||
|
return match.group(0) # 如果没有对应的参考资料,保留原样
|
||||||
|
|
||||||
|
# 使用 re.sub() 进行替换
|
||||||
|
return pattern.sub(replacement, text)
|
||||||
|
|
||||||
|
|
||||||
|
@requester.requester_class("dashscope-chat-applications")
|
||||||
|
class DashscopeChatApplication(requester.LLMAPIRequester):
|
||||||
|
"""Dashscope ChatApplications API 请求器"""
|
||||||
|
|
||||||
|
requester_cfg: dict
|
||||||
|
|
||||||
|
def __init__(self, ap: app.Application):
|
||||||
|
self.requester_cfg = ap.provider_cfg.data['requester']['dashscope-chat-applications']
|
||||||
|
self.ap = ap
|
||||||
|
|
||||||
|
async def initialize(self):
|
||||||
|
dashscope.api_key = self.ap.provider_cfg.data['keys']['dashscope'][0]
|
||||||
|
|
||||||
|
async def _req(self, args: dict):
|
||||||
|
|
||||||
|
#print("args:", args)
|
||||||
|
|
||||||
|
#局部变量
|
||||||
|
chunk = None
|
||||||
|
pending_content = ""
|
||||||
|
output = {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "",
|
||||||
|
"tool_calls": [],
|
||||||
|
"tool_call_id": None # Dashscope暂时不支持工具调用
|
||||||
|
} #由于Dashscope的content的键值是text,所以需要定义一个新格式的字典适配llm_entities.Message
|
||||||
|
|
||||||
|
references_dict = {} # 用于存储引用编号和对应的参考资料
|
||||||
|
|
||||||
|
#调用API
|
||||||
|
response = dashscope.Application.call(
|
||||||
|
api_key=dashscope.api_key,
|
||||||
|
app_id=args["model"],
|
||||||
|
prompt=args["messages"],
|
||||||
|
stream=True, # 设置流式输出
|
||||||
|
tools=args.get("tools", None),
|
||||||
|
incremental_output = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
#处理API返回的流式输出
|
||||||
|
for chunk in response:
|
||||||
|
#print(chunk)
|
||||||
|
if not chunk:
|
||||||
|
continue
|
||||||
|
|
||||||
|
#获取流式传输的output
|
||||||
|
stream_output = chunk.get("output", {})
|
||||||
|
if stream_output.get("text") is not None:
|
||||||
|
pending_content += stream_output.get("text")
|
||||||
|
|
||||||
|
|
||||||
|
#获取模型传出的参考资料列表
|
||||||
|
references_dict_list = stream_output.get("doc_references", [])
|
||||||
|
|
||||||
|
#从模型传出的参考资料信息中提取用于替换的字典
|
||||||
|
if references_dict_list is not None:
|
||||||
|
for doc in references_dict_list:
|
||||||
|
if doc.get("index_id") is not None:
|
||||||
|
references_dict[doc.get("index_id")] = doc.get("doc_name")
|
||||||
|
|
||||||
|
#将参考资料替换到文本中
|
||||||
|
pending_content = replace_references(pending_content, references_dict)
|
||||||
|
|
||||||
|
#将流式传输的内容整合到output中
|
||||||
|
output["content"] = pending_content
|
||||||
|
|
||||||
|
return output if chunk else None
|
||||||
|
|
||||||
|
async def _make_msg(
|
||||||
|
self,
|
||||||
|
chat_completion: dict,
|
||||||
|
) -> llm_entities.Message:
|
||||||
|
chatcmpl_message = chat_completion
|
||||||
|
|
||||||
|
# 确保 role 字段存在且不为 None
|
||||||
|
if 'role' not in chatcmpl_message or chatcmpl_message['role'] is None:
|
||||||
|
chatcmpl_message['role'] = 'assistant'
|
||||||
|
|
||||||
|
message = llm_entities.Message(**chatcmpl_message)
|
||||||
|
#print("message:", message)
|
||||||
|
return message
|
||||||
|
|
||||||
|
async def _closure(
|
||||||
|
self,
|
||||||
|
query: core_entities.Query,
|
||||||
|
req_messages: list[dict],
|
||||||
|
use_model: entities.LLMModelInfo,
|
||||||
|
use_funcs: list[tools_entities.LLMFunction] = None,
|
||||||
|
) -> llm_entities.Message:
|
||||||
|
|
||||||
|
args = self.requester_cfg['args'].copy()
|
||||||
|
args["model"] = use_model.name if use_model.model_name is None else use_model.model_name
|
||||||
|
|
||||||
|
# 设置此次请求中的messages
|
||||||
|
messages = req_messages.copy()
|
||||||
|
|
||||||
|
# 检查vision
|
||||||
|
for msg in messages:
|
||||||
|
if 'content' in msg and isinstance(msg["content"], list):
|
||||||
|
for me in msg["content"]:
|
||||||
|
if me["type"] == "image_base64":
|
||||||
|
me["image_url"] = {
|
||||||
|
"url": me["image_base64"]
|
||||||
|
}
|
||||||
|
me["type"] = "image_url"
|
||||||
|
del me["image_base64"]
|
||||||
|
|
||||||
|
args["messages"] = messages
|
||||||
|
|
||||||
|
# 发送请求
|
||||||
|
resp = await self._req(args)
|
||||||
|
|
||||||
|
# 处理请求结果
|
||||||
|
message = await self._make_msg(resp)
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
async def call(
|
||||||
|
self,
|
||||||
|
query: core_entities.Query,
|
||||||
|
model: entities.LLMModelInfo,
|
||||||
|
messages: typing.List[llm_entities.Message],
|
||||||
|
funcs: typing.List[tools_entities.LLMFunction] = None,
|
||||||
|
) -> llm_entities.Message:
|
||||||
|
req_messages = [] # req_messages 仅用于类内,外部同步由 query.messages 进行
|
||||||
|
for m in messages:
|
||||||
|
msg_dict = m.dict(exclude_none=True)
|
||||||
|
content = msg_dict.get("content")
|
||||||
|
if isinstance(content, list):
|
||||||
|
# 检查 content 列表中是否每个部分都是文本
|
||||||
|
if all(isinstance(part, dict) and part.get("type") == "text" for part in content):
|
||||||
|
# 将所有文本部分合并为一个字符串
|
||||||
|
msg_dict["content"] = "\n".join(part["text"] for part in content)
|
||||||
|
req_messages.append(msg_dict)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return await self._closure(query=query, req_messages=req_messages, use_model=model, use_funcs=funcs)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
raise errors.RequesterError('请求超时')
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import openai
|
||||||
|
|
||||||
|
from . import chatcmpl
|
||||||
|
from .. import requester
|
||||||
|
from ....core import app
|
||||||
|
|
||||||
|
|
||||||
|
@requester.requester_class("siliconflow-chat-completions")
|
||||||
|
class QwenChatCompletions(chatcmpl.OpenAIChatCompletions):
|
||||||
|
"""Qwen ChatCompletion API 请求器"""
|
||||||
|
|
||||||
|
client: openai.AsyncClient
|
||||||
|
|
||||||
|
requester_cfg: dict
|
||||||
|
|
||||||
|
def __init__(self, ap: app.Application):
|
||||||
|
self.ap = ap
|
||||||
|
|
||||||
|
self.requester_cfg = self.ap.provider_cfg.data['requester']['qwen-chat-completions']
|
||||||
@@ -211,6 +211,16 @@
|
|||||||
"requester": "zhipuai-chat-completions",
|
"requester": "zhipuai-chat-completions",
|
||||||
"token_mgr": "zhipuai",
|
"token_mgr": "zhipuai",
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "your-dashscope-app-id",
|
||||||
|
"requester": "dashscope-chat-applications",
|
||||||
|
"token_mgr": "dashscope",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "qwen-plus",
|
||||||
|
"requester": "qwen-chat-completions",
|
||||||
|
"token_mgr": "qwen",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,12 @@
|
|||||||
],
|
],
|
||||||
"siliconflow": [
|
"siliconflow": [
|
||||||
"xxxxxxx"
|
"xxxxxxx"
|
||||||
|
],
|
||||||
|
"dashscope": [
|
||||||
|
"sk-1234567890"
|
||||||
|
],
|
||||||
|
"qwen": [
|
||||||
|
"sk-1234567890",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"requester": {
|
"requester": {
|
||||||
@@ -40,6 +46,16 @@
|
|||||||
},
|
},
|
||||||
"timeout": 120
|
"timeout": 120
|
||||||
},
|
},
|
||||||
|
"dashscope-chat-applications": {
|
||||||
|
"args": {},
|
||||||
|
"base-url": "https://dashscope.aliyuncs.com/api/v1",
|
||||||
|
"timeout": 120
|
||||||
|
},
|
||||||
|
"qwen-chat-completions": {
|
||||||
|
"base-url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||||
|
"args": {},
|
||||||
|
"timeout": 120
|
||||||
|
},
|
||||||
"moonshot-chat-completions": {
|
"moonshot-chat-completions": {
|
||||||
"base-url": "https://api.moonshot.cn/v1",
|
"base-url": "https://api.moonshot.cn/v1",
|
||||||
"args": {},
|
"args": {},
|
||||||
|
|||||||
Reference in New Issue
Block a user