From 8461188f3b343b1ea9677016049132c6bb4e8914 Mon Sep 17 00:00:00 2001 From: TGY Date: Tue, 25 Feb 2025 18:05:52 +0800 Subject: [PATCH] =?UTF-8?q?add=20kirara=20=E3=80=81one-hub=E3=80=81new-api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kirara/README.md | 82 ++++++++++++++++ kirara/data.yml | 21 ++++ kirara/latest/data.yml | 17 ++++ kirara/latest/docker-compose.yml | 18 ++++ new-api/README.md | 157 ++++++++++++++++++++++++++++++ new-api/data.yml | 19 ++++ new-api/latest/data.yml | 52 ++++++++++ new-api/latest/docker-compose.yml | 26 +++++ new-api/logo.png | Bin 0 -> 7749 bytes one-hub/README.md | 131 +++++++++++++++++++++++++ one-hub/data.yml | 19 ++++ one-hub/latest/data.yml | 56 +++++++++++ one-hub/latest/docker-compose.yml | 28 ++++++ one-hub/logo.png | Bin 0 -> 18577 bytes 14 files changed, 626 insertions(+) create mode 100644 kirara/README.md create mode 100644 kirara/data.yml create mode 100644 kirara/latest/data.yml create mode 100644 kirara/latest/docker-compose.yml create mode 100644 new-api/README.md create mode 100644 new-api/data.yml create mode 100644 new-api/latest/data.yml create mode 100644 new-api/latest/docker-compose.yml create mode 100644 new-api/logo.png create mode 100644 one-hub/README.md create mode 100644 one-hub/data.yml create mode 100644 one-hub/latest/data.yml create mode 100644 one-hub/latest/docker-compose.yml create mode 100644 one-hub/logo.png diff --git a/kirara/README.md b/kirara/README.md new file mode 100644 index 000000000..571c73648 --- /dev/null +++ b/kirara/README.md @@ -0,0 +1,82 @@ +
+ +# Kirara AI Chatbot Framework + +[![GitHub stars](https://img.shields.io/github/stars/lss233/chatgpt-mirai-qq-bot?style=social)](https://github.com/lss233/chatgpt-mirai-qq-bot) + +
+ +## 概述 + +Kirara 是一个基于插件生态和工作流系统的 AI 聊天机器人框架,支持多种 AI 模型和即时通讯平台。 + +## 主要特性 + +- 支持多种 AI 模型:DeepSeek、Claude、Grok、OpenAI、Gemini、ChatGLM、Ollama +- 人设调教与虚拟女仆功能 +- 语音对话支持 +- 多平台支持:QQ、Telegram、Discord、微信等 +- 插件系统扩展 +- 工作流自定义 + +## 部署 + +### 使用 Docker Compose 部署(推荐) + +```yaml +version: "3.8" +services: + kirara-agent: + image: lss233/kirara-agent-framework:latest + container_name: kirara-agent + restart: always + volumes: + - ./data:/app/data + ports: + - "${PANEL_APP_PORT_HTTP}:8080" +``` + +启动命令: + +```bash +docker-compose up -d +``` + +### 直接使用 Docker 镜像 + +```bash +docker run -d \ + --name kirara-agent \ + --restart always \ + -v $(pwd)/data:/app/data \ + -p 8080:8080 \ + lss233/kirara-agent-framework:latest +``` + +## 配置 + +环境变量配置: + +| 变量名 | 描述 | 默认值 | +|--------|------|--------| +| PANEL_APP_PORT_HTTP | HTTP 服务端口 | 8080 | +| DATA_PATH | 数据存储路径 | /app/data | + +## 界面截图 + +(截图待添加) + +## 交流与支持 + +- GitHub Issues: [https://github.com/lss233/chatgpt-mirai-qq-bot/issues](https://github.com/lss233/chatgpt-mirai-qq-bot/issues) +- QQ 群: 123456789 +- Telegram 群: @kirara_chat + +## 相关项目 + +- [Mirai](https://github.com/mamoe/mirai): QQ 协议实现 +- [ChatGPT-Mirai](https://github.com/lss233/chatgpt-mirai-qq-bot): 项目基础 + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=lss233/chatgpt-mirai-qq-bot&type=Date)](https://star-history.com/#lss233/chatgpt-mirai-qq-bot&Date) diff --git a/kirara/data.yml b/kirara/data.yml new file mode 100644 index 000000000..1f4d98a44 --- /dev/null +++ b/kirara/data.yml @@ -0,0 +1,21 @@ +name: kirara +tags: +- AI / 大模型 +- 聊天机器人 +title: Kirara AI 聊天机器人框架 +description: Kirara AI 聊天机器人框架 +additionalProperties: + key: kirara + name: kirara + tags: + - AI + - Chatbot + shortDescZh: 插件生态 x 工作流系统,DIY 你自己的 AI 聊天机器人!支持DeepSeek、Claude、Grok、OpenAI、Gemini、ChatGLM、Ollama,人设调教,虚拟女仆、语音对话 | 支持 QQ、Telegram、Discord、微信 等平台 + shortDescEn: Plugin ecosystem x workflow system, DIY your own AI chatbot! Supports DeepSeek, Claude, Grok, OpenAI, Gemini, ChatGLM, Ollama, character customization, virtual maid, voice chat | Supports QQ, Telegram, Discord, WeChat and other platforms + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://kirara-docs.app.lss233.com/ + github: https://github.com/lss233/chatgpt-mirai-qq-bot/ + document: https://github.com/lss233/chatgpt-mirai-qq-bot/blob/master/README.md diff --git a/kirara/latest/data.yml b/kirara/latest/data.yml new file mode 100644 index 000000000..68c4eccc4 --- /dev/null +++ b/kirara/latest/data.yml @@ -0,0 +1,17 @@ +additionalProperties: + formFields: + - default: 48080 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + - default: ./data + edit: true + envKey: DATA_PATH + labelEn: Data folder path + labelZh: 数据文件夹路径 + required: true + type: text diff --git a/kirara/latest/docker-compose.yml b/kirara/latest/docker-compose.yml new file mode 100644 index 000000000..4b03c3363 --- /dev/null +++ b/kirara/latest/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.8" +services: + kirara-agent: + image: lss233/kirara-agent-framework:latest + container_name: ${CONTAINER_NAME} + restart: always + volumes: + - "${DATA_PATH}:/app/data" + ports: + - "${PANEL_APP_PORT_HTTP}:8080" + networks: + - 1panel-network + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/new-api/README.md b/new-api/README.md new file mode 100644 index 000000000..d571d3c9a --- /dev/null +++ b/new-api/README.md @@ -0,0 +1,157 @@ +
+ +![new-api](https://raw.githubusercontent.com/Calcium-Ion/new-api/refs/heads/main/web/public/logo.png) + +# New API + +Calcium-Ion%2Fnew-api | Trendshift + +
+ +> [!NOTE] +> 本项目为开源项目,在[One API](https://github.com/songquanpeng/one-api)的基础上进行二次开发 + +> [!IMPORTANT] +> 使用者必须在遵循 OpenAI 的[使用条款](https://openai.com/policies/terms-of-use)以及**法律法规**的情况下使用,不得用于非法用途。 +> 本项目仅供个人学习使用,不保证稳定性,且不提供任何技术支持。 +> 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。 + +> [!TIP] +> 最新版Docker镜像:`calciumion/new-api:latest` +> 默认账号root 密码123456 +> 更新指令: +> ``` +> docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR +> ``` + + +## 主要变更 +此分叉版本的主要变更如下: + +1. 全新的UI界面(部分界面还待更新) +2. 添加[Midjourney-Proxy(Plus)](https://github.com/novicezk/midjourney-proxy)接口的支持,[对接文档](Midjourney.md) +3. 支持在线充值功能,可在系统设置中设置,当前支持的支付接口: + + [x] 易支付 +4. 支持用key查询使用额度: + + 配合项目[neko-api-key-tool](https://github.com/Calcium-Ion/neko-api-key-tool)可实现用key查询使用 +5. 渠道显示已使用额度,支持指定组织访问 +6. 分页支持选择每页显示数量 +7. 兼容原版One API的数据库,可直接使用原版数据库(one-api.db) +8. 支持模型按次数收费,可在 系统设置-运营设置 中设置 +9. 支持渠道**加权随机** +10. 数据看板 +11. 可设置令牌能调用的模型 +12. 支持Telegram授权登录。 + 1. 系统设置-配置登录注册-允许通过Telegram登录 + 2. 对[@Botfather](https://t.me/botfather)输入指令/setdomain + 3. 选择你的bot,然后输入http(s)://你的网站地址/login + 4. Telegram Bot 名称是bot username 去掉@后的字符串 +13. 添加 [Suno API](https://github.com/Suno-API/Suno-API)接口的支持,[对接文档](Suno.md) +14. 支持Rerank模型,目前仅兼容Cohere和Jina,可接入Dify,[对接文档](Rerank.md) +15. **[OpenAI Realtime API](https://platform.openai.com/docs/guides/realtime/integration)** - 支持OpenAI的Realtime API,支持Azure渠道。 + +## 模型支持 +此版本额外支持以下模型: +1. 第三方模型 **gps** (gpt-4-gizmo-*) +2. 智谱glm-4v,glm-4v识图 +3. Anthropic Claude 3 +4. [Ollama](https://github.com/ollama/ollama?tab=readme-ov-file),添加渠道时,密钥可以随便填写,默认的请求地址是[http://localhost:11434](http://localhost:11434),如果需要修改请在渠道中修改 +5. [Midjourney-Proxy(Plus)](https://github.com/novicezk/midjourney-proxy)接口,[对接文档](Midjourney.md) +6. [零一万物](https://platform.lingyiwanwu.com/) +7. 自定义渠道,支持填入完整调用地址 +8. [Suno API](https://github.com/Suno-API/Suno-API) 接口,[对接文档](Suno.md) +9. Rerank模型,目前支持[Cohere](https://cohere.ai/)和[Jina](https://jina.ai/),[对接文档](Rerank.md) +10. Dify +11. Vertex AI,目前兼容Claude,Gemini,Llama3.1 + +您可以在渠道中添加自定义模型gpt-4-gizmo-*,此模型并非OpenAI官方模型,而是第三方模型,使用官方key无法调用。 + +## 比原版One API多出的配置 +- `GENERATE_DEFAULT_TOKEN`:是否为新注册用户生成初始令牌,默认为 `false`。 +- `STREAMING_TIMEOUT`:设置流式一次回复的超时时间,默认为 60 秒。 +- `DIFY_DEBUG`:设置 Dify 渠道是否输出工作流和节点信息到客户端,默认为 `true`。 +- `FORCE_STREAM_OPTION`:是否覆盖客户端stream_options参数,请求上游返回流模式usage,默认为 `true`,建议开启,不影响客户端传入stream_options参数返回结果。 +- `GET_MEDIA_TOKEN`:是否统计图片token,默认为 `true`,关闭后将不再在本地计算图片token,可能会导致和上游计费不同,此项覆盖 `GET_MEDIA_TOKEN_NOT_STREAM` 选项作用。 +- `GET_MEDIA_TOKEN_NOT_STREAM`:是否在非流(`stream=false`)情况下统计图片token,默认为 `true`。 +- `UPDATE_TASK`:是否更新异步任务(Midjourney、Suno),默认为 `true`,关闭后将不会更新任务进度。 +- `GEMINI_MODEL_MAP`:Gemini模型指定版本(v1/v1beta),使用“模型:版本”指定,","分隔,例如:-e GEMINI_MODEL_MAP="gemini-1.5-pro-latest:v1beta,gemini-1.5-pro-001:v1beta",为空则使用默认配置(v1beta) +- `COHERE_SAFETY_SETTING`:Cohere模型[安全设置](https://docs.cohere.com/docs/safety-modes#overview),可选值为 `NONE`, `CONTEXTUAL`,`STRICT`,默认为 `NONE`。 +## 部署 +### 部署要求 +- 本地数据库(默认):SQLite(Docker 部署默认使用 SQLite,必须挂载 `/data` 目录到宿主机) +- 远程数据库:MySQL 版本 >= 5.7.8,PgSQL 版本 >= 9.6 + +### 使用宝塔面板Docker功能部署 +安装宝塔面板 (**9.2.0版本**及以上),前往 [宝塔面板](https://www.bt.cn/new/download.html) 官网,选择正式版的脚本下载安装 +安装后登录宝塔面板,在菜单栏中点击 Docker ,首次进入会提示安装 Docker 服务,点击立即安装,按提示完成安装 +安装完成后在应用商店中找到 **New-API** ,点击安装,配置基本选项 即可完成安装 +[图文教程](BT.md) + +### 基于 Docker 进行部署 +### 使用 Docker Compose 部署(推荐) +```shell +# 下载项目 +git clone https://github.com/Calcium-Ion/new-api.git +cd new-api +# 按需编辑 docker-compose.yml +# 启动 +docker-compose up -d +``` + +### 直接使用 Docker 镜像 +```shell +# 使用 SQLite 的部署命令: +docker run --name new-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest +# 使用 MySQL 的部署命令,在上面的基础上添加 `-e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"`,请自行修改数据库连接参数。 +# 例如: +docker run --name new-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/new-api:/data calciumion/new-api:latest +``` + +## 渠道重试 +渠道重试功能已经实现,可以在`设置->运营设置->通用设置`设置重试次数,**建议开启缓存**功能。 +如果开启了重试功能,第一次重试使用同优先级,第二次重试使用下一个优先级,以此类推。 +### 缓存设置方法 +1. `REDIS_CONN_STRING`:设置之后将使用 Redis 作为缓存使用。 + + 例子:`REDIS_CONN_STRING=redis://default:redispw@localhost:49153` +2. `MEMORY_CACHE_ENABLED`:启用内存缓存(如果设置了`REDIS_CONN_STRING`,则无需手动设置),会导致用户额度的更新存在一定的延迟,可选值为 `true` 和 `false`,未设置则默认为 `false`。 + + 例子:`MEMORY_CACHE_ENABLED=true` +### 为什么有的时候没有重试 +这些错误码不会重试:400,504,524 +### 我想让400也重试 +在`渠道->编辑`中,将`状态码复写`改为 +```json +{ + "400": "500" +} +``` +可以实现400错误转为500错误,从而重试 + +## Midjourney接口设置文档 +[对接文档](Midjourney.md) + +## Suno接口设置文档 +[对接文档](Suno.md) + +## 界面截图 +![796df8d287b7b7bd7853b2497e7df511](https://github.com/user-attachments/assets/255b5e97-2d3a-4434-b4fa-e922ad88ff5a) + +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/ad0e7aae-0203-471c-9716-2d83768927d4) +![image](https://github.com/user-attachments/assets/29f81de5-33fc-4fc5-a5ff-f9b54b653c7c) + +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/3ca0b282-00ff-4c96-bf9d-e29ef615c605) +夜间模式 +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/1c66b593-bb9e-4757-9720-ff2759539242) +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/af9a07ee-5101-4b3d-8bd9-ae21a4fd7e9e) + +## 交流群 + + +## 相关项目 +- [One API](https://github.com/songquanpeng/one-api):原版项目 +- [Midjourney-Proxy](https://github.com/novicezk/midjourney-proxy):Midjourney接口支持 +- [chatnio](https://github.com/Deeptrain-Community/chatnio):下一代 AI 一站式 B/C 端解决方案 +- [neko-api-key-tool](https://github.com/Calcium-Ion/neko-api-key-tool):用key查询使用额度 + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=Calcium-Ion/new-api&type=Date)](https://star-history.com/#Calcium-Ion/new-api&Date) \ No newline at end of file diff --git a/new-api/data.yml b/new-api/data.yml new file mode 100644 index 000000000..462e0d59f --- /dev/null +++ b/new-api/data.yml @@ -0,0 +1,19 @@ +name: new api +tags: + - AI / 大模型 +title: OpenAI 接口管理 & 分发系统 +description: OpenAI 接口管理 & 分发系统 +additionalProperties: + key: new-api + name: new api + tags: + - AI + shortDescZh: AI模型接口管理与分发系统,支持将多种大模型转为OpenAI格式调用、支持Midjourney Proxy、Suno、Rerank,兼容易支付协议,可供个人或者企业内部管理与分发渠道使用,本项目基于One API二次开发。 + shortDescEn: Access all LLM through the standard OpenAI API format, easy to deploy & use + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://nekoapi.com/ + github: https://github.com/Calcium-Ion/new-api + document: https://github.com/Calcium-Ion/new-api/blob/main/README.md diff --git a/new-api/latest/data.yml b/new-api/latest/data.yml new file mode 100644 index 000000000..2c2c3e0e0 --- /dev/null +++ b/new-api/latest/data.yml @@ -0,0 +1,52 @@ +additionalProperties: + formFields: + - default: "" + edit: true + envKey: PANEL_DB_HOST + key: mysql + labelEn: Database Service + labelZh: 数据库服务 + required: true + type: service + - default: newapi + edit: true + envKey: PANEL_DB_NAME + labelEn: Database + labelZh: 数据库名 + random: true + required: true + rule: paramCommon + type: text + - default: newapi + edit: true + envKey: PANEL_DB_USER + labelEn: User + labelZh: 数据库用户 + random: true + required: true + rule: paramCommon + type: text + - default: newapi + edit: true + envKey: PANEL_DB_USER_PASSWORD + labelEn: Password + labelZh: 数据库用户密码 + random: true + required: true + rule: paramComplexity + type: password + - default: 3000 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + - default: Asia/Shanghai + edit: true + envKey: TZ + labelEn: Time Zone + labelZh: 时区 + required: true + type: text diff --git a/new-api/latest/docker-compose.yml b/new-api/latest/docker-compose.yml new file mode 100644 index 000000000..1e361775b --- /dev/null +++ b/new-api/latest/docker-compose.yml @@ -0,0 +1,26 @@ +services: + one-api: + image: calciumion/new-api:latest + container_name: ${CONTAINER_NAME} + restart: always + ports: + - ${PANEL_APP_PORT_HTTP}:3000 + networks: + - 1panel-network + command: --log-dir /app/logs + volumes: + - ./data:/data + - ./logs:/app/logs + environment: + - SQL_DSN=${PANEL_DB_USER}:${PANEL_DB_USER_PASSWORD}@tcp(${PANEL_DB_HOST}:3306)/${PANEL_DB_NAME} # 修改此行,或注释掉以使用 SQLite 作为数据库 + - TZ=${TZ} +# - SESSION_SECRET=${SESSION_SECRET} +# - REDIS_CONN_STRING=redis://redis +# - NODE_TYPE=slave # 多机部署时从节点取消注释该行 +# - SYNC_FREQUENCY=60 # 需要定期从数据库加载数据时取消注释该行 +# - FRONTEND_BASE_URL=https://openai.justsong.cn # 多机部署时从节点取消注释该行 + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/new-api/logo.png b/new-api/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8aea273d4c9cf94636ddc350337516501c6e2e89 GIT binary patch literal 7749 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 LNkvXXu0mjfIs7~s literal 0 HcmV?d00001 diff --git a/one-hub/README.md b/one-hub/README.md new file mode 100644 index 000000000..ff0f0f1f2 --- /dev/null +++ b/one-hub/README.md @@ -0,0 +1,131 @@ +

+ 中文 | English +

+ +

+ + + + +

+ +
+ +# One Hub + +_本项目是基于[one-api](https://github.com/songquanpeng/one-api)二次开发而来的_ + +

+ + license + + + release + + + docker + + + docker + + + GoReportCard + +

+ +**请不要和原版混用,因为新增功能,数据库与原版不兼容** + +**为了更加简洁,本项目之后,除了新增供应商时会更新程序自带的模型列表,平常不再更新程序自带的模型列表。** + +**如果发现缺少新模型,请在`后台-模型价格-更新价格`中更新新增的模型** + +[演示网站](https://one-api-martialbe.vercel.app/) + +
+ +> [!WARNING] +> 本项目为个人学习使用,不保证稳定性,且不提供任何技术支持,使用者必须在遵循 OpenAI 的使用条款以及法律法规的情况下使用,不得用于非法用途。 +> 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。 + +## 功能变化 + +- 全新的 UI 界面 +- 新增用户仪表盘 +- 新增管理员分析数据统计界面 +- 重构了中转`供应商`模块 +- 支持使用`Azure Speech`模拟`TTS`功能 +- 渠道可配置单独的 http/socks5 代理 +- 支持动态返回用户模型列表 +- 支持自定义测速模型 +- 日志增加请求耗时 +- 支持和优化非 OpenAI 模型的函数调用(支持的模型可以在 lobe-chat 直接使用) +- 支持完成倍率自定义 +- 支持完整的分页和排序 +- 支持`Telegram bot` +- 支持模型按次收费 +- 支持模型通配符 +- 支持使用配置文件启动程序 +- 支持模型价格更新 +- 支持自动获取供应商模型 +- 支持仅聊天,开启后如果有传入`function call`参数会跳过该渠道 +- 支持支付 +- 支持配置用户组 RPM +- 支持`Prometheus`监控 + +## 文档 + +请查看[文档](https://github.com/MartialBE/one-hub/wiki) + +## 当前支持的供应商 + +| 供应商 | Chat | Embeddings | Audio | Images | 其他 | +| --------------------------------------------------------------------- | ------------------------ | ---------- | ------ | ----------- | ---------------------------------------------------------------- | +| [OpenAI](https://platform.openai.com/docs/api-reference/introduction) | ✅ | ✅ | ✅ | ✅ | - | +| [Azure OpenAI](https://oai.azure.com/) | ✅ | ✅ | ✅ | ✅ | - | +| [Azure Speech](https://portal.azure.com/) | - | - | ⚠️ tts | - | - | +| [Anthropic](https://www.anthropic.com/) | ✅ | - | - | - | - | +| [Gemini](https://aistudio.google.com/) | ✅ | - | - | - | - | +| [百度文心](https://console.bce.baidu.com/qianfan/overview) | ✅ | ✅ | - | - | - | +| [通义千问](https://dashscope.console.aliyun.com/overview) | ✅ | ✅ | - | - | - | +| [讯飞星火](https://console.xfyun.cn/) | ✅ | - | - | - | - | +| [智谱](https://open.bigmodel.cn/overview) | ✅ | ✅ | - | ⚠️ 图片生成 | - | +| [腾讯混元](https://cloud.tencent.com/product/hunyuan) | ✅ | - | - | - | - | +| [百川](https://platform.baichuan-ai.com/console/apikey) | ✅ | ✅ | - | - | - | +| [MiniMax](https://www.minimaxi.com/user-center/basic-information) | ✅ | ✅ | - | - | - | +| [Deepseek](https://platform.deepseek.com/usage) | ✅ | - | - | - | - | +| [Moonshot](https://moonshot.ai/) | ✅ | - | - | - | - | +| [Mistral](https://mistral.ai/) | ✅ | ✅ | - | - | - | +| [Groq](https://console.groq.com/keys) | ✅ | - | - | - | - | +| [Amazon Bedrock](https://console.aws.amazon.com/bedrock/home) | ⚠️ 仅支持 Anthropic 模型 | - | - | - | - | +| [零一万物](https://platform.lingyiwanwu.com/details) | ✅ | - | - | - | - | +| [Cloudflare AI](https://ai.cloudflare.com/) | ✅ | - | ⚠️ stt | ⚠️ 图片生成 | - | +| [Midjourney](https://www.midjourney.com/) | - | - | - | - | [midjourney-proxy](https://github.com/novicezk/midjourney-proxy) | +| [Cohere](https://cohere.com/) | ✅ | - | - | - | - | +| [Stability AI](https://platform.stability.ai/account/credits) | - | - | - | ⚠️ 图片生成 | - | +| [Coze](https://www.coze.com/open/docs/chat?_lang=zh) | ✅ | - | - | - | - | +| [Ollama](https://github.com/ollama/ollama) | ✅ | ✅ | - | - | - | +| [Suno](https://suno.com/) | - | - | - | - | [Suno-API](https://github.com/Suno-API/Suno-API) | + +## 感谢 + +- 本程序使用了以下开源项目 + - [one-api](https://github.com/songquanpeng/one-api)为本项目的基础 + - [Berry Free React Admin Template](https://github.com/codedthemes/berry-free-react-admin-template)为本项目的前端界面 + - [minimal-ui-kit](https://github.com/minimal-ui-kit/material-kit-react),使用了其中的部分样式 + - [new api](https://github.com/Calcium-Ion/new-api),Midjourney/Suno 模块的代码来源于此 + - [go-zero](https://github.com/zeromicro/go-zero) - Token 限流器的实现 + +感谢以上项目的作者和贡献者 + +## 交流群 + + + +## 其他 + + + + + Star History of MartialBE/one-api + + \ No newline at end of file diff --git a/one-hub/data.yml b/one-hub/data.yml new file mode 100644 index 000000000..ce1a9c98e --- /dev/null +++ b/one-hub/data.yml @@ -0,0 +1,19 @@ +name: one hub +tags: + - AI / 大模型 +title: OpenAI 接口管理 & 分发系统 +description: OpenAI 接口管理 & 分发系统 +additionalProperties: + key: one-hub + name: one-hub + tags: + - AI + shortDescZh: AI模型接口管理与分发系统,支持将多种大模型转为OpenAI格式调用、支持Midjourney Proxy、Suno、Rerank,兼容易支付协议,可供个人或者企业内部管理与分发渠道使用,本项目基于One API二次开发。 + shortDescEn: Access all LLM through the standard OpenAI API format, easy to deploy & use + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://one-hub.xiao5.info/ + github: https://github.com/MartialBE/one-hub + document: https://github.com/MartialBE/one-hub/blob/main/README.md diff --git a/one-hub/latest/data.yml b/one-hub/latest/data.yml new file mode 100644 index 000000000..6394e946c --- /dev/null +++ b/one-hub/latest/data.yml @@ -0,0 +1,56 @@ +additionalProperties: + formFields: + - default: "" + envKey: PANEL_DB_HOST + key: mysql + labelEn: Database Service + labelZh: 数据库服务 + required: true + type: service + - default: onehub + envKey: PANEL_DB_NAME + labelEn: Database + labelZh: 数据库名 + random: true + required: true + rule: paramCommon + type: text + - default: onehub + envKey: PANEL_DB_USER + labelEn: User + labelZh: 数据库用户 + random: true + required: true + rule: paramCommon + type: text + - default: onehub + envKey: PANEL_DB_USER_PASSWORD + labelEn: Password + labelZh: 数据库用户密码 + random: true + required: true + rule: paramComplexity + type: password + - default: 4000 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + - default: Asia/Shanghai + edit: true + envKey: TZ + labelEn: Time Zone + labelZh: 时区 + required: true + type: text + - default: onehub + envKey: USER_TOKEN_SECRET + labelEn: USER_TOKEN_SECRET + labelZh: SECRET随机字符串 + random: true + required: true + rule: paramComplexity + type: password \ No newline at end of file diff --git a/one-hub/latest/docker-compose.yml b/one-hub/latest/docker-compose.yml new file mode 100644 index 000000000..bf43b29a7 --- /dev/null +++ b/one-hub/latest/docker-compose.yml @@ -0,0 +1,28 @@ +services: + one-hub: + image: ghcr.io/martialbe/one-api:latest + container_name: ${CONTAINER_NAME} + restart: always + ports: + - ${PANEL_APP_PORT_HTTP}:3000 + networks: + - 1panel-network + command: --log-dir /app/logs + volumes: + - ./data:/data + - ./logs:/app/logs + environment: + - SQL_DSN=${PANEL_DB_USER}:${PANEL_DB_USER_PASSWORD}@tcp(${PANEL_DB_HOST}:3306)/${PANEL_DB_NAME} # 修改此行,或注释掉以使用 SQLite 作为数据库 + - TZ=${TZ} + - USER_TOKEN_SECRET=${USER_TOKEN_SECRET} # 必填,否则无法启动,修改为随机字符串,32位以上 + # - REDIS_CONN_STRING=redis://redis + # - SESSION_SECRET=random_string # 推荐填写,否则每次重启后已登录用户的 cookie 将失效。 + # - HASHIDS_SALT=random_string # 可空,建议设置,字符串元素不能重复 + # - NODE_TYPE=slave # 多机部署时从节点取消注释该行 + # - SYNC_FREQUENCY=60 # 需要定期从数据库加载数据时取消注释该行 + # - FRONTEND_BASE_URL=https://openai.justsong.cn # 多机部署时从节点取消注释该行 + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/one-hub/logo.png b/one-hub/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..da6602d6b6499ea9856e1e240fba957119342e07 GIT binary patch literal 18577 zcmd>lgrAU*KKH z@6)J=*a#?S4n7b%_*^}Q>ihrwsmSt7HR2RtXqT{3cBXx==u{vjp#xDmyM&CLooA)2 z+0V@o$Y`&-TVG7)^6Q_xmc{)i=h#v!F3Qq%ol9otMgup-#T!;CaI)&uo?4WZ2)=XOvzDCw zGZPPW?fWt&ER;CFD4Az-3}pTQh^JFfUdf5DS$-%NkB4Kqz-P9v?TP=bDZpk#Xg^_M zlxZ)|F6WM0y>4xLArag}d2s%BmCJ3!Jq`aqBD);59Pe7aI7<7*Q|D`Y~a6E#nBzB9AY!*;kdI;uUCp8TMVO<>Zpd`uicKmSm!qXy?(^O+7yn9%h2CxC!taKmLw0L}+} z0jIxvV3dNzIFcy8_}8>!>DnzT0ku`=TV-Uv6}-03BRy@RBt4~!mwt+B4rL0O6CrZUk# ziXZ&y&Bpql`P7uxx4mM)Z>VQWPsL~%{===^BCq+Z9NwhnnbzKS^vO}UNbEb4-hXm2 zc$6n^Or#oAxzFLYhsoqWHsZ}w zmlyeVIU8N7%Rhb~)qu7}9U?EwaQ-!BN-Gf1$Jpl$t!#Tq<9skE_WDnn6=FfVVg;#& zq=Irx83#Uzxp-8a3vg3U>v)>32%#WIrGG)ET zKNTE2a(Q}wn7aN$ptNOM$m?O6b*1{?IsI=8#AybB)P$F3yNZ3@zKCm{D$Z?S#J_IT zEnzTgvk_$EF1{O&I2e|8^TAQlP$67}|LCCk*{i75#9%jeaQ5)&Q0f>WpOi! zdZbxA1+Ai<9?Vhw#M$gtFn<(OE60ou2%R@{UOdt9*|1gqk!7K}^(%p{?Cs1jY?Q(~ zl~RdSjhQ+|fJlLY!)JyGgdYz-&A>?Dgu7(kKQNZNX^o>SjSHgG?aIyI{d+$2f&Bh~OV>eTuz(%)>7Cxiygy-BBfJXaLDmLqF|xmxW)P#Zran z@}tbuZ{U9@M8cJ=Tk)l*Qk3?+)F-q!ZUtAxJDVOciBaki%~SXew+(Mg$wgw;Vm8R* z9CMdtv9Y--lJQ5!t8}%UnEt#at6vhQCw0hwj!XEj#|vCxl)+K>JTGHzWRJlN%kP<~ zpd&kBvb_>7Ypw}STm$0Wt*$>DHN}7DS=+Yp54z1{GDWE?5o|XjxAHP1)$6&PJdZ8a zfolkw;S(_Tlv9wd-+k^=XI%4!L4;)%-b~xQloBiR=`{mR;i~&dxPX( zZ+U-61=1t|08aC`-9kPJ|0X5JPLC1z+Z^QVfHp0oQp6e4-8aS$ixEFOiJwP#lcL!| zM@45-Y@#Bk);IUNl!v}yg2ZioM|f$J0KoH4H#}ml#%6~nSJsLyM#bFiCZ96CKW)oo zX$v`DL#k2#Slhlr?=~k!(c%snU&Dx=-FgqQNkUQPtbgMHpp4<&kGT@!avcFHE+a@dy<1O`s!rppTfuD79~}Sr;|P?i zN6#tGuy>T)z_A8kB?r5nL>9&Pu8&(Dvg`4vpV+kZIcD2Qjc5|1g4xxxpk|1=V1mdA zoPdBYiO|^COKJTvQhxXKRllvZ$NB(VLT`a%I4Vd)?efFaz%33Mz~c4f^#R3xTMdID z-KZ3G2|A6;Y*yar4WnyFiYi=R=|+%!W7FBFw5W{GP1h&vdq_)y>EpaDXgv&%c#8zY6* zyOi{w6KXwE^K281Bz=yWx=^{J&jjwEGv&~0MM|V|UhB0|i!3TeT?nFRV3yw^Z3+i% zKATC#p?ZI9d`QGnMBYG0aZ~|b$~c(iL0Rx9KJwIs$f58UW`Q@R8l~!KL?eZRT7lP8 z4(=D+lUr+YP0~rY-k}hrm_sE>Fuj6c_nswXR)U3lq)pu>Oh~Q0co>z&C2_!Qw)~?k zmzH|yS)VdXs>u-LawtsvlO!xd*lwbPK1YfROB&FHBu=8p2{Pr_Y4`vnmIRT+m8-@E zb4ttMb4jT2M2A@}Wh8O~WUvhgjZkh9&@OYZBby9HjbdQYC2LU>n;m5bq3c{zYj+?# z&oFpzdCqu)t{!}os;QL9zFIqf#qNf98u zDwq@Xr%03{e`T2c%0m{;I@Ao=-*<08xfg)C_4=}n>yI~vbkWw-i!-i6_J*i`K~mbt zGQPqVOU($~V&PW_sMPSQr2`h?J#KkYjt!q+Pk06@nfe+G=POxV=SsySQhb%2o0xR- zxd<5@f4DcRcAx)Q{$IK!$t437Fm=uAv?asT&cuUF0`_KS633FJ7iJu2+;{}VEfrV% z4+t*Xs`>WY=#Zp}vT-Ato|hzdpV&iqrdKZVg5}||cR`nm)wsOv3-I$Z**w##GfK}( zjKhEF>hlSKDQ7dgtW}$cS4o{m&)IKn<_iuQCL=~#BHwSASi@qN!tQ>jN$5v9(@kGG*8Jut-?h1Fi5rRFg9ZhLpWDfu^K?~aR ztaEzzFjM_b;(KBk6ba}vv&;9_ad}6HCky+Z9ILrRek!j#$fDvv6n%-`hZ#F?t}9%b zjA*tYkCVnW0(-2m1zNT$G#ol|$821EAw8dF3mhCD82shyA7nY-eyP%MxH;EgyHxID ztqYl>`9hKQ=au9gMZDYLWc-V9+otc9b$vOT8X7f}BeN6KXks&PzRb;Pu>55=@Vwye z`OV{8NUkcFLV+k9io0L?!J^>_NB=|>zq(sjx(g0BJ>N`W*A4e#r*2i;pVHczKEjoH zYDSm0By;D6DiRV5472Bym4bqg$&;CA{iFczgl+4jQ$4)}tzOuBIji!oppswPT$)Iy zN-IW5UP=Xb!pj0V(*l(nZs`8Oc2AX;l13~U%~;tf1g5r&PSfyX^S-6T%!CY3ee;1}3If@>d~R za98C%4J)vgwKrGx32hNbx0oicOqs!plx=ZZZIbBt+-q~F@JOFBY2fI#?k$q-Ry_J< zDQJwbsK^S9>}Bg`UQY3p2>R*RK4T^_}~pC-Dj?c4^ygzvjE&?ec*v@-ZI9yUoy z76yY#ZQ?tB5PE518?I(A1xhT=xK(a+>1j&5;6WcgIL0f(u6+F=wT5Lec<{;qj$wd)nTPFrY@;=PGGX)c86g}_kf1{=SRc|XIWo&=vA}ueM6+9M_ppo z4A-2U8w*s=iQ3wQNbU0tPBSKS4b9zOCLQdLRC8Fm=@;iyh0z&b?>qX-5JOU*!yJty z?1dU};ShgbWDh#mC7uW#oC@K7lMu+I_P#5DasRRC;z&CHN$+AsP}(WUveES^!g>2YEM1F%1e}&f#A~+L&2Z>`BgB;lcv-gSqd|(O)*HPB98s?Xt5? zVCiSNi0aR80gZ~ORPw9!^m6niNNU&BvY|)01yFKYZPR=!lJy5%h zJ<+d~<(d^%oYI%1tf__{$c6(G*C=~~jW&C@)RUxJo^ZlC0K!i*t^Nodr%o&|9|)!! zwjJS+kiatEZIi8MElWs(9}R8eA5_SJib75m-g|-oy=VDUcE%5~rXEq^soTkvUa`Q< z70cF|lV-dChrJz?>;8kq68@IO=~Q9QD~uOHL@y~Z->boSrSH?m&XY&n&A33@UPtJX zw3v(mbG%Mw!3u^8?MF_`PBKt`QP2|ds^8qfBg!su%gZ1XCU5wIE;CO9 zC9dA}WS39P^z$i|V=M7$+*Rgoe+${yeH72>oGc8o(-mM~;XZo|1BVgU=ynFnD|WFz z^TK{?nHtd)q}RiWe@mv=tST6EsXrZV952tg%+P(8TM>A3>6Rz(Vf4GFc%-BE;Owe& z!s7R?_(O$|v5e(DNp7J8f4cC}(W|MW)925@&1x;5zWP}tPMon(&%OsPOa-9ZyAcn7 zq+(}8nU8eHT|!(H4c{)vhVf zFKTN=+~MUZP1AD6@qMamofBcrhbBEJlVMQMt02s9gycNc3ypzfCWoqZM7KH@337*T%2pXk2LJf}i^Rr6kRYdlFj*fYm?hNh$iahr#E-r%S_b=^QWZmsBi zrl%YH4CJ~(N)C+9m5R-%i-f(a`{vIhSnGo}Ze*Dab@ZllUDJ`aKUA$18FI8Xdx}&1 zjiK8ychJ{$q5P;-P!aU}%cleq4;RwbA5>-H}=7}qb#(eGZuQ|}Up zxB(etc8B!*5$N8FOpuzOCthtvH_St?Z3Rbx zW9vlIc+#>E-?7-{*P_k0*s|Tzx@EvYgeI>{5lp*1?DPuqEmj#}GMit@Ko{?{}7-0~$c^_ltjrrlw( zg->0jRwx6Y+2@kfojW-X-TcOUqAU982L0??BRAYLJ_;NLTF{ca9X$O~?z?6lJvYys|ZMz|0+&n!BHeZ-WBbaoo6b4zBW}p=P2_0k1*1 zGffMV9&9N%0!-vT>1wl3K1uQQnCC=o-Zuju|b<(xLF z={U%M#+BH|!3&_EalO|&?B)ad6&9VY%HFsk@f~&~5Tc>ho$A{LgTJ<4=>Gb5&6F^) zlEj#SJS_IjOurfsILQy{|4a;y-P3p_u;Y(X^^nD(34v6x;R~#B1=C`7!pD~8oOjPC zcB)<^)qHXIXBG`4ETO%yB$!ZE!*}xik;i`}R{J<)#U%k>w5P z+YcrYwoOrK8kjrJf=s3`?>xiDcN*5~1ari!SnKxL0N3usENchE_J-reZ*Q{nZ>dlN z2vDn}VCZw!xjtZtd7LSI)LIg6u+Of_98@}jyhRXCz-`L6>|kL5ytF!(Uw*3dw%sZ9 zKC$@o)JIxw!W+Dp>ihod)t{1Q7J09?&FjlJUxyqW5Rb3)IYigp4JK7C8t@Rg;V_BF za13}PbGO~-w~>U|HKD;))M#h7>vyMiyCrR#Molyte|wUzb8aGIP}{Q(p1j5E_f%~!4l3}Q(;6%8uUc&KI${e>7RwSFoeK--P9e1RR#RKQ%eE03 z)Cxt#>Gmy}LP<<_DBcFFxT5GrZEvI=6hQ>yWp@ z=Jty(OB2|F4O1dr>&JYZ2%2bhrEuS2bt~z*e`yNUSp=6u@=7V*Q~vhjQL}k6qC`AM zD-^x0CAD2wf@fWOx1y#mu6xbx{E3oRJvZ!k<)DCVoZG(<>hKJ?I@zx>sL9qvF@>wA z?ctj`FJiaCjLDiETT5Zgb~-$Qjgact47LPtM&=<+SGqYZ`wP6E6-!cAWQpK~?^BWS zn%`-lhgFs)c#Pb+PD2n{Z(@x>u2rv3JgS~Yizl9?6(e2DdWo}Q&N`MGx6!RNUZhu~ z=^Q>fIJDrFFTil6)B9LK^~T(tyAb8OCw%634J-r#(m@S)v3a(lYp9KZ!AF_xY7hRF z$~@s8woY+<+-*DhSJdk2ZL;G@H!6WgWnL2ZX)bwH`d9Z5SXNbT2c`Q?mHdEw#S0%& zTzm8}GjiaZtO|}E&g#ixlTmQOI`KyHtrGv<&m7d-r%O=uCb()aBza0!V2QB)r>`rG zuZ#g?s@8+f#cRARb|pvc8rlLkO*^6pW&40T^0)~=lrm)I4)U{G?Uzvju@kN%zy9` zoGr`gJ(xaB%(gWNRfJuP5{a}q`z3{UP~Sw?bjiD3XH1S{DkoIaRb908(k9FYnDF;j zsNH^*s~}=|RR4VJ(Z`G0<{S{4UZ;K|3fr^zT36_9k%zI{zj$8GD(Gz?<5oPg%XPOvNuqDYLk63q zrEOyCI;2L=`Q$UUJubwpSb7d0d{_lj4gNSvP&4*KzH%`J?n!r5Q~@pNbe-~wnb{|` zOi3>#C3C?$Og=pLgeMPs-?C}4%4<2i{{ZiJ^^V&Yd&r+S)J+&>bEo+%!zx8VA41&})r`T@p;9EhM&G zn|>UquHSWrHIbw2>7cmqAqmG%0{@v%jqoBZagGCN*Y5Qo_J|Y<4SWt!9 zbam|mUTm#cCNH9e2E{jd&6^H zPY9V91ParqivczE>|$AZ@R1nwoyDv^__{I2o&Mjlnj{94E2cnt&bu|=d(jcQ&LakY zB3LpiOIUjMSXDZXI9_JlEDyYrM6a+bl(I*+r{0%+hqXunrOva>E01-`vl=hhsYSr$ z^~I|bkU{Cqoh;qa7XfmIoC5vilIVx{Fv~WZFC7%nix79x zLB#1WSvom1^LGwknnZLADSe}l?~q{~HIs|u{z=iq#COJpaPFoZxh+bL2|zzcs7!Qm z;qm#zl*uA;GkY2Lqio!CX)W4H5&?|XweHiqSR54DV>95}pN_XAi7sVsoU8h2yttzlMI^LPW zD&OQ6+?hXA8E2Ngop``b1?2a(m~$`BQK)c#K*JjGQ)kI?e2kMpT;W4fJ@1JZmhc_S zVNR~&oW%pnwT-b%LF9I5cdfnYAwS$x~!J-rR zoB^K(g(q+y2UEy_u2%25)VyKLU#_4?1z&fc7}Bi2J=uM&dk4Uz zE3D{$Q~Xy9|HQeSSizC}EsNPVrpVS~UUl1Z51rueWksl$>SZ%u`6^73ZS_vyVIRCF z>UmJ@Ye?+|L}Ug%iR-7kqO)h&?s+9}?9V*l2w@9KE+IFv$V&nrizrEsoPQOqF!*kZ zCu5~j@9`bCcX9x=U+K5E4J&eIih_Jf!^#nO7hA*tUO9{TzvD|EV| zoAh-Gynt*Q{Pz!!It@I#!#NtnvmX%p$>I;FK|0!O2>0 zvEtviTraEO;_cKLeDtMPEFSkLrx4{&k`exbNhD?5mO9_WKMS{4DJLrf7Xi#*&|{hW z`Vd#*^GzSI`_j-C4{H5tp*wgRo2GQ{yb5F1` ztQ1BNo86I0q?+8)0#ufTp6c}X2;+S(`&`T?dA6H!AcSwjf6qaC8l`Q&xOeN3=VG;O z5U9(8;Oq2y3P~;IRd*Wzt=i_b^}lnkx z20HBZbz-gKK~HO__wTY4SSBYzx2{(SW8JD>?N3B^$XK6^5H2P(=x8^E+>z4qogQh>Du_EGWUde!(LwZ~_#p_AG91KGv-`HI zfWdy8tCK$cp^tW&@H(b+hgVnHNmS-)J9eA*Q`dJ{_mPYfrj^vV+Q91F?FL4k$RJ;T zk6(5_PKutZ5TSFLruljj!?nFBfo9|Nqe#x5v*HFcR&sWZEST6rFZBYkNG7?bpVhkh z{C$FLTo*3&tNU;6?GA^JRo@i_^bIXJ5TiZ4VQ1NoS;Ev8T&jqi5WwGQ4L?I0cA$If zK-#5_fo||@t0~ob)4CGXCkzhUj)cB$aqShLmrpU?? z^3CB%+w<_KnkMxKx8uRs8Wt@sWfSF^@Cu^e1+mBLWK9&lGB_jd#0KedbCw*Jg$#h0uBJ+7^js&&YuEB>jT_63B>GkQjwf~u;li-s+m zcOF|JrLWl+Nv6WV9-*i}c$lLgRCWIhk8Zf#Qa2g>YSG94q&&ariGFMJ=k_V` zj7MYQ-dvqMI)=wWRGik?d_!GG#yOpt58eUxqWo}?9P^j70*)3Y`Q5HZF$1KEqE@z@ zNe)&?+$+qEh5_GnJl7hu_AF^^SIML9N_7k}F(t5gX`BCW6FQFx3-yE+1jix|rRH4f z{TtW3mU1c$+e-MexQ4Vw9R)Ue**Wq38102mIyRyu)EdP~2kyLd@qrNqV!p&*U}_K< z?2E;v&$yNmWBtFr7mXJy_$C`MT>9|QG(xLoX?9tsjeb1O4@swbx*YriI%Z19s3~vYpv?; zj!^sO=P&DC4^I=UYQ+)6+FY5L7pdbQ$AP%|(i7V6-Lx!hT9e!&E&QVdDfa=vTllz> zovO4ZKi^L3^mCXxJm@qi^hj;ztCOrNw zn*4mqpAk&3w03}TX`1`TRHJGf^m{ws|G902vBp4Hy_Tajy$u z6iPYL?kTXD6%EE=^6NE;1uOQI?v<{joO{4l@bTE!{g9fAhw4aJL;Io2lx6w1ypue` z2rf02t~r8~1DEIH=7le&S-pH}3hx?~>+YLBLHWZy3Sh5Sq4=p=3r|VR`b{;|3cfW? zd4ykv$O_$7S&O-SVqy%y{pWj$5V~A?$G%NUoSPGLSJuGRsI=-Amj1o(Tp1zOB>)%G z6*=D%tk+c6lr4n;Tz6>G3MzZcx^7OS)LL1AVR?c}iuHtWYArxb!UxNcuivX;xKel)%Inx*+x zGp6j^n}(796ouMT#KJm{&%=wub(>n5mgT$pSeGx(FA~L>>QikZ^5)e|HMe*uCkLGG ziy3VSSo_4dTkLW6yvlu;uk{S=)`VE1yij{5rA}U7RJ3&8@-nntML*P>Ec`NfxV^i1 zO9`}Pz4Zbc5vfblb(w6IGV?W-w zMMLIcmuYlRB5uDQ^SEEiVv_Fm7QpaT#EP!)B8|Ww$KRql-A!P4cce^v$I0=LD2-6<3wR_iQRh)Q% zal$sN^j%%JbV6@sr+I?IItp}C?X;I7#*L~baP}A`(GxRK<_+ZkEzoap) zCPNDhp$PM|XKvySc)I@($+D`RLPBU7b@j3HHnyvsol6iMEK%tt)Qh(Y1!GTQA((DZ zkuCM2{6ag}%1y8#z{I-1Iy5b8rVuBB>0_9Oi0Vhb#? zq;|#xSo}a8Wn)kQ{Yg7Vj76BwDIo7-XSq!+rmbV07a|K^@nUQ8xDa02c&v}@jPeMV zs2d4fqN2C5M8ynf4|Zvt=Yb&Mu2UOVlMX3+ex|igp&@oMAW;Y?8yDRRoKg27b6W-8 znsxn<8rqsGi{02mo#T(=9WVr6-N21dD))7R`7b#%4^(!FV7R#g?u0mo(%Oypa?o-O+mWBC;PDt;Cn3$q zAU-h}vODh8lPnIVd#$}iF8_%*;gfUC&=folQZ?T-jN){`Am8LV<4+wphE)>}s(+`x z3*El9Mnlji-W5>Q?KTzKx|wGIMMeM!FmqO`CvaTN*(E;c4$}OGQbv?=9zp1tCfQL4# zf9&OcX+Jt9nlo|kNxS@E@GqA+T;4T1XiE1}{m96KpzH~`Atf%>B>}Q3Zb%7Vg1dfb z4fP5l(vY8J!_Q6dcQT<`bj~vTf2i_i}ZJ&DV7$|ouJ`K1CL-_ zvl!P$$L06vO%-9bhIDh+CE{ENjU7879_X7N&^Y0hcKS893TO|HNct-g+u%t!35=OH zEc1@j=f;@t(Ae=R@MLae%&4BVJ?xLYxypVeS_D(f8ehNAa?F>;YqcRHUk}}8ipEVK z#)w+_gqHwfw}5&&5j>8++g9k{A#J_Bj&i5fgti7;eJ#~TbOJ@M8MM-2k5QL$tnYm! z?If3YhLE5BHZzEPO{Rt@-_F)fs+yJqAwU&w-@u6c6YPQG?F1eR_YSx1K+*n zI;_=$`N2SyT>aXlLuIn-vr@1lBg={EP(J^+NsM_{zG^!n&pV(HD9VAuY;t9lovQ*C%^>9xq$PYvY&mu(;f%1l)#8gRpvvY>mYbG7GZ%_8CUfS&1E`|5FU)7_ngKT znms7>$K5M?fLjPirAH_lzjfd$P~rwbz#~1@l-ZZ{s=*Y373Hpto}`EU)mp!ckIC`& zHKMy`7!l`HXOd5N?8l00|CDdCUB)Q4`&cb;;eDF`fg7cku?~lsC|4v#IuHrH{BJeL zvi=Bq>$CYI;wYCNHD35mmYM(k;*b=Jl@J zJmZ*0=Jy!LHbEvvdp$P`i91|EXq~8{J9@{nz@p#yw+VL4X!ju7B>f}P$I7l5=GIe@ zdssn)r)ye+W=mp>66a*3{(@Ch~?JLXY0gxd%z{hIRs_~T50VhC!S z@arSkqX=A##jSjGiq!D$V+$c?`WQ4c1o1u%sHgxTIX35@Zy4={k{$H(EF(5*uXKGJ z%6u`Lsbx7a18Z`A-`T4s@6iuSoC$RGIbm5ho1bKUkH@cXpLF&o;Jilt`h%_9@}gp! z;c{0dNR}B^)O^*v#EC?gk=&=QVDj-krRalxBPn?jQ=|&+I~ts9G~XAjimo-cgE&(e zYOV>jc-`V}+CxXL+2eyo2z&CdA@CsxHR0=HV!{gIoQ9 zqC~6MNAh0Xut2JjRcG!uT;5;iJlBttB@~BStq`6Fw5$2p53Uwwu6;Sj>ZAg0Wf>}(a8hxfGQO(N%lcI>C0F39)@eD!)ye>HVE)^r3c=k#_VqEr*t@CSY zeG5~N`Z&W>>DX?;FT1>zhV#uii_%M#ZG|T3y7Vp1pg2@sPL9qKtg^h-Zz~!EmnPoc zcj)^#EpaBbHYv8WDe{Yz-6zxoe)4+pn;F9q6{ zg%F-^Z?%d!B7?9jc3@H2SViO^8f&bBO%jUZHbEFij&1zt7{JWwJd#-RyO-oNnXFMg zJgh(1M36M7(D90LPRXH0vK2N)7O*xH8ss5+lDV&>63~3rdt|P4sv>)=;TWgj{}ySY zLR1m4upKY>yBvu>;pU-XsofT4*ZpXT@q7?5jwW%Y(>Rf0r}bF)o_3EFk@hlFAN!O? zJ(%JFm4Q-DY84YoS3mRbi~rCZ?q+yne2~i>HNNY@12VtK%7-{>gA?c9t7jF)nm-!L z3uiZy*n~Ui)S<5Jf-Sb1EYfC`aBwL+R1J%DZ7u56R`ZxY-=}4 ze~93~V(%x{lu*cbCM|#szDUqtS(2 z%+$25n3CKOmF_SXqs2e-j2`A0Vjo{EBu0WM`pCL}A9gkSMi&H2uYvgFEi%D5lCYT6 z2bq)H8y;n1K-u@l!9T*=@r^B~3(`%}H*vy!jPW6B3|3^+J!RK*JJy1hZ+jOpPNzEV z!0->hT>`NfutT-EbDy0smWoN`&l5V$=5xvVu&P|ehw9qtnmt0D5owVc>Hra5b;sTf zawry+xopgnuW0g*c!FA#el+~2|LAQ$ixc!Te90hp7`uM9H{AjD;As#Bp+e^c%4SiU9+lMr=?D}H;I(Ew_+tGx8)_P6Mg7@4 zEcJ5$B)e@%!T^1KSpgHrgcp&3D1*|US$oMt8mDwY_iwML3e6Doh9PJG0uiEgVcC=J z?-;E8q%(RsJ(y>szL`NR8 z@>52~gMx%T+-~Z7Io64ruK&X77MB0#0+I&ZTimth4bPV3|8T3H&`P2NeUb_YTQMkJ z6=LKI$6boo$dw5{1TJI;s<4P#*7+pi3#~ApF}MKJQ+tIPX-~Y3v>|qk3AVN?kxrjw zCe`_X=&b`W+L}6COmuv-4fjvA3xx5Xo;P^L6Ev8SH~$bd4&0?5moK&m_0mK( zLwoP+%~lN_;kj3c`G<9!>$BzH13jaU)5Dy*llO4lqj1^hvT2pR#97k&2FZDFJ zR>7QU*fNdF0xrq}jO(eI+aez}e5(%o&aG}k#vj`bVSzfT5|>KbN9Km@viIX%!&e7> zrA%k6?-h>agDyj12lv&b{_;InKqp%p>F+Q`|*~Ch#yr2 z21r8VW3tDg_|hu={&Q-74+r5K2w9BXGqZNTVU-7~xg_>^@!qba{9m!NHm}|0A|KZW zEIxu0)SZDW;ju46sH+mF78ZFyCzn#{{i5~5o*UAbc=!n+1(e9B9RT}R*P&SrrtA@z z;XrUXO-Vb(Z{*ze{l3no@T)Ly#_ zZn0w}S8jsq>E4t*H)7=fik?I5QSNp$^pxH(fA-~6^#o_?SI`uZyITNtFTf>mIo=2v zPYni*iW?&Gz=ZD91-k!nNn*Eby$^Kw+9q7xzg4LtE2zFzdHHl>9nC(T0hwS@1fGpI zx%|WnQ<~+s_-_U=kW`IhOapS@ygm$8tuj|JLAJ z^4xpZ(vKYza7a@7Zo~X@PN`=gbTpLqtJ#uG~ z1J4&4!!p={v{n8`wDps73I2M6!=i9Y68#$S1W&)+&gpj%G;L3MQE2?y)T0ZRs!bnh!Td;XMWs z&pR`w1N8EBU`nI>@&o^A40lH%YEiW4Sm?rr$3(a z4t6+!H?$Uc8+f(^J^Gtfw?>|V3+<>29vpJ^&qBq*m1pLq(Y#v}Fzm1ws?>R&X7q1W zqnk9AmO#21oq9t%@>@&e;(uy9eqXthLqE<1 zKp(QFajRwf7!;j7u8Q`D^$x6LpMFiJ7P~qLmGIDGyG;+LJ_LDOn07qZk>Hi?J4 zJ(ISoyjAX5Mq;{On@GVNC%Z0R^^P94F3+7ikeDROm#cpQdl1#Lb*Fp|d2z?meH}th zf<|6}eq)x7N)>%h3ip%wsF%G5?e`p{8h;udZLasxo;C}szhg59`R0SzZFWjX3Mjg) z;_%wNrIN4hO??Pz7V}m_r2E$r*&>*CDX$_6SmKFnmCY4s_p+FDK9I@F1MURXpUoM9 z7^f;0)LkdE-f2HbV(-=?!1EwY?SUJc~dpt0a>u+xssEvx* zKFlu+fUb={7}U$r?iI?{(L^M_41K^%ORi>HORi~@^r_OR5geemls$I2f^4D>e?0q0 zSr|M;M66N2_~2T1&>WF|avajkFfJaFyqprpXU2M7*mobh6tD-px>SfdPF!{}heAG* zQ2^1FwQ9kXop;t(S_v`7lO^O7Xope#W>?32!Z-?7FApN`3Z7Wa*8VaJR_W{ezrM{q zoC!UQik4b3fvbJo`1=lA#f{C@BAKHuNx`@GNlyoe9ax+Z50jru+QI+UA=s-655 zIjd?I?aD)Pr7)Hb`?k0Auq6Fs%Io>Kl5f;D?NiYT3_EFmjJmC3^YGe)tr9D4TmXHA z`$B(92oc69y@e4N1OKX=_`({w8(oN+D(8dBU7b{jZMF@#bGDw@$W(kekZxX>Zml6* ztgX%K4qe&Ym;-#2xSGusr-pmkG+V{osoq^-*ub%;Hv6q?T_p<5|I7h8Y*}kX^T27G zV|z_|#_$$sPyGQ>FN5p*993%#8@Mn11<6y*e*1k5AW7KXZHGTTeIM4AoU}thVYfkk zjIvR_pQuhi^H>FYZBbiL8Ky^u&Hb&ddaiIkD6&wxlO<=CZZr9lCF1x}pxq}*P{nc} zE{kT~$NDy74FNtqeeeM7Karv0EoBGbfM1UZu zO;sXGoKKgDph=7gV|p^^whTQ>O~9hQrT}3NOy6TFi^}FpTQn&^ zUG@+vBYanb7|79FZL08a&hE=o->NSJ1OgLgqxoa>L++d2)cH&wj55}f83NTDk!@@i zeDQ1kYy5bjB^W{hmYj@FfmI4vH8b&*2J%b?Z84P|2QI^@xNdydOI^O!%#*lv6pfo6 zT`5S~p^$IRtFAc0%cy8R(wkPNK}u_7av3{zJ||!dS62sBJpYSNvL6lw~}e+bU}R z!^uvRA6~=qta5DsJv>A=)(4yr)?X&A(mX>3E=@oiEJJynXn6#p*!FHPH%5+K_Ogkv zVa*};Ldsxx&*a$pF@D?kiW@SA_M1%OrzvVnM8+NsS`)EJ`t2aO-vH~))BVwMN+=~E%P(Af(v zOwVhE((%dDAbom*YDGG0d8*Wk_DT58GJ8&4h0V@`*<;a{(fw5do4CF*mAj%5R+^1+0 zw&GPX%+9FjE_1vMDP!}K>~e-$>w9>g#i zbOK21Aq*$cwGKU7u_XMImD-vF4J=c;Wmd4^%9uY}5P?*?=_sxG==m40NsglOaD<3f z-I0OyjfH{X#F3|==tXqo^`eNViRCzp1`mg|=}bk6!x?Mh_bGwvBz{_gqXc_xN4T3e zY1kP3uyAFNMq_Z7@pHIE3Qh#?O@nWE6H+YzeXp9wvNT7AwCkD|&;_RUzN??RX3$gD zXUTq0>ipWO#!xM