mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-20 11:26:07 +00:00
feat: 删除oss相关代码
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from .. import migration
|
|
||||||
|
|
||||||
|
|
||||||
@migration.migration_class("vision-and-oss-config", 6)
|
|
||||||
class VisionAndOSSConfigMigration(migration.Migration):
|
|
||||||
"""迁移"""
|
|
||||||
|
|
||||||
async def need_migrate(self) -> bool:
|
|
||||||
"""判断当前环境是否需要运行此迁移"""
|
|
||||||
return "enable-vision" not in self.ap.provider_cfg.data \
|
|
||||||
or "oss" not in self.ap.system_cfg.data
|
|
||||||
|
|
||||||
async def run(self):
|
|
||||||
"""执行迁移"""
|
|
||||||
if "enable-vision" not in self.ap.provider_cfg.data:
|
|
||||||
self.ap.provider_cfg.data["enable-vision"] = False
|
|
||||||
|
|
||||||
if "oss" not in self.ap.system_cfg.data:
|
|
||||||
self.ap.system_cfg.data["oss"] = [
|
|
||||||
{
|
|
||||||
"type": "aliyun",
|
|
||||||
"endpoint": "https://oss-cn-hangzhou.aliyuncs.com",
|
|
||||||
"public-read-base-url": "https://qchatgpt.oss-cn-hangzhou.aliyuncs.com",
|
|
||||||
"access-key-id": "LTAI5tJ5Q5J8J6J5J5J5J5J5",
|
|
||||||
"access-key-secret": "xxxxxx",
|
|
||||||
"bucket": "qchatgpt",
|
|
||||||
"prefix": "qchatgpt",
|
|
||||||
"enable": False,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
await self.ap.provider_cfg.dump_config()
|
|
||||||
await self.ap.system_cfg.dump_config()
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .. import migration
|
||||||
|
|
||||||
|
|
||||||
|
@migration.migration_class("vision-config", 6)
|
||||||
|
class VisionConfigMigration(migration.Migration):
|
||||||
|
"""迁移"""
|
||||||
|
|
||||||
|
async def need_migrate(self) -> bool:
|
||||||
|
"""判断当前环境是否需要运行此迁移"""
|
||||||
|
return "enable-vision" not in self.ap.provider_cfg.data
|
||||||
|
|
||||||
|
async def run(self):
|
||||||
|
"""执行迁移"""
|
||||||
|
if "enable-vision" not in self.ap.provider_cfg.data:
|
||||||
|
self.ap.provider_cfg.data["enable-vision"] = False
|
||||||
|
|
||||||
|
await self.ap.provider_cfg.dump_config()
|
||||||
@@ -15,7 +15,6 @@ from ..command import cmdmgr
|
|||||||
from ..plugin import manager as plugin_mgr
|
from ..plugin import manager as plugin_mgr
|
||||||
from ..pipeline import pool
|
from ..pipeline import pool
|
||||||
from ..pipeline import controller, stagemgr
|
from ..pipeline import controller, stagemgr
|
||||||
from ..oss import oss
|
|
||||||
from ..utils import version as version_mgr, proxy as proxy_mgr
|
from ..utils import version as version_mgr, proxy as proxy_mgr
|
||||||
|
|
||||||
|
|
||||||
@@ -72,8 +71,6 @@ class Application:
|
|||||||
|
|
||||||
proxy_mgr: proxy_mgr.ProxyManager = None
|
proxy_mgr: proxy_mgr.ProxyManager = None
|
||||||
|
|
||||||
oss_mgr: oss.OSSServiceManager = None
|
|
||||||
|
|
||||||
logger: logging.Logger = None
|
logger: logging.Logger = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ required_deps = {
|
|||||||
"yaml": "pyyaml",
|
"yaml": "pyyaml",
|
||||||
"aiohttp": "aiohttp",
|
"aiohttp": "aiohttp",
|
||||||
"psutil": "psutil",
|
"psutil": "psutil",
|
||||||
"oss2": "oss2",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ from ...provider.modelmgr import modelmgr as llm_model_mgr
|
|||||||
from ...provider.sysprompt import sysprompt as llm_prompt_mgr
|
from ...provider.sysprompt import sysprompt as llm_prompt_mgr
|
||||||
from ...provider.tools import toolmgr as llm_tool_mgr
|
from ...provider.tools import toolmgr as llm_tool_mgr
|
||||||
from ...platform import manager as im_mgr
|
from ...platform import manager as im_mgr
|
||||||
from ...oss import oss as oss_mgr
|
|
||||||
|
|
||||||
|
|
||||||
@stage.stage_class("BuildAppStage")
|
@stage.stage_class("BuildAppStage")
|
||||||
class BuildAppStage(stage.BootingStage):
|
class BuildAppStage(stage.BootingStage):
|
||||||
@@ -69,10 +67,6 @@ class BuildAppStage(stage.BootingStage):
|
|||||||
await cmd_mgr_inst.initialize()
|
await cmd_mgr_inst.initialize()
|
||||||
ap.cmd_mgr = cmd_mgr_inst
|
ap.cmd_mgr = cmd_mgr_inst
|
||||||
|
|
||||||
oss_mgr_inst = oss_mgr.OSSServiceManager(ap)
|
|
||||||
await oss_mgr_inst.initialize()
|
|
||||||
ap.oss_mgr = oss_mgr_inst
|
|
||||||
|
|
||||||
llm_model_mgr_inst = llm_model_mgr.ModelManager(ap)
|
llm_model_mgr_inst = llm_model_mgr.ModelManager(ap)
|
||||||
await llm_model_mgr_inst.initialize()
|
await llm_model_mgr_inst.initialize()
|
||||||
ap.model_mgr = llm_model_mgr_inst
|
ap.model_mgr = llm_model_mgr_inst
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import importlib
|
|||||||
|
|
||||||
from .. import stage, app
|
from .. import stage, app
|
||||||
from ...config import migration
|
from ...config import migration
|
||||||
from ...config.migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
|
from ...config.migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion, m006_vision_config
|
||||||
from ...config.migrations import m005_deepseek_cfg_completion, m006_vision_and_oss_config
|
from ...config.migrations import m005_deepseek_cfg_completion
|
||||||
|
|
||||||
|
|
||||||
@stage.stage_class("MigrationStage")
|
@stage.stage_class("MigrationStage")
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import aiohttp
|
|
||||||
import typing
|
|
||||||
from urllib.parse import urlparse, parse_qs
|
|
||||||
import ssl
|
|
||||||
|
|
||||||
from . import service as osssv
|
|
||||||
from ..core import app
|
|
||||||
from .services import aliyun
|
|
||||||
|
|
||||||
|
|
||||||
class OSSServiceManager:
|
|
||||||
|
|
||||||
ap: app.Application
|
|
||||||
|
|
||||||
service: osssv.OSSService = None
|
|
||||||
|
|
||||||
def __init__(self, ap: app.Application):
|
|
||||||
self.ap = ap
|
|
||||||
|
|
||||||
async def initialize(self):
|
|
||||||
"""初始化
|
|
||||||
"""
|
|
||||||
|
|
||||||
mapping = {}
|
|
||||||
|
|
||||||
for svcls in osssv.preregistered_services:
|
|
||||||
mapping[svcls.name] = svcls
|
|
||||||
|
|
||||||
for sv in self.ap.system_cfg.data['oss']:
|
|
||||||
if sv['enable']:
|
|
||||||
|
|
||||||
if sv['type'] not in mapping:
|
|
||||||
raise Exception(f"未知的OSS服务类型: {sv['type']}")
|
|
||||||
|
|
||||||
self.service = mapping[sv['type']](self.ap, sv)
|
|
||||||
await self.service.initialize()
|
|
||||||
break
|
|
||||||
|
|
||||||
def available(self) -> bool:
|
|
||||||
"""是否可用
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否可用
|
|
||||||
"""
|
|
||||||
return self.service is not None
|
|
||||||
|
|
||||||
async def fetch_image(self, image_url: str) -> bytes:
|
|
||||||
parsed = urlparse(image_url)
|
|
||||||
query = parse_qs(parsed.query)
|
|
||||||
|
|
||||||
# Flatten the query dictionary
|
|
||||||
query = {k: v[0] for k, v in query.items()}
|
|
||||||
|
|
||||||
ssl_context = ssl.create_default_context()
|
|
||||||
ssl_context.check_hostname = False
|
|
||||||
ssl_context.verify_mode = ssl.CERT_NONE
|
|
||||||
|
|
||||||
async with aiohttp.ClientSession(trust_env=False) as session:
|
|
||||||
async with session.get(
|
|
||||||
f"http://{parsed.netloc}{parsed.path}",
|
|
||||||
params=query,
|
|
||||||
ssl=ssl_context
|
|
||||||
) as resp:
|
|
||||||
resp.raise_for_status() # 检查HTTP错误
|
|
||||||
file_bytes = await resp.read()
|
|
||||||
return file_bytes
|
|
||||||
|
|
||||||
async def upload_url_image(
|
|
||||||
self,
|
|
||||||
image_url: str,
|
|
||||||
) -> str:
|
|
||||||
"""上传URL图片
|
|
||||||
|
|
||||||
Args:
|
|
||||||
image_url (str): 图片URL
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: 文件URL
|
|
||||||
"""
|
|
||||||
|
|
||||||
file_bytes = await self.fetch_image(image_url)
|
|
||||||
|
|
||||||
return await self.service.upload(file_bytes=file_bytes, ext=".jpg")
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import typing
|
|
||||||
import abc
|
|
||||||
|
|
||||||
from ..core import app
|
|
||||||
|
|
||||||
|
|
||||||
preregistered_services: list[typing.Type[OSSService]] = []
|
|
||||||
|
|
||||||
def service_class(
|
|
||||||
name: str
|
|
||||||
) -> typing.Callable[[typing.Type[OSSService]], typing.Type[OSSService]]:
|
|
||||||
"""OSS服务类装饰器
|
|
||||||
|
|
||||||
Args:
|
|
||||||
name (str): 服务名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
typing.Callable[[typing.Type[OSSService]], typing.Type[OSSService]]: 装饰器
|
|
||||||
"""
|
|
||||||
def decorator(cls: typing.Type[OSSService]) -> typing.Type[OSSService]:
|
|
||||||
assert issubclass(cls, OSSService)
|
|
||||||
|
|
||||||
cls.name = name
|
|
||||||
|
|
||||||
preregistered_services.append(cls)
|
|
||||||
|
|
||||||
return cls
|
|
||||||
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
|
|
||||||
class OSSService(metaclass=abc.ABCMeta):
|
|
||||||
"""OSS抽象类"""
|
|
||||||
|
|
||||||
name: str
|
|
||||||
|
|
||||||
ap: app.Application
|
|
||||||
|
|
||||||
cfg: dict
|
|
||||||
|
|
||||||
def __init__(self, ap: app.Application, cfg: dict) -> None:
|
|
||||||
self.ap = ap
|
|
||||||
self.cfg = cfg
|
|
||||||
|
|
||||||
async def initialize(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
async def upload(
|
|
||||||
self,
|
|
||||||
local_file: str=None,
|
|
||||||
file_bytes: bytes=None,
|
|
||||||
ext: str=None,
|
|
||||||
) -> str:
|
|
||||||
"""上传文件
|
|
||||||
|
|
||||||
Args:
|
|
||||||
local_file (str, optional): 本地文件路径. Defaults to None.
|
|
||||||
file_bytes (bytes, optional): 文件字节. Defaults to None.
|
|
||||||
ext (str, optional): 文件扩展名. Defaults to None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: 文件URL
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
import oss2
|
|
||||||
|
|
||||||
from .. import service as osssv
|
|
||||||
|
|
||||||
|
|
||||||
@osssv.service_class('aliyun')
|
|
||||||
class AliyunOSSService(osssv.OSSService):
|
|
||||||
"""阿里云OSS服务"""
|
|
||||||
|
|
||||||
auth: oss2.Auth
|
|
||||||
|
|
||||||
bucket: oss2.Bucket
|
|
||||||
|
|
||||||
async def initialize(self):
|
|
||||||
self.auth = oss2.Auth(
|
|
||||||
self.cfg['access-key-id'],
|
|
||||||
self.cfg['access-key-secret']
|
|
||||||
)
|
|
||||||
|
|
||||||
self.bucket = oss2.Bucket(
|
|
||||||
self.auth,
|
|
||||||
self.cfg['endpoint'],
|
|
||||||
self.cfg['bucket']
|
|
||||||
)
|
|
||||||
|
|
||||||
async def upload(
|
|
||||||
self,
|
|
||||||
local_file: str=None,
|
|
||||||
file_bytes: bytes=None,
|
|
||||||
ext: str=None,
|
|
||||||
) -> str:
|
|
||||||
if local_file is not None:
|
|
||||||
with open(local_file, 'rb') as f:
|
|
||||||
file_bytes = f.read()
|
|
||||||
|
|
||||||
if file_bytes is None:
|
|
||||||
raise Exception("缺少文件内容")
|
|
||||||
|
|
||||||
name = str(uuid.uuid1())
|
|
||||||
|
|
||||||
key = f"{self.cfg['prefix']}/{name}{ext}"
|
|
||||||
self.bucket.put_object(key, file_bytes)
|
|
||||||
|
|
||||||
return f"{self.cfg['public-read-base-url']}/{key}"
|
|
||||||
@@ -26,18 +26,9 @@ class OpenAIChatCompletions(api.LLMAPIRequester):
|
|||||||
|
|
||||||
requester_cfg: dict
|
requester_cfg: dict
|
||||||
|
|
||||||
cached_image_oss_url: dict[str, str] = {}
|
|
||||||
"""缓存的OSS服务的图片URL
|
|
||||||
|
|
||||||
key: 前文message中的原图片URL(QQ图片)
|
|
||||||
value: OSS服务的图片URL
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, ap: app.Application):
|
def __init__(self, ap: app.Application):
|
||||||
self.ap = ap
|
self.ap = ap
|
||||||
|
|
||||||
self.cached_image_oss_url = {}
|
|
||||||
|
|
||||||
self.requester_cfg = self.ap.provider_cfg.data['requester']['openai-chat-completions']
|
self.requester_cfg = self.ap.provider_cfg.data['requester']['openai-chat-completions']
|
||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
@@ -89,13 +80,11 @@ class OpenAIChatCompletions(api.LLMAPIRequester):
|
|||||||
messages = req_messages.copy()
|
messages = req_messages.copy()
|
||||||
|
|
||||||
# 检查vision
|
# 检查vision
|
||||||
if self.ap.oss_mgr.available():
|
for msg in messages:
|
||||||
for msg in messages:
|
if 'content' in msg and isinstance(msg["content"], list):
|
||||||
if 'content' in msg and isinstance(msg["content"], list):
|
for me in msg["content"]:
|
||||||
for me in msg["content"]:
|
if me["type"] == "image_url":
|
||||||
if me["type"] == "image_url":
|
me["image_url"]['url'] = await self.get_base64_str(me["image_url"]['url'])
|
||||||
# me["image_url"]['url'] = await self.get_oss_url(me["image_url"]['url'])
|
|
||||||
me["image_url"]['url'] = await self.get_base64_str(me["image_url"]['url'])
|
|
||||||
|
|
||||||
args["messages"] = messages
|
args["messages"] = messages
|
||||||
|
|
||||||
@@ -135,20 +124,6 @@ class OpenAIChatCompletions(api.LLMAPIRequester):
|
|||||||
except openai.APIError as e:
|
except openai.APIError as e:
|
||||||
raise errors.RequesterError(f'请求错误: {e.message}')
|
raise errors.RequesterError(f'请求错误: {e.message}')
|
||||||
|
|
||||||
async def get_oss_url(
|
|
||||||
self,
|
|
||||||
original_url: str,
|
|
||||||
) -> str:
|
|
||||||
|
|
||||||
if original_url in self.cached_image_oss_url:
|
|
||||||
return self.cached_image_oss_url[original_url]
|
|
||||||
|
|
||||||
oss_url = await self.ap.oss_mgr.upload_url_image(original_url)
|
|
||||||
|
|
||||||
self.cached_image_oss_url[original_url] = oss_url
|
|
||||||
|
|
||||||
return oss_url
|
|
||||||
|
|
||||||
async def get_base64_str(
|
async def get_base64_str(
|
||||||
self,
|
self,
|
||||||
original_url: str,
|
original_url: str,
|
||||||
|
|||||||
@@ -38,10 +38,6 @@ class ModelManager:
|
|||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
|
|
||||||
# 检查是否启用了vision但是没有配置oss
|
|
||||||
if self.ap.provider_cfg.data['enable-vision'] and not self.ap.oss_mgr.available():
|
|
||||||
self.ap.logger.warn("启用了视觉但是没有配置可用的oss服务,基于 URL 传递图片的视觉 API 将无法正常使用")
|
|
||||||
|
|
||||||
# 初始化token_mgr, requester
|
# 初始化token_mgr, requester
|
||||||
for k, v in self.ap.provider_cfg.data['keys'].items():
|
for k, v in self.ap.provider_cfg.data['keys'].items():
|
||||||
self.token_mgrs[k] = token.TokenManager(k, v)
|
self.token_mgrs[k] = token.TokenManager(k, v)
|
||||||
|
|||||||
@@ -14,5 +14,3 @@ pydantic
|
|||||||
websockets
|
websockets
|
||||||
urllib3
|
urllib3
|
||||||
psutil
|
psutil
|
||||||
|
|
||||||
oss2
|
|
||||||
@@ -1,17 +1,5 @@
|
|||||||
{
|
{
|
||||||
"admin-sessions": [],
|
"admin-sessions": [],
|
||||||
"oss": [
|
|
||||||
{
|
|
||||||
"type": "aliyun",
|
|
||||||
"endpoint": "https://oss-cn-hangzhou.aliyuncs.com",
|
|
||||||
"public-read-base-url": "https://qchatgpt.oss-cn-hangzhou.aliyuncs.com",
|
|
||||||
"access-key-id": "LTAI5tJ5Q5J8J6J5J5J5J5J5",
|
|
||||||
"access-key-secret": "xxxxxx",
|
|
||||||
"bucket": "qchatgpt",
|
|
||||||
"prefix": "qchatgpt",
|
|
||||||
"enable": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"network-proxies": {
|
"network-proxies": {
|
||||||
"http": null,
|
"http": null,
|
||||||
"https": null
|
"https": null
|
||||||
|
|||||||
Reference in New Issue
Block a user