mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-08 23:06:03 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0094056def | ||
|
|
a9f305a1c6 | ||
|
|
e8cc048901 | ||
|
|
05da43f606 | ||
|
|
a81faa7d8e | ||
|
|
18ba7d1da7 | ||
|
|
875adfcbaa | ||
|
|
6e9c213893 | ||
|
|
753066ccb9 | ||
|
|
8b36782c25 | ||
|
|
da9dde6bd2 | ||
|
|
07f6e69b93 |
12
README.md
12
README.md
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://docs.langbot.app/chrome-512.png" alt="QChatGPT" width="180" />
|
<img src="https://docs.langbot.app/langbot-logo-0.5x.png" alt="QChatGPT" width="180" />
|
||||||
</p>
|
</p>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
@@ -9,10 +9,7 @@
|
|||||||
<a href="https://trendshift.io/repositories/6187" target="_blank"><img src="https://trendshift.io/api/badge/repositories/6187" alt="RockChinQ%2FQChatGPT | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
<a href="https://trendshift.io/repositories/6187" target="_blank"><img src="https://trendshift.io/api/badge/repositories/6187" alt="RockChinQ%2FQChatGPT | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||||
|
|
||||||
[](https://github.com/RockChinQ/LangBot/releases/latest)
|
[](https://github.com/RockChinQ/LangBot/releases/latest)
|
||||||
<a href="https://hub.docker.com/repository/docker/rockchin/langbot">
|

|
||||||
<img src="https://img.shields.io/docker/pulls/rockchin/langbot?color=blue" alt="docker pull">
|
|
||||||
</a>
|
|
||||||

|
|
||||||

|

|
||||||
<br/>
|
<br/>
|
||||||
<img src="https://img.shields.io/badge/python-3.10 | 3.11 | 3.12-blue.svg" alt="python">
|
<img src="https://img.shields.io/badge/python-3.10 | 3.11 | 3.12-blue.svg" alt="python">
|
||||||
@@ -22,9 +19,6 @@
|
|||||||
<a href="https://qm.qq.com/q/PClALFK242">
|
<a href="https://qm.qq.com/q/PClALFK242">
|
||||||
<img alt="Static Badge" src="https://img.shields.io/badge/%E7%A4%BE%E5%8C%BA%E7%BE%A4-619154800-purple">
|
<img alt="Static Badge" src="https://img.shields.io/badge/%E7%A4%BE%E5%8C%BA%E7%BE%A4-619154800-purple">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://codecov.io/gh/RockChinQ/QChatGPT" >
|
|
||||||
<img src="https://codecov.io/gh/RockChinQ/QChatGPT/graph/badge.svg?token=pjxYIL2kbC"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## 使用文档
|
## 使用文档
|
||||||
|
|
||||||
@@ -42,5 +36,5 @@
|
|||||||
<a href="https://github.com/RockChinQ/qcg-center">遥测服务端源码</a> |
|
<a href="https://github.com/RockChinQ/qcg-center">遥测服务端源码</a> |
|
||||||
<a href="https://github.com/the-lazy-me/QChatGPT-Wiki">官方文档储存库</a>
|
<a href="https://github.com/the-lazy-me/QChatGPT-Wiki">官方文档储存库</a>
|
||||||
|
|
||||||
<img alt="回复效果(带有联网插件)" src="https://docs.langbot.top/QChatGPT-0516.png" width="500px"/>
|
<img alt="回复效果(带有联网插件)" src="https://docs.langbot.app/QChatGPT-0516.png" width="500px"/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ version: "3"
|
|||||||
services:
|
services:
|
||||||
langbot:
|
langbot:
|
||||||
image: rockchin/langbot:latest
|
image: rockchin/langbot:latest
|
||||||
|
container_name: langbot
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- ./plugins:/app/plugins
|
- ./plugins:/app/plugins
|
||||||
|
|||||||
6
main.py
6
main.py
@@ -36,6 +36,12 @@ async def main_entry(loop: asyncio.AbstractEventLoop):
|
|||||||
print("已自动安装缺失的依赖包,请重启程序。")
|
print("已自动安装缺失的依赖包,请重启程序。")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
# 检查pydantic版本,如果没有 pydantic.v1,则把 pydantic 映射为 v1
|
||||||
|
import pydantic.version
|
||||||
|
if pydantic.version.VERSION < '2.0':
|
||||||
|
import pydantic
|
||||||
|
sys.modules['pydantic.v1'] = pydantic
|
||||||
|
|
||||||
# 检查配置文件
|
# 检查配置文件
|
||||||
|
|
||||||
from pkg.core.bootutils import files
|
from pkg.core.bootutils import files
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import quart
|
import quart
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
import argon2
|
||||||
|
|
||||||
from .. import group
|
from .. import group
|
||||||
from .....persistence.entities import user
|
from .....persistence.entities import user
|
||||||
@@ -32,7 +33,10 @@ class UserRouterGroup(group.RouterGroup):
|
|||||||
async def _() -> str:
|
async def _() -> str:
|
||||||
json_data = await quart.request.json
|
json_data = await quart.request.json
|
||||||
|
|
||||||
token = await self.ap.user_service.authenticate(json_data['user'], json_data['password'])
|
try:
|
||||||
|
token = await self.ap.user_service.authenticate(json_data['user'], json_data['password'])
|
||||||
|
except argon2.exceptions.VerifyMismatchError:
|
||||||
|
return self.fail(1, '用户名或密码错误')
|
||||||
|
|
||||||
return self.success(data={
|
return self.success(data={
|
||||||
'token': token
|
'token': token
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ class UserService:
|
|||||||
|
|
||||||
ph = argon2.PasswordHasher()
|
ph = argon2.PasswordHasher()
|
||||||
|
|
||||||
if not ph.verify(user_obj.password, password):
|
ph.verify(user_obj.password, password)
|
||||||
raise ValueError('密码错误')
|
|
||||||
|
|
||||||
return await self.generate_jwt_token(user_email)
|
return await self.generate_jwt_token(user_email)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ..core import app, entities as core_entities
|
from ..core import app, entities as core_entities
|
||||||
from . import errors, operator
|
from . import errors, operator
|
||||||
|
|||||||
@@ -42,8 +42,11 @@ async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.
|
|||||||
)
|
)
|
||||||
|
|
||||||
stream_handler = logging.StreamHandler(sys.stdout)
|
stream_handler = logging.StreamHandler(sys.stdout)
|
||||||
|
# stream_handler.setLevel(level)
|
||||||
|
# stream_handler.setFormatter(color_formatter)
|
||||||
|
stream_handler.stream = open(sys.stdout.fileno(), mode='w', encoding='utf-8', buffering=1)
|
||||||
|
|
||||||
log_handlers: list[logging.Handler] = [stream_handler, logging.FileHandler(log_file_name)]
|
log_handlers: list[logging.Handler] = [stream_handler, logging.FileHandler(log_file_name, encoding='utf-8')]
|
||||||
log_handlers += extra_handlers if extra_handlers is not None else []
|
log_handlers += extra_handlers if extra_handlers is not None else []
|
||||||
|
|
||||||
for handler in log_handlers:
|
for handler in log_handlers:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import typing
|
|||||||
import datetime
|
import datetime
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ..provider import entities as llm_entities
|
from ..provider import entities as llm_entities
|
||||||
from ..provider.modelmgr import entities
|
from ..provider.modelmgr import entities
|
||||||
|
|||||||
26
pkg/core/migrations/m015_gitee_ai_config.py
Normal file
26
pkg/core/migrations/m015_gitee_ai_config.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from .. import migration
|
||||||
|
|
||||||
|
|
||||||
|
@migration.migration_class("gitee-ai-config", 15)
|
||||||
|
class GiteeAIConfigMigration(migration.Migration):
|
||||||
|
"""迁移"""
|
||||||
|
|
||||||
|
async def need_migrate(self) -> bool:
|
||||||
|
"""判断当前环境是否需要运行此迁移"""
|
||||||
|
return 'gitee-ai-chat-completions' not in self.ap.provider_cfg.data['requester'] or 'gitee-ai' not in self.ap.provider_cfg.data['keys']
|
||||||
|
|
||||||
|
async def run(self):
|
||||||
|
"""执行迁移"""
|
||||||
|
self.ap.provider_cfg.data['requester']['gitee-ai-chat-completions'] = {
|
||||||
|
"base-url": "https://ai.gitee.com/v1",
|
||||||
|
"args": {},
|
||||||
|
"timeout": 120
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ap.provider_cfg.data['keys']['gitee-ai'] = [
|
||||||
|
"XXXXX"
|
||||||
|
]
|
||||||
|
|
||||||
|
await self.ap.provider_cfg.dump_config()
|
||||||
@@ -7,6 +7,7 @@ from .. import migration
|
|||||||
from ..migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
|
from ..migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
|
||||||
from ..migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url, m008_ad_fixwin_config_migrate, m009_msg_truncator_cfg
|
from ..migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url, m008_ad_fixwin_config_migrate, m009_msg_truncator_cfg
|
||||||
from ..migrations import m010_ollama_requester_config, m011_command_prefix_config, m012_runner_config, m013_http_api_config, m014_force_delay_config
|
from ..migrations import m010_ollama_requester_config, m011_command_prefix_config, m012_runner_config, m013_http_api_config, m014_force_delay_config
|
||||||
|
from ..migrations import m015_gitee_ai_config
|
||||||
|
|
||||||
|
|
||||||
@stage.stage_class("MigrationStage")
|
@stage.stage_class("MigrationStage")
|
||||||
@@ -28,3 +29,4 @@ class MigrationStage(stage.BootingStage):
|
|||||||
|
|
||||||
if await migration_instance.need_migrate():
|
if await migration_instance.need_migrate():
|
||||||
await migration_instance.run()
|
await migration_instance.run()
|
||||||
|
print(f'已执行迁移 {migration_instance.name}')
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import typing
|
import typing
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ...provider import entities as llm_entities
|
from ...provider import entities as llm_entities
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
import enum
|
import enum
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
from ..platform.types import message as platform_message
|
from ..platform.types import message as platform_message
|
||||||
|
|
||||||
from ..core import entities
|
from ..core import entities
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from .. import strategy as strategy_model
|
from .. import strategy as strategy_model
|
||||||
from ....core import entities as core_entities
|
from ....core import entities as core_entities
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class Text2ImageStrategy(strategy_model.LongTextStrategy):
|
|||||||
"""
|
"""
|
||||||
kv = []
|
kv = []
|
||||||
nums = []
|
nums = []
|
||||||
beforeDatas = re.findall('[\d]+', path)
|
beforeDatas = re.findall('[\\d]+', path)
|
||||||
for num in beforeDatas:
|
for num in beforeDatas:
|
||||||
indexV = []
|
indexV = []
|
||||||
times = path.count(num)
|
times = path.count(num)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ...platform.types import message as platform_message
|
from ...platform.types import message as platform_message
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import pydantic
|
|
||||||
|
|
||||||
from ..core import app
|
from ..core import app
|
||||||
from . import stage
|
from . import stage
|
||||||
from .resprule import resprule
|
from .resprule import resprule
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import traceback
|
|||||||
import botpy
|
import botpy
|
||||||
import botpy.message as botpy_message
|
import botpy.message as botpy_message
|
||||||
import botpy.types.message as botpy_message_type
|
import botpy.types.message as botpy_message_type
|
||||||
import pydantic
|
|
||||||
import pydantic.networks
|
|
||||||
|
|
||||||
from .. import adapter as adapter_model
|
from .. import adapter as adapter_model
|
||||||
from ...pipeline.longtext.strategies import forward
|
from ...pipeline.longtext.strategies import forward
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
import pydantic.main as pdm
|
import pydantic.v1.main as pdm
|
||||||
from pydantic import BaseModel
|
from pydantic.v1 import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class PlatformMetaclass(pdm.ModelMetaclass):
|
class PlatformMetaclass(pdm.ModelMetaclass):
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from datetime import datetime
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
|
|
||||||
class Entity(pydantic.BaseModel):
|
class Entity(pydantic.BaseModel):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from datetime import datetime
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from . import entities as platform_entities
|
from . import entities as platform_entities
|
||||||
from . import message as platform_message
|
from . import message as platform_message
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ from enum import Enum
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
import pydantic.main
|
|
||||||
|
|
||||||
from . import entities as platform_entities
|
from . import entities as platform_entities
|
||||||
from .base import PlatformBaseModel, PlatformIndexedMetaclass, PlatformIndexedModel
|
from .base import PlatformBaseModel, PlatformIndexedMetaclass, PlatformIndexedModel
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
import abc
|
import abc
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from . import events
|
from . import events
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ..core import entities as core_entities
|
from ..core import entities as core_entities
|
||||||
from ..provider import entities as llm_entities
|
from ..provider import entities as llm_entities
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
import enum
|
import enum
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
|
|
||||||
from ..platform.types import message as platform_message
|
from ..platform.types import message as platform_message
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from . import api
|
from . import requester
|
||||||
from . import token
|
from . import token
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ class LLMModelInfo(pydantic.BaseModel):
|
|||||||
|
|
||||||
token_mgr: token.TokenManager
|
token_mgr: token.TokenManager
|
||||||
|
|
||||||
requester: api.LLMAPIRequester
|
requester: requester.LLMAPIRequester
|
||||||
|
|
||||||
tool_call_supported: typing.Optional[bool] = False
|
tool_call_supported: typing.Optional[bool] = False
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from . import entities
|
from . import entities, requester
|
||||||
from ...core import app
|
from ...core import app
|
||||||
|
|
||||||
from . import token, api
|
from . import token
|
||||||
from .apis import chatcmpl, anthropicmsgs, moonshotchatcmpl, deepseekchatcmpl, ollamachat
|
from .requesters import chatcmpl, anthropicmsgs, moonshotchatcmpl, deepseekchatcmpl, ollamachat, giteeaichatcmpl
|
||||||
|
|
||||||
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"
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class ModelManager:
|
|||||||
|
|
||||||
model_list: list[entities.LLMModelInfo]
|
model_list: list[entities.LLMModelInfo]
|
||||||
|
|
||||||
requesters: dict[str, api.LLMAPIRequester]
|
requesters: dict[str, requester.LLMAPIRequester]
|
||||||
|
|
||||||
token_mgrs: dict[str, token.TokenManager]
|
token_mgrs: dict[str, token.TokenManager]
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class ModelManager:
|
|||||||
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)
|
||||||
|
|
||||||
for api_cls in api.preregistered_requesters:
|
for api_cls in requester.preregistered_requesters:
|
||||||
api_inst = api_cls(self.ap)
|
api_inst = api_cls(self.ap)
|
||||||
await api_inst.initialize()
|
await api_inst.initialize()
|
||||||
self.requesters[api_inst.name] = api_inst
|
self.requesters[api_inst.name] = api_inst
|
||||||
@@ -94,7 +94,7 @@ class ModelManager:
|
|||||||
|
|
||||||
model_name = model.get('model_name', default_model_info.model_name)
|
model_name = model.get('model_name', default_model_info.model_name)
|
||||||
token_mgr = self.token_mgrs[model['token_mgr']] if 'token_mgr' in model else default_model_info.token_mgr
|
token_mgr = self.token_mgrs[model['token_mgr']] if 'token_mgr' in model else default_model_info.token_mgr
|
||||||
requester = self.requesters[model['requester']] if 'requester' in model else default_model_info.requester
|
req = self.requesters[model['requester']] if 'requester' in model else default_model_info.requester
|
||||||
tool_call_supported = model.get('tool_call_supported', default_model_info.tool_call_supported)
|
tool_call_supported = model.get('tool_call_supported', default_model_info.tool_call_supported)
|
||||||
vision_supported = model.get('vision_supported', default_model_info.vision_supported)
|
vision_supported = model.get('vision_supported', default_model_info.vision_supported)
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ class ModelManager:
|
|||||||
name=model['name'],
|
name=model['name'],
|
||||||
model_name=model_name,
|
model_name=model_name,
|
||||||
token_mgr=token_mgr,
|
token_mgr=token_mgr,
|
||||||
requester=requester,
|
requester=req,
|
||||||
tool_call_supported=tool_call_supported,
|
tool_call_supported=tool_call_supported,
|
||||||
vision_supported=vision_supported
|
vision_supported=vision_supported
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import traceback
|
|||||||
|
|
||||||
import anthropic
|
import anthropic
|
||||||
|
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors, requester
|
||||||
|
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors
|
||||||
from ....core import entities as core_entities
|
from ....core import entities as core_entities
|
||||||
from ... import entities as llm_entities
|
from ... import entities as llm_entities
|
||||||
from ...tools import entities as tools_entities
|
from ...tools import entities as tools_entities
|
||||||
from ....utils import image
|
from ....utils import image
|
||||||
|
|
||||||
|
|
||||||
@api.requester_class("anthropic-messages")
|
@requester.requester_class("anthropic-messages")
|
||||||
class AnthropicMessages(api.LLMAPIRequester):
|
class AnthropicMessages(requester.LLMAPIRequester):
|
||||||
"""Anthropic Messages API 请求器"""
|
"""Anthropic Messages API 请求器"""
|
||||||
|
|
||||||
client: anthropic.AsyncAnthropic
|
client: anthropic.AsyncAnthropic
|
||||||
@@ -12,15 +12,15 @@ import httpx
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
import async_lru
|
import async_lru
|
||||||
|
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors, requester
|
||||||
from ....core import entities as core_entities, app
|
from ....core import entities as core_entities, app
|
||||||
from ... import entities as llm_entities
|
from ... import entities as llm_entities
|
||||||
from ...tools import entities as tools_entities
|
from ...tools import entities as tools_entities
|
||||||
from ....utils import image
|
from ....utils import image
|
||||||
|
|
||||||
|
|
||||||
@api.requester_class("openai-chat-completions")
|
@requester.requester_class("openai-chat-completions")
|
||||||
class OpenAIChatCompletions(api.LLMAPIRequester):
|
class OpenAIChatCompletions(requester.LLMAPIRequester):
|
||||||
"""OpenAI ChatCompletion API 请求器"""
|
"""OpenAI ChatCompletion API 请求器"""
|
||||||
|
|
||||||
client: openai.AsyncClient
|
client: openai.AsyncClient
|
||||||
@@ -3,13 +3,13 @@ from __future__ import annotations
|
|||||||
from ....core import app
|
from ....core import app
|
||||||
|
|
||||||
from . import chatcmpl
|
from . import chatcmpl
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors, requester
|
||||||
from ....core import entities as core_entities, app
|
from ....core import entities as core_entities, app
|
||||||
from ... import entities as llm_entities
|
from ... import entities as llm_entities
|
||||||
from ...tools import entities as tools_entities
|
from ...tools import entities as tools_entities
|
||||||
|
|
||||||
|
|
||||||
@api.requester_class("deepseek-chat-completions")
|
@requester.requester_class("deepseek-chat-completions")
|
||||||
class DeepseekChatCompletions(chatcmpl.OpenAIChatCompletions):
|
class DeepseekChatCompletions(chatcmpl.OpenAIChatCompletions):
|
||||||
"""Deepseek ChatCompletion API 请求器"""
|
"""Deepseek ChatCompletion API 请求器"""
|
||||||
|
|
||||||
53
pkg/provider/modelmgr/requesters/giteeaichatcmpl.py
Normal file
53
pkg/provider/modelmgr/requesters/giteeaichatcmpl.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import aiohttp
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from . import chatcmpl
|
||||||
|
from .. import entities, errors, requester
|
||||||
|
from ....core import app
|
||||||
|
from ... import entities as llm_entities
|
||||||
|
from ...tools import entities as tools_entities
|
||||||
|
from .. import entities as modelmgr_entities
|
||||||
|
|
||||||
|
|
||||||
|
@requester.requester_class("gitee-ai-chat-completions")
|
||||||
|
class GiteeAIChatCompletions(chatcmpl.OpenAIChatCompletions):
|
||||||
|
"""Gitee AI ChatCompletions API 请求器"""
|
||||||
|
|
||||||
|
def __init__(self, ap: app.Application):
|
||||||
|
self.ap = ap
|
||||||
|
self.requester_cfg = ap.provider_cfg.data['requester']['gitee-ai-chat-completions'].copy()
|
||||||
|
|
||||||
|
async def _closure(
|
||||||
|
self,
|
||||||
|
req_messages: list[dict],
|
||||||
|
use_model: entities.LLMModelInfo,
|
||||||
|
use_funcs: list[tools_entities.LLMFunction] = None,
|
||||||
|
) -> llm_entities.Message:
|
||||||
|
self.client.api_key = use_model.token_mgr.get_token()
|
||||||
|
|
||||||
|
args = self.requester_cfg['args'].copy()
|
||||||
|
args["model"] = use_model.name if use_model.model_name is None else use_model.model_name
|
||||||
|
|
||||||
|
if use_funcs:
|
||||||
|
tools = await self.ap.tool_mgr.generate_tools_for_openai(use_funcs)
|
||||||
|
|
||||||
|
if tools:
|
||||||
|
args["tools"] = tools
|
||||||
|
|
||||||
|
# gitee 不支持多模态,把content都转换成纯文字
|
||||||
|
for m in req_messages:
|
||||||
|
if 'content' in m and isinstance(m["content"], list):
|
||||||
|
m["content"] = " ".join([c["text"] for c in m["content"]])
|
||||||
|
|
||||||
|
args["messages"] = req_messages
|
||||||
|
|
||||||
|
resp = await self._req(args)
|
||||||
|
|
||||||
|
message = await self._make_msg(resp)
|
||||||
|
|
||||||
|
return message
|
||||||
@@ -3,13 +3,13 @@ from __future__ import annotations
|
|||||||
from ....core import app
|
from ....core import app
|
||||||
|
|
||||||
from . import chatcmpl
|
from . import chatcmpl
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors, requester
|
||||||
from ....core import entities as core_entities, app
|
from ....core import entities as core_entities, app
|
||||||
from ... import entities as llm_entities
|
from ... import entities as llm_entities
|
||||||
from ...tools import entities as tools_entities
|
from ...tools import entities as tools_entities
|
||||||
|
|
||||||
|
|
||||||
@api.requester_class("moonshot-chat-completions")
|
@requester.requester_class("moonshot-chat-completions")
|
||||||
class MoonshotChatCompletions(chatcmpl.OpenAIChatCompletions):
|
class MoonshotChatCompletions(chatcmpl.OpenAIChatCompletions):
|
||||||
"""Moonshot ChatCompletion API 请求器"""
|
"""Moonshot ChatCompletion API 请求器"""
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ from typing import Union, Mapping, Any, AsyncIterator
|
|||||||
import async_lru
|
import async_lru
|
||||||
import ollama
|
import ollama
|
||||||
|
|
||||||
from .. import api, entities, errors
|
from .. import entities, errors, requester
|
||||||
from ... import entities as llm_entities
|
from ... import entities as llm_entities
|
||||||
from ...tools import entities as tools_entities
|
from ...tools import entities as tools_entities
|
||||||
from ....core import app
|
from ....core import app
|
||||||
@@ -17,8 +17,8 @@ from ....utils import image
|
|||||||
REQUESTER_NAME: str = "ollama-chat"
|
REQUESTER_NAME: str = "ollama-chat"
|
||||||
|
|
||||||
|
|
||||||
@api.requester_class(REQUESTER_NAME)
|
@requester.requester_class(REQUESTER_NAME)
|
||||||
class OllamaChatCompletions(api.LLMAPIRequester):
|
class OllamaChatCompletions(requester.LLMAPIRequester):
|
||||||
"""Ollama平台 ChatCompletion API请求器"""
|
"""Ollama平台 ChatCompletion API请求器"""
|
||||||
client: ollama.AsyncClient
|
client: ollama.AsyncClient
|
||||||
request_cfg: dict
|
request_cfg: dict
|
||||||
@@ -2,8 +2,6 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import pydantic
|
|
||||||
|
|
||||||
|
|
||||||
class TokenManager():
|
class TokenManager():
|
||||||
"""鉴权 Token 管理器
|
"""鉴权 Token 管理器
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import typing
|
import typing
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ...provider import entities
|
from ...provider import entities
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import abc
|
|||||||
import typing
|
import typing
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
|
|
||||||
from ...core import entities as core_entities
|
from ...core import entities as core_entities
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import os
|
|||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pydantic
|
import pydantic.v1 as pydantic
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from ..core import app
|
from ..core import app
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
semantic_version = "v3.4.0"
|
semantic_version = "v3.4.0.1"
|
||||||
|
|
||||||
debug_mode = False
|
debug_mode = False
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import pydantic
|
|
||||||
|
|
||||||
|
|
||||||
LOG_PAGE_SIZE = 20
|
LOG_PAGE_SIZE = 20
|
||||||
MAX_CACHED_PAGES = 10
|
MAX_CACHED_PAGES = 10
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Pillow
|
|||||||
tiktoken
|
tiktoken
|
||||||
PyYaml
|
PyYaml
|
||||||
aiohttp
|
aiohttp
|
||||||
pydantic<2.0
|
pydantic>2.0
|
||||||
websockets
|
websockets
|
||||||
urllib3
|
urllib3
|
||||||
psutil
|
psutil
|
||||||
|
|||||||
@@ -8,69 +8,59 @@
|
|||||||
"vision_supported": false
|
"vision_supported": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-3.5-turbo-0125",
|
"name": "gpt-4o",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": false
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-3.5-turbo",
|
"name": "gpt-4o-2024-11-20",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": false
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-3.5-turbo-1106",
|
"name": "gpt-4o-2024-08-06",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": false
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gpt-4o-2024-05-13",
|
||||||
|
"tool_call_supported": true,
|
||||||
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chatgpt-4o-latest",
|
||||||
|
"tool_call_supported": true,
|
||||||
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gpt-4o-mini",
|
||||||
|
"tool_call_supported": true,
|
||||||
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "o1-preview",
|
||||||
|
"tool_call_supported": true,
|
||||||
|
"vision_supported": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "o1-mini",
|
||||||
|
"tool_call_supported": true,
|
||||||
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-4-turbo",
|
"name": "gpt-4-turbo",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "gpt-4-turbo-2024-04-09",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-turbo-preview",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-0125-preview",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-1106-preview",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "gpt-4",
|
"name": "gpt-4",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gpt-4o",
|
"name": "gpt-3.5-turbo",
|
||||||
"tool_call_supported": true,
|
"tool_call_supported": true,
|
||||||
"vision_supported": true
|
"vision_supported": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-0613",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-32k",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gpt-4-32k-0613",
|
|
||||||
"tool_call_supported": true,
|
|
||||||
"vision_supported": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"model_name": "SparkDesk",
|
"model_name": "SparkDesk",
|
||||||
@@ -81,19 +71,19 @@
|
|||||||
"name": "OneAPI/gemini-pro"
|
"name": "OneAPI/gemini-pro"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "claude-3-opus-20240229",
|
"name": "claude-3-opus-latest",
|
||||||
"requester": "anthropic-messages",
|
"requester": "anthropic-messages",
|
||||||
"token_mgr": "anthropic",
|
"token_mgr": "anthropic",
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "claude-3-sonnet-20240229",
|
"name": "claude-3-5-sonnet-latest",
|
||||||
"requester": "anthropic-messages",
|
"requester": "anthropic-messages",
|
||||||
"token_mgr": "anthropic",
|
"token_mgr": "anthropic",
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "claude-3-haiku-20240307",
|
"name": "claude-3-5-haiku-latest",
|
||||||
"requester": "anthropic-messages",
|
"requester": "anthropic-messages",
|
||||||
"token_mgr": "anthropic",
|
"token_mgr": "anthropic",
|
||||||
"vision_supported": true
|
"vision_supported": true
|
||||||
@@ -120,6 +110,11 @@
|
|||||||
"name": "deepseek-chat",
|
"name": "deepseek-chat",
|
||||||
"requester": "deepseek-chat-completions",
|
"requester": "deepseek-chat-completions",
|
||||||
"token_mgr": "deepseek"
|
"token_mgr": "deepseek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deepseek-coder",
|
||||||
|
"requester": "deepseek-chat-completions",
|
||||||
|
"token_mgr": "deepseek"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,9 @@
|
|||||||
],
|
],
|
||||||
"deepseek": [
|
"deepseek": [
|
||||||
"sk-1234567890"
|
"sk-1234567890"
|
||||||
|
],
|
||||||
|
"gitee-ai": [
|
||||||
|
"XXXXX"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"requester": {
|
"requester": {
|
||||||
@@ -42,9 +45,14 @@
|
|||||||
"base-url": "http://127.0.0.1:11434",
|
"base-url": "http://127.0.0.1:11434",
|
||||||
"args": {},
|
"args": {},
|
||||||
"timeout": 600
|
"timeout": 600
|
||||||
|
},
|
||||||
|
"gitee-ai-chat-completions": {
|
||||||
|
"base-url": "https://ai.gitee.com/v1",
|
||||||
|
"args": {},
|
||||||
|
"timeout": 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"model": "gpt-3.5-turbo",
|
"model": "gpt-4o",
|
||||||
"prompt-mode": "normal",
|
"prompt-mode": "normal",
|
||||||
"prompt": {
|
"prompt": {
|
||||||
"default": ""
|
"default": ""
|
||||||
|
|||||||
@@ -54,6 +54,15 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
|
},
|
||||||
|
"gitee": {
|
||||||
|
"type": "array",
|
||||||
|
"title": "Gitee API 密钥",
|
||||||
|
"description": "Gitee API 密钥",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -160,6 +169,25 @@
|
|||||||
"default": 600
|
"default": 600
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"gitee-ai-chat-completions": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "Gitee AI API 请求配置",
|
||||||
|
"description": "仅可编辑 URL 和 超时时间,额外请求参数不支持可视化编辑,请到编辑器编辑",
|
||||||
|
"properties": {
|
||||||
|
"base-url": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "API URL"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"type": "number",
|
||||||
|
"title": "API 请求超时时间",
|
||||||
|
"default": 120
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -47,17 +47,21 @@ const login = () => {
|
|||||||
user: user.value,
|
user: user.value,
|
||||||
password: password.value
|
password: password.value
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.data.data.token) {
|
if (res.data.code == 0) {
|
||||||
emit('success', '登录成功')
|
emit('success', '登录成功')
|
||||||
localStorage.setItem('user-token', res.data.data.token)
|
localStorage.setItem('user-token', res.data.data.token)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
location.reload()
|
location.reload()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
} else {
|
} else {
|
||||||
emit('error', '登录失败')
|
emit('error', res.data.msg)
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
emit('error', err.response.data.message)
|
if (err.response.data.msg) {
|
||||||
|
emit('error', err.response.data.msg)
|
||||||
|
} else {
|
||||||
|
emit('error', '登录失败')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user