Compare commits

..

14 Commits

Author SHA1 Message Date
Junyan Qin
59211191a4 chore: release v3.4.0.2 2024-11-23 00:23:47 +08:00
Junyan Qin
a3ca7e82c7 hotfix: 调用工具时bug 2024-11-23 00:23:08 +08:00
Junyan Qin
0094056def chore: release v3.4.0.1 2024-11-22 23:55:24 +08:00
Junyan Qin
a9f305a1c6 feat: 添加对pydantic v1的兼容性 2024-11-22 23:37:46 +08:00
Junyan Qin
e8cc048901 deps: bump pydantic to v2 2024-11-22 23:29:12 +08:00
Junyan Qin
05da43f606 chore: 更新模型信息 2024-11-22 22:33:05 +08:00
Junyan Qin
a81faa7d8e fix: gitee ai 配置 schema 2024-11-22 20:01:35 +08:00
Junyan Qin
18ba7d1da7 Merge pull request #929 from RockChinQ/feat/gitee-ai
feat: 添加对 Gitee AI 的支持
2024-11-22 19:59:25 +08:00
Junyan Qin
875adfcbaa feat: 添加对 Gitee AI 的支持 2024-11-21 23:28:19 +08:00
Junyan Qin
6e9c213893 fix: 登录失败时无提示 2024-11-20 21:03:02 +08:00
Junyan Qin
753066ccb9 fix: webui 访问提示在Windows上的编码问题 2024-11-19 19:33:58 +08:00
Junyan Qin
8b36782c25 chore: 更新 docker-compose.yaml 2024-11-18 23:31:49 +08:00
Junyan Qin
da9dde6bd2 doc: update README 2024-11-17 21:30:53 +08:00
Junyan Qin
07f6e69b93 doc: update README.md 2024-11-17 21:11:21 +08:00
46 changed files with 232 additions and 119 deletions

View File

@@ -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>
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/LangBot)](https://github.com/RockChinQ/LangBot/releases/latest) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/RockChinQ/LangBot)](https://github.com/RockChinQ/LangBot/releases/latest)
<a href="https://hub.docker.com/repository/docker/rockchin/langbot"> ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.qchatgpt.rockchin.top%2Fapi%2Fv2%2Fview%2Frealtime%2Fcount_query%3Fminute%3D10080&query=%24.data.count&label=%E4%BD%BF%E7%94%A8%E9%87%8F%EF%BC%887%E6%97%A5%EF%BC%89)
<img src="https://img.shields.io/docker/pulls/rockchin/langbot?color=blue" alt="docker pull">
</a>
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.docs.langbot.app%2Fapi%2Fv2%2Fview%2Frealtime%2Fcount_query%3Fminute%3D10080&query=%24.data.count&label=%E4%BD%BF%E7%94%A8%E9%87%8F%EF%BC%887%E6%97%A5%EF%BC%89)
![Wakapi Count](https://wakapi.rockchin.top/api/badge/RockChinQ/interval:any/project:QChatGPT) ![Wakapi Count](https://wakapi.rockchin.top/api/badge/RockChinQ/interval:any/project:QChatGPT)
<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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View 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()

View File

@@ -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}')

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
) )

View File

@@ -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

View File

@@ -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

View File

@@ -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 请求器"""

View 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

View File

@@ -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 请求器"""

View File

@@ -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

View File

@@ -2,8 +2,6 @@ from __future__ import annotations
import typing import typing
import pydantic
class TokenManager(): class TokenManager():
"""鉴权 Token 管理器 """鉴权 Token 管理器

View File

@@ -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

View File

@@ -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

View File

@@ -118,10 +118,9 @@ class ToolManager:
traceback.print_exc() traceback.print_exc()
return f"error occurred when executing function {name}: {e}" return f"error occurred when executing function {name}: {e}"
finally: finally:
plugin = None plugin = None
for p in self.ap.plugin_mgr.plugins: for p in self.ap.plugin_mgr.plugins():
if function in p.content_functions: if function in p.content_functions:
plugin = p plugin = p
break break

View File

@@ -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

View File

@@ -1,4 +1,4 @@
semantic_version = "v3.4.0" semantic_version = "v3.4.0.2"
debug_mode = False debug_mode = False

View File

@@ -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

View File

@@ -9,7 +9,7 @@ Pillow
tiktoken tiktoken
PyYaml PyYaml
aiohttp aiohttp
pydantic<2.0 pydantic>2.0
websockets websockets
urllib3 urllib3
psutil psutil

View File

@@ -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"
} }
] ]
} }

View File

@@ -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": ""

View File

@@ -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
}
}
} }
} }
}, },

View File

@@ -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', '登录失败')
}
}) })
} }