Pre-release v0.3.0 (#4159)

* publish 0.2.10 (#2797)

新功能:
- 优化 PDF 文件的 OCR,过滤无意义的小图片 by @liunux4odoo #2525
- 支持 Gemini 在线模型 by @yhfgyyf #2630
- 支持 GLM4 在线模型 by @zRzRzRzRzRzRzR
- elasticsearch更新https连接 by @xldistance #2390
- 增强对PPT、DOC知识库文件的OCR识别 by @596192804 #2013
- 更新 Agent 对话功能 by @zRzRzRzRzRzRzR
- 每次创建对象时从连接池获取连接,避免每次执行方法时都新建连接 by @Lijia0 #2480
- 实现 ChatOpenAI 判断token有没有超过模型的context上下文长度 by @glide-the
- 更新运行数据库报错和项目里程碑 by @zRzRzRzRzRzRzR #2659
- 更新配置文件/文档/依赖 by @imClumsyPanda @zRzRzRzRzRzRzR
- 添加日文版 readme by @eltociear #2787

修复:
- langchain 更新后,PGVector 向量库连接错误 by @HALIndex #2591
- Minimax's model worker 错误 by @xyhshen 
- ES库无法向量检索.添加mappings创建向量索引 by MSZheng20 #2688

* Update README.md

* Add files via upload

* Update README.md

* 修复PDF旋转的BUG

* Support Chroma

* perf delete unused import

* 忽略测试代码

* 更新文件

* API前端丢失问题解决

* 更新了chromadb的打印的符号

* autodl代号错误

* Update README.md

* Update README.md

* Update README.md

* 修复milvus相关bug

* 支持星火3.5模型

* 修复es 知识库查询bug (#2848)

* 修复es 知识库查询bug (#2848)

* 更新zhipuai请求方式

* 增加对 .htm 扩展名的显式支持

* 更新readme

* Docker镜像制作与K8S YAML部署操作说明 (#2892)

* Dev (#2280)

* 修复Azure 不设置Max token的bug

* 重写agent

1. 修改Agent实现方式,支持多参数,仅剩 ChatGLM3-6b和 OpenAI GPT4 支持,剩余模型将在暂时缺席Agent功能
2. 删除agent_chat 集成到llm_chat中
3. 重写大部分工具,适应新Agent

* 更新架构

* 删除web_chat,自动融合

* 移除所有聊天,都变成Agent控制

* 更新配置文件

* 更新配置模板和提示词

* 更改参数选择bug

* 修复模型选择的bug

* 更新一些内容

* 更新多模态 语音 视觉的内容

1. 更新本地模型语音 视觉多模态功能并设置了对应工具

* 支持多模态Grounding

1. 美化了chat的代码
2. 支持视觉工具输出Grounding任务
3. 完善工具调用的流程

* 支持XPU,修改了glm3部分agent

* 添加 qwen agent

* 对其ChatGLM3-6B与Qwen-14B

* fix callback handler

* 更新Agent工具返回

* fix: LLMChain no output when no tools selected

* 跟新了langchain 0.1.x需要的依赖和修改的代码

* 更新chatGLM3 langchain0.1.x Agent写法

* 按照 langchain 0.1 重写 qwen agent

* 修复 callback 无效的问题

* 添加文生图工具

* webui 支持文生图

* 集成openai plugins插件

* 删除fastchat的配置

* 增加openai插件

* 集成openai plugins插件

* 更新模型执行列表和今晚修改的内容

* 集成openai_plugins/imitater插件

* 集成openai_plugins/imitater插件

* 集成openai_plugins/imitater插件

* 减少错误的显示

* 标准配置

* vllm参数配置

* 增加智谱插件

* 删除本地fschat配置

* 删除本地fschat配置,pydantic升级到2

* 删除本地fschat workers

* openai-plugins-list.json

* 升级agent,pydantic升级到2

* fix model_config是系统关键词问题

* embeddings模块集成openai plugins插件,使用统一api调用

* loom模型服务update_store更新逻辑

* 集成LOOM在线embedding业务

* 本地知识库搜索字段修改

* 知识库在线api接入点配置在线api接入点配置更新逻辑

* Update model_config.py.example

* 修改模型配置方式,所有模型以 openai 兼容框架的形式接入,chatchat 自身不再加载模型。
改变 Embeddings 模型改为使用框架 API,不再手动加载,删除自定义 Embeddings Keyword 代码
修改依赖文件,移除 torch transformers 等重依赖
暂时移出对 loom 的集成

后续:
1、优化目录结构
2、检查合并中有无被覆盖的 0.2.10 内容

* move document_loaders & text_splitter under server

* make torch & transformers optional
import pydantic Model & Field from langchain.pydantic_v1 instead of pydantic.v1

* - pydantic 限定为 v1,并统一项目中所有 pydantic 导入路径,为以后升级 v2 做准备
- 重构 api.py:
    - 按模块划分为不同的 router
    - 添加 openai 兼容的转发接口,项目默认使用该接口以实现模型负载均衡
    - 添加 /tools 接口,可以获取/调用编写的 agent tools
    - 移除所有 EmbeddingFuncAdapter,统一改用 get_Embeddings
    - 待办:
        - /chat/chat 接口改为 openai 兼容
        - 添加 /chat/kb_chat 接口,openai 兼容
        - 改变 ntlk/knowledge_base/logs 等数据目录位置

* 移除 llama-index 依赖;修复 /v1/models 错误

* 原因:windows下启动失败提示补充python-multipart包 (#3184)

改动:requirements添加python-multipart==0.0.9
版本:0.0.9  Requires: Python >=3.8

Co-authored-by: XuCai <liangxc@akulaku.com>

* 添加 xinference 本地模型和自定义模型配置 UI: streamlit run model_loaders/xinference_manager.py

* update xinference manager ui

* fix merge conflict

* model_config 中补充 oneapi 默认在线模型;/v1/models 接口支持 oneapi 平台,统一返回模型列表

* 重写 calculate 工具

* 调整根目录结构,kb/logs/media/nltk_data 移动到专用数据目录(可配置,默认 data)。注意知识库文件要做相应移动

* update kb_config.py.example

* 优化 ES 知识库
- 开发者
    - get_OpenAIClient 的 local_wrap 默认值改为 False,避免 API 服务未启动导致其它功能受阻(如Embeddings)
    - 修改 ES 知识库服务:
	- 检索策略改为 ApproxRetrievalStrategy
	- 设置 timeout 为 60, 避免文档过多导致 ConnecitonTimeout Error
    - 修改 LocalAIEmbeddings,使用多线程进行  embed_texts,效果不明显,瓶颈可能主要在提供 Embedding 的服务器上

* 修复glm3 agent被注释的agent会话文本结构解析代码
看起来输出的文本占位符如下,目前解析代码是有问题的
Thought <|assistant|> Action\r
```python
tool_call(action_input)
```<|observation|>

* make qwen agent work with langchain>=0.1 (#3228)

* make xinference model manager support xinference 0.9.x

* 使用多进程提高导入知识库的速度 (#3276)

* xinference的代码

先传 我后面来改

* Delete server/xinference directory

* Create khazic

* diiii

diii

* Revert "xinference的代码"

* fix markdown header split (#1825) (#3324)

* dify model_providers configuration
This module provides the interface for invoking and authenticating various models, and offers Dify a unified information and credentials form rule for model providers.

* fix merge conflict: langchain Embeddings not imported in server.utils

* 添加 react 编写的新版 WEBUI (#3417)

* feat:提交前端代码

* feat:提交logo样式切换

* feat:替换avatar、部分位置icon、chatchat相关说明、git链接、Wiki链接、关于、设置、反馈与建议等功能,关闭lobehub自检更新功能

* fix:移除多余代码

---------

Co-authored-by: liunux4odoo <41217877+liunux4odoo@users.noreply.github.com>

* model_providers bootstrap

* model_providers bootstrap

* update to pydantic v2 (#3486)

* 使用poetry管理项目

* 使用poetry管理项目

* dev分支解决pydantic版本冲突问题,增加ollama配置,支持ollama会话和向量接口 (#3508)

* dev分支解决pydantic版本冲突问题,增加ollama配置,支持ollama会话和向量接口
1、因dev版本的pydantic升级到了v2版本,由于在class History(BaseModel)中使用了from server.pydantic_v1,而fastapi的引用已变为pydantic的v2版本,所以fastapi用v2版本去校验用v1版本定义的对象,当会话历史histtory不为空的时候,会报错:TypeError: BaseModel.validate() takes 2 positional arguments but 3 were given。经测试,解方法为在class History(BaseModel)中也使用v2版本即可;
2、配置文件参照其它平台配置,增加了ollama平台相关配置,会话模型用户可根据实际情况自行添加,向量模型目前支持nomic-embed-text(必须升级ollama到0.1.29以上)。
3、因ollama官方只在会话部分对openai api做了兼容,向量api暂未适配,好在langchain官方库支持OllamaEmbeddings,因而在get_Embeddings方法中添加了相关支持代码。

* 修复 pydantic 升级到 v2 后 DocumentWithVsID 和 /v1/embeddings 兼容性问题

---------

Co-authored-by: srszzw <srszzw@163.com>
Co-authored-by: liunux4odoo <liunux@qq.com>

* 对python的要求降级到py38

* fix bugs; make poetry using tsinghua mirror of pypi

* update gitignore; remove unignored files

* update wiki sub module

* 20240326

* 20240326

* qqqq

* 删除历史文件

* 移动项目模块

* update .gitignore; fix model version error in api_schemas

* 封装ModelManager

* - 重写 tool 部分: (#3553)

- 简化 tool 的定义方式
    - 所有 tool 和 tool_config 支持热加载
    - 修复:json_schema_extra warning

* 使用yaml加载用户配置适配器

* 格式化代码

* 格式化

* 优化工具定义;添加 openai 兼容的统一 chat 接口 (#3570)

- 修复:
    - Qwen Agent 的 OutputParser 不再抛出异常,遇到非 COT 文本直接返回
    - CallbackHandler 正确处理工具调用信息

- 重写 tool 定义方式:
    - 添加 regist_tool 简化 tool 定义:
        - 可以指定一个用户友好的名称
        - 自动将函数的 __doc__ 作为 tool.description
	- 支持用 Field 定义参数,不再需要额外定义 ModelSchema
        - 添加 BaseToolOutput 封装 tool	返回结果,以便同时获取原始值、给LLM的字符串值
        - 支持工具热加载(有待测试)

- 增加 openai 兼容的统一 chat 接口,通过 tools/tool_choice/extra_body 不同参数组合支持:
    - Agent 对话
    - 指定工具调用(如知识库RAG)
    - LLM 对话

- 根据后端功能更新 webui

* 修复:search_local_knowledge_base 工具返回值错误;/tools 路由错误;webui 中“正在思考”一直显示 (#3571)

* 添加 openai 兼容的 files 接口 (#3573)

* 使用BootstrapWebBuilder适配RESTFulOpenAIBootstrapBaseWeb加载

* 格式化和代码检查说明

* 模型列表适配

* make format

* chat_completions接口报文适配

* make format

* xinference 插件示例

* 一些默认参数

* exec path fix

* 解决ollama部署的qwen,执行agent,返回的json格式不正确问题。

* provider_configuration.py
查询所有的平台信息,包含计费策略和配置schema_validators(参数必填信息校验规则)
/workspaces/current/model-providers
查询平台模型分类的详细默认信息,包含了模型类型,模型参数,模型状态
workspaces/current/models/model-types/{model_type}

* 开发手册

* 兼容model_providers,集成webui及API中平台配置的初始化 (#3625)

* provider_configuration init of MODEL_PLATFORMS

* 开发手册

* 兼容model_providers,集成webui及API中平台配置的初始化

* Dev model providers (#3628)


* gemini 初始化参数问题

* gemini 同步工具调用

* embedding convert endpoint

* 修复 --api -w命令

* /v1/models 接口返回值由 List[Model] 改为 {'data': List[Model]},兼容最新版 xinference

* 3.8兼容 (#3769)

* 增加使用说明

* 3.8兼容性配置

* fix

* formater

* 不同平台兼容测试用例

* embedding兼容

* 增加日志信息

* pip源仓库设置,一些版本问题,启动说明  配置说明 (#3854)

* 仓库设置,一些版本问题

* pip源仓库设置,一些版本问题,启动说明

* 配置说明

* 泛型标记错误 (#3855)

* 仓库设置,一些版本问题

* pip源仓库设置,一些版本问题,启动说明

* 配置说明

* 发布的依赖信息

* 泛型标记错误

* 泛型标记错误

* CICD github action build publish pypi、Release Tag (#3886)

* 测试用例

* CICD 流程

* CICD 流程

* CICD 流程

* 一些agent数据处理的问题,model_runtime模块的说明文档 (#3943)

* 一些agent数据出来的问题

* Changes:
- Translated and updated the Model Runtime documentation to reflect the latest changes and features.
- Clarified the decoupling benefits of the Model Runtime module from the Chatchat service.
- Removed outdated information regarding the model configuration storage module.
- Detailed the retained functionalities post-removal of the Dify configuration page.
- Provided a comprehensive overview of the Model Runtime's three-layered structure.
- Included the status of the `fetch-from-remote` feature and its non-implementation in Dify.
- Added instructions for custom service provider model capabilities.

* - 新功能 (#3944)

- streamlit 更新到 1.34,webui 支持 Dialog 操作
    - streamlit-chatbox 更新到 1.1.12,更好的多会话支持
- 开发者
    - 在 API 中增加项目图片路由(/img/{file_name}),方便前端使用

* 修改包名

* 修改包信息

* ollama配置解析问题

* 用户配置动态加载 (#3951)

* version = "0.3.0.20240506"

* version = "0.3.0.20240506"

* version = "0.3.0.20240506"

* version = "0.3.0.20240506"

* 启动说明

* 一些bug

* 修复了一些配置重载的bug

* 配置的加载行为修改

* 配置的加载行为修改

* agent代码优化

* ollama 代码升级,使用openai协议

* 支持deepseek客户端

* contributing (#4043)

* 添加了贡献说明 docs/contributing,包含了一些代码仓库说明和开发规范,以及在model_providers下面编写了一些单元测试的示例

* 关于providers的配置说明

* python3.8兼容

* python3.8兼容

* ollama兼容

* ollama兼容

* 一些兼容 pydantic<3,>=1.9.0  的代码,

* 一些兼容 pydantic<3,>=1.9.0 model_config 的代码,

* make format

* test

* 更新版本

* get_img_base64

* get_img_base64

* get_img_base64

* get_img_base64

* get_img_base64

* 统一模型类型编码

* 向量处理问题

* 优化目录结构 (#4058)

* 优化目录结构

* 修改一些测试问题

---------

Co-authored-by: glide-the <2533736852@qq.com>

* repositories

* 调整日志

* 调整日志zdf

* 增加可选依赖extras

* feat:Added some documentation. (#4085)

* feat:Added some documentation.

* feat:Added some documentation.

* feat:Added some documentation.

---------

Co-authored-by: yuehuazhang <yuehuazhang@tencent.com>

* fix code.md typos

* fix chatchat-server/pyproject.toml typos

* feat:README (#4118)

Co-authored-by: yuehuazhang <yuehuazhang@tencent.com>

* 初始化数据库集成model_providers

* 关闭守护进程

* 1、修改知识库列表接口,返回全量属性字段,同时修改受影响的相关代码。 (#4119)

2、run_in_process_pool改为run_in_thread_pool,解决兼容性问题。
3、poetry配置文件修复。

* 动态更新Prompt中的知识库描述信息,使大模型更容易判断使用哪个知识库。 (#4121)

* 1、修改知识库列表接口,返回全量属性字段,同时修改受影响的相关代码。
2、run_in_process_pool改为run_in_thread_pool,解决兼容性问题。
3、poetry配置文件修复。

* 1、动态更新Prompt中的知识库描述信息,使大模型更容易判断使用哪个知识库。

* fix: 补充 xinference 配置信息 (#4123)

* feat:README

* feat:补充 xinference 平台 llm 和 embedding 模型配置.

---------

Co-authored-by: yuehuazhang <yuehuazhang@tencent.com>

* 知识库工具的下拉列表改为动态获取,不必重启服务。 (#4126)

* 1、知识库工具的下拉列表改为动态获取,不必重启服务。

* update README and imgs

* update README and imgs

* update README and imgs

* update README and imgs

* 修改安装说明描述问题

* make formater

* 更新版本"0.3.0.20240606

* Update code.md

* 优化知识库相关功能 (#4153)

- 新功能
    - pypi 包新增 chatchat-kb 命令脚本,对应 init_database.py 功能

- 开发者
    - _model_config.py 中默认包含 xinference 配置项
    - 所有涉及向量库的操作,前置检查当前 Embed 模型是否可用
    - /knowledge_base/create_knowledge_base 接口增加 kb_info 参数
    - /knowledge_base/list_files 接口返回所有数据库字段,而非文件名称列表
    - 修正 xinference 模型管理脚本

* 消除警告

* 一些依赖问题

* 增加text2sql工具,支持特定表、智能判定表,支持对表名进行额外说明 (#4154)

* 1、增加text2sql工具,支持特定表、智能判定表,支持对表名进行额外说明

* 支持SQLAlchemy大部分数据库、新增read-only模式,提高安全性、增加text2sql使用建议 (#4155)

* 1、修改text2sql连接配置,支持SQLAlchemy大部分数据库;
2、新增read-only模式,若有数据库写保护需求,会从大模型判断、SQLAlchemy拦截器两个层面进行写拦截,提高安全性;
3、增加text2sql使用建议;

* dotenv

* dotenv 配置

* 用户工作空间操作 (#4156)

工作空间的配置预设,提供ConfigBasic建造方法产生实例。
  该类的实例对象用于存储工作空间的配置信息,如工作空间的路径等
  工作空间的配置信息存储在用户的家目录下的.config/chatchat/workspace/workspace_config.json文件中。
  注意:不存在则读取默认

提供了操作入口
指令` chatchat-config` 工作空间配置

options:
```
  -h, --help            show this help message and exit
  -v {true,false}, --verbose {true,false}
                        是否开启详细日志
  -d DATA, --data DATA  数据存放路径
  -f FORMAT, --format FORMAT
                        日志格式
  --clear               清除配置
```

* 配置路径问题

* fix faiss_cache bug

* Feature(File RAG): add file_rag in chatchat-server, add ensemble retriever and vectorstore retriever.

* Feature(File RAG): add file_rag in chatchat-server, add ensemble retriever and vectorstore retriever.

* fix xinference manager bug

* Fix(File RAG): use jieba instead of cutword

* Fix(File RAG): update kb_doc_api.py

* 工作空间的配置预设,提供ConfigBasic建造 实例。 (#4158)

- ConfigWorkSpace接口说明
```text

ConfigWorkSpace是一个配置工作空间的抽象类,提供基础的配置信息存储和读取功能。
提供ConfigFactory建造方法产生实例。
该类的实例对象用于存储工作空间的配置信息,如工作空间的路径等
工作空间的配置信息存储在用户的家目录下的.chatchat/workspace/workspace_config.json文件中。
注意:不存在则读取默认
```

* 编写配置说明

* 编写配置说明

---------

Co-authored-by: liunux4odoo <41217877+liunux4odoo@users.noreply.github.com>
Co-authored-by: glide-the <2533736852@qq.com>
Co-authored-by: tonysong <tonysong@digitalgd.com.cn>
Co-authored-by: songpb <songpb@gmail.com>
Co-authored-by: showmecodett <showmecodett@gmail.com>
Co-authored-by: zR <2448370773@qq.com>
Co-authored-by: zqt <1178747941@qq.com>
Co-authored-by: zqt996 <67185303+zqt996@users.noreply.github.com>
Co-authored-by: fengyaojie <fengyaojie@xdf.cn>
Co-authored-by: Hans WAN <hanswan@tom.com>
Co-authored-by: thinklover <thinklover@gmail.com>
Co-authored-by: liunux4odoo <liunux@qq.com>
Co-authored-by: xucailiang <74602715+xucailiang@users.noreply.github.com>
Co-authored-by: XuCai <liangxc@akulaku.com>
Co-authored-by: dignfei <913015993@qq.com>
Co-authored-by: Leb <khazzz1c@gmail.com>
Co-authored-by: Sumkor <sumkor@foxmail.com>
Co-authored-by: panhong <381500590@qq.com>
Co-authored-by: srszzw <741992282@qq.com>
Co-authored-by: srszzw <srszzw@163.com>
Co-authored-by: yuehua-s <41819795+yuehua-s@users.noreply.github.com>
Co-authored-by: yuehuazhang <yuehuazhang@tencent.com>
This commit is contained in:
imClumsyPanda 2024-06-10 22:48:35 +08:00 committed by GitHub
parent 7c163b95c5
commit 995c5e300e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1996 changed files with 279761 additions and 8432 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring

93
.github/actions/poetry_setup/action.yml vendored Normal file
View File

@ -0,0 +1,93 @@
# An action for setting up poetry install with caching.
# Using a custom action since the default action does not
# take poetry install groups into account.
# Action code from:
# https://github.com/actions/setup-python/issues/505#issuecomment-1273013236
name: poetry-install-with-caching
description: Poetry install with support for caching of dependency groups.
inputs:
python-version:
description: Python version, supporting MAJOR.MINOR only
required: true
poetry-version:
description: Poetry version
required: true
cache-key:
description: Cache key to use for manual handling of caching
required: true
working-directory:
description: Directory whose poetry.lock file should be cached
required: true
runs:
using: composite
steps:
- uses: actions/setup-python@v5
name: Setup python ${{ inputs.python-version }}
id: setup-python
with:
python-version: ${{ inputs.python-version }}
- uses: actions/cache@v4
id: cache-bin-poetry
name: Cache Poetry binary - Python ${{ inputs.python-version }}
env:
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "1"
with:
path: |
/opt/pipx/venvs/poetry
# This step caches the poetry installation, so make sure it's keyed on the poetry version as well.
key: bin-poetry-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-${{ inputs.poetry-version }}
- name: Refresh shell hashtable and fixup softlinks
if: steps.cache-bin-poetry.outputs.cache-hit == 'true'
shell: bash
env:
POETRY_VERSION: ${{ inputs.poetry-version }}
PYTHON_VERSION: ${{ inputs.python-version }}
run: |
set -eux
# Refresh the shell hashtable, to ensure correct `which` output.
hash -r
# `actions/cache@v3` doesn't always seem able to correctly unpack softlinks.
# Delete and recreate the softlinks pipx expects to have.
rm /opt/pipx/venvs/poetry/bin/python
cd /opt/pipx/venvs/poetry/bin
ln -s "$(which "python$PYTHON_VERSION")" python
chmod +x python
cd /opt/pipx_bin/
ln -s /opt/pipx/venvs/poetry/bin/poetry poetry
chmod +x poetry
# Ensure everything got set up correctly.
/opt/pipx/venvs/poetry/bin/python --version
/opt/pipx_bin/poetry --version
- name: Install poetry
if: steps.cache-bin-poetry.outputs.cache-hit != 'true'
shell: bash
env:
POETRY_VERSION: ${{ inputs.poetry-version }}
PYTHON_VERSION: ${{ inputs.python-version }}
# Install poetry using the python version installed by setup-python step.
run: pipx install "poetry==$POETRY_VERSION" --python '${{ steps.setup-python.outputs.python-path }}' --verbose
- name: Restore pip and poetry cached dependencies
uses: actions/cache@v4
env:
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "4"
WORKDIR: ${{ inputs.working-directory == '' && '.' || inputs.working-directory }}
with:
path: |
~/.cache/pip
~/.cache/pypoetry/virtualenvs
~/.cache/pypoetry/cache
~/.cache/pypoetry/artifacts
${{ env.WORKDIR }}/.venv
key: py-deps-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-poetry-${{ inputs.poetry-version }}-${{ inputs.cache-key }}-${{ hashFiles(format('{0}/**/poetry.lock', env.WORKDIR)) }}

264
.github/workflows/_release.yml vendored Normal file
View File

@ -0,0 +1,264 @@
name: release
run-name: Release ${{ inputs.working-directory }} by @${{ github.actor }}
on:
workflow_call:
branches:
- dev
inputs:
working-directory:
required: true
type: string
description: "From which folder this pipeline executes"
workflow_dispatch:
branches:
- dev
inputs:
working-directory:
required: true
type: string
default: './chatchat-server'
description: "From which folder this pipeline executes"
env:
PYTHON_VERSION: "3.8"
POETRY_VERSION: "1.7.1"
jobs:
build:
if: github.ref == 'refs/heads/master'
environment: Scheduled testing
runs-on: ubuntu-latest
outputs:
pkg-name: ${{ steps.check-version.outputs.pkg-name }}
version: ${{ steps.check-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
# We want to keep this build stage *separate* from the release stage,
# so that there's no sharing of permissions between them.
# The release stage has trusted publishing and GitHub repo contents write access,
# and we want to keep the scope of that access limited just to the release job.
# Otherwise, a malicious `build` step (e.g. via a compromised dependency)
# could get access to our GitHub or PyPI credentials.
#
# Per the trusted publishing GitHub Action:
# > It is strongly advised to separate jobs for building [...]
# > from the publish job.
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: poetry build
working-directory: ${{ inputs.working-directory }}
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Check Version
id: check-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
test-pypi-publish:
needs:
- build
uses:
./.github/workflows/_test_release.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
pre-release-checks:
needs:
- build
- test-pypi-publish
environment: Scheduled testing
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# We explicitly *don't* set up caching here. This ensures our tests are
# maximally sensitive to catching breakage.
#
# For example, here's a way that caching can cause a falsely-passing test:
# - Make the langchain package manifest no longer list a dependency package
# as a requirement. This means it won't be installed by `pip install`,
# and attempting to use it would cause a crash.
# - That dependency used to be required, so it may have been cached.
# When restoring the venv packages from cache, that dependency gets included.
# - Tests pass, because the dependency is present even though it wasn't specified.
# - The package is published, and it breaks on the missing dependency when
# used in the real world.
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
- name: Import published package
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
# Here we use:
# - The default regular PyPI index as the *primary* index, meaning
# that it takes priority (https://pypi.org/simple)
# - The test PyPI index as an extra index, so that any dependencies that
# are not found on test PyPI can be resolved and installed anyway.
# (https://test.pypi.org/simple). This will include the PKG_NAME==VERSION
# package because VERSION will not have been uploaded to regular PyPI yet.
# - attempt install again after 5 seconds if it fails because there is
# sometimes a delay in availability on test pypi
run: |
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" || \
( \
sleep 5 && \
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" \
)
# Replace all dashes in the package name with underscores,
# since that's how Python imports packages with dashes in the name.
IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/_/g)"
poetry run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))"
- name: Import test dependencies
run: poetry install --with test
working-directory: ${{ inputs.working-directory }}
# Overwrite the local version of the package with the test PyPI version.
- name: Import published package (again)
working-directory: ${{ inputs.working-directory }}
shell: bash
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
run: |
poetry run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION"
- name: Run unit tests
run: make tests
env:
ZHIPUAI_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
ZHIPUAI_BASE_URL: ${{ secrets.ZHIPUAI_BASE_URL }}
working-directory: ${{ inputs.working-directory }}
# - name: Run integration tests
# env:
# ZHIPUAI_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
# ZHIPUAI_BASE_URL: ${{ secrets.ZHIPUAI_BASE_URL }}
# run: make integration_tests
# working-directory: ${{ inputs.working-directory }}
publish:
needs:
- build
- test-pypi-publish
- pre-release-checks
environment: Scheduled testing
runs-on: ubuntu-latest
permissions:
# This permission is used for trusted publishing:
# https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
#
# Trusted publishing has to also be configured on PyPI for each package:
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
id-token: write
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
- uses: actions/download-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true
password: ${{ secrets.PYPI_API_TOKEN }}
# We overwrite any existing distributions with the same name and version.
# This is *only for CI use* and is *extremely dangerous* otherwise!
# https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates
skip-existing: true
mark-release:
needs:
- build
- test-pypi-publish
- pre-release-checks
- publish
environment: Scheduled testing
runs-on: ubuntu-latest
permissions:
# This permission is needed by `ncipollo/release-action` to
# create the GitHub release.
contents: write
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
- uses: actions/download-artifact@v4
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Create Release
uses: ncipollo/release-action@v1
if: ${{ inputs.working-directory == './chatchat-server' }}
with:
artifacts: "dist/*"
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
generateReleaseNotes: true
tag: v${{ needs.build.outputs.version }}
commit: main

97
.github/workflows/_test_release.yml vendored Normal file
View File

@ -0,0 +1,97 @@
name: test-release
on:
workflow_call:
branches:
- dev
inputs:
working-directory:
required: true
type: string
description: "From which folder this pipeline executes"
env:
POETRY_VERSION: "1.7.1"
PYTHON_VERSION: "3.8"
jobs:
build:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
outputs:
pkg-name: ${{ steps.check-version.outputs.pkg-name }}
version: ${{ steps.check-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
uses: "./.github/actions/poetry_setup"
with:
python-version: ${{ env.PYTHON_VERSION }}
poetry-version: ${{ env.POETRY_VERSION }}
working-directory: ${{ inputs.working-directory }}
cache-key: release
# We want to keep this build stage *separate* from the release stage,
# so that there's no sharing of permissions between them.
# The release stage has trusted publishing and GitHub repo contents write access,
# and we want to keep the scope of that access limited just to the release job.
# Otherwise, a malicious `build` step (e.g. via a compromised dependency)
# could get access to our GitHub or PyPI credentials.
#
# Per the trusted publishing GitHub Action:
# > It is strongly advised to separate jobs for building [...]
# > from the publish job.
# https://github.com/pypa/gh-action-pypi-publish#non-goals
- name: Build project for distribution
run: poetry build
working-directory: ${{ inputs.working-directory }}
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: test-dist
path: ${{ inputs.working-directory }}/dist/
- name: Check Version
id: check-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
echo version="$(poetry version --short)" >> $GITHUB_OUTPUT
publish:
needs:
- build
runs-on: ubuntu-latest
permissions:
# This permission is used for trusted publishing:
# https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
#
# Trusted publishing has to also be configured on PyPI for each package:
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: test-dist
path: ${{ inputs.working-directory }}/dist/
- name: Publish to test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ inputs.working-directory }}/dist/
verbose: true
print-hash: true
repository-url: https://test.pypi.org/legacy/
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
# We overwrite any existing distributions with the same name and version.
# This is *only for CI use* and is *extremely dangerous* otherwise!
# https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates
skip-existing: true

15
.gitignore vendored
View File

@ -1,12 +1,11 @@
*.log
*.log.*
*.bak
logs
/knowledge_base/*
!/knowledge_base/samples
/knowledge_base/samples/vector_store
/libs/chatchat-server/chatchat/data/*
!/libs/chatchat-server/chatchat/data/knowledge_base/samples
/libs/chatchat-server/chatchat/data/knowledge_base/samples/vector_store
!/libs/chatchat-server/chatchat/data/nltk_data
/configs/*.py
.vscode/
# below are standard python ignore files
@ -173,4 +172,10 @@ cython_debug/
.pytest_cache
.DS_Store
# Test File
test.py
/knowledge_base/samples/content/202311-D平台项目工作大纲参数人员中间库表结构说明V1.1(1).docx
/knowledge_base/samples/content/imi_temeplate.txt
chatchat/data

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "knowledge_base/samples/content/wiki"]
path = knowledge_base/samples/content/wiki
path = chatchat/chatchat/data/knowledge_base/samples/content/wiki
url = https://github.com/chatchat-space/Langchain-Chatchat.wiki.git

View File

@ -1,13 +1,11 @@
![](img/logo-long-chatchat-trans-v2.png)
![](docs/img/logo-long-chatchat-trans-v2.png)
🌍 [READ THIS IN ENGLISH](README_en.md)
🌍 [日本語で読む](README_ja.md)
📃 **LangChain-Chatchat** (原 Langchain-ChatGLM)
基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现,开源、可离线部署的检索增强生成(RAG)大模型知识库项目。
⚠️`0.2.10`将会是`0.2.x`系列的最后一个版本,`0.2.x`系列版本将会停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`
基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现,开源、可离线部署的 RAG 与 Agent 应用项目。
---
@ -44,18 +42,19 @@ OpenAI GPT API 的调用,并将在后续持续扩充对各类模型及模型 A
📺 [原理介绍视频](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
![实现原理图](img/langchain+chatglm.png)
![实现原理图](docs/img/langchain+chatglm.png)
从文档处理角度来看,实现流程如下:
![实现原理图2](img/langchain+chatglm2.png)
![实现原理图2](docs/img/langchain+chatglm2.png)
🚩 本项目未涉及微调、训练过程,但可利用微调或训练对本项目效果进行优化。
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) 中 `v13`
版本所使用代码已更新至本项目 `v0.2.9` 版本。
🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) 中 `0.2.10`
🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.6) 已经更新到 ```0.2.7``` 版本。
版本所使用代码已更新至本项目 `v0.2.10` 版本。
🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7) 已经更新到 ```0.2.7``` 版本。
🌲 一行命令运行 Docker
@ -63,7 +62,7 @@ OpenAI GPT API 的调用,并将在后续持续扩充对各类模型及模型 A
docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7
```
🧩 本项目有一个非常完整的[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) README只是一个简单的介绍_
🧩 本项目有一个非常完整的 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) README只是一个简单的介绍_
_仅仅是入门教程能够基础运行__。
如果你想要更深入的了解本项目,或者想对本项目做出贡献。请移步 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
界面
@ -74,13 +73,13 @@ _仅仅是入门教程能够基础运行__。
本开源方案采用```Apache License```,可以免费商用,无需付费。
我们支持市面上主流的本地大语言模型和Embedding模型支持开源的本地向量数据库。
支持列表详见[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
支持列表详见 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
## 快速上手
### 1. 环境配置
+ 首先,确保你的机器安装了 Python 3.8 - 3.11 (我们强烈推荐使用 Python3.11)
+ 首先,确保你的机器安装了 Python 3.8 - 3.11 。
```
$ python --version
@ -105,10 +104,10 @@ $ pip install -r requirements_webui.txt
# 默认依赖包括基本运行环境FAISS向量库。如果要使用 milvus/pg_vector 等向量库,请将 requirements.txt 中相应依赖取消注释再安装。
```
请注意LangChain-Chatchat `0.2.x` 系列是针对 Langchain `0.0.x` 系列版本的,如果你使用的是 Langchain `0.1.x`
系列版本,需要降级您的`Langchain`版本。
请注意LangChain-Chatchat `0.3.x` 当前版本是针对 Langchain `0.1.x` 系列版本的,如果你使用的是 Langchain `0.2.x`
版本,需要降级您的 `Langchain` 版本。
### 2 模型下载
### 2. 模型启动
如需在本地或离线环境下运行本项目,需要首先将项目所需的模型下载至本地,通常开源 LLM 与 Embedding
模型可以从 [HuggingFace](https://huggingface.co/models) 下载。
@ -134,7 +133,7 @@ $ python copy_config_example.py
$ python init_database.py --recreate-vs
```
### 4. 一键启动
### 4. 项目一键启动
按照以下命令启动项目
@ -148,22 +147,21 @@ $ python startup.py -a
1. FastAPI Docs 界面
![](img/fastapi_docs_026.png)
![](docs/img/fastapi_docs_026.png)
2. Web UI 启动界面示例:
- Web UI 对话界面:
![img](img/LLM_success.png)
![img](docs/img/LLM_success.png)
- Web UI 知识库管理页面:
![](img/init_knowledge_base.jpg)
![](docs/img/init_knowledge_base.jpg)
### 注意
以上方式只是为了快速上手,如果需要更多的功能和自定义启动方式
,请参考[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
以上方式只是为了快速上手,如果需要更多的功能和自定义启动方式,请参考[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
---
@ -171,12 +169,11 @@ $ python startup.py -a
## 项目里程碑
+ `2023年4月`: `Langchain-ChatGLM 0.1.0` 发布,支持基于 ChatGLM-6B 模型的本地知识库问答。
+ `2023年8月`: `Langchain-ChatGLM` 改名为 `Langchain-Chatchat``0.2.0` 发布,使用 `fastchat` 作为模型加载方案,支持更多的模型和数据库。
+ `2023年8月`: `Langchain-ChatGLM` 改名为 `Langchain-Chatchat`发布 `0.2.0` 版本,使用 `fastchat` 作为模型加载方案,支持更多的模型和数据库。
+ `2023年10月`: `Langchain-Chatchat 0.2.5` 发布,推出 Agent 内容,开源项目在`Founder Park & Zhipu AI & Zilliz`
举办的黑客马拉松获得三等奖。
+ `2023年12月`: `Langchain-Chatchat` 开源项目获得超过 **20K** stars.
+ `2024年1月`: `LangChain 0.1.x` 推出,`Langchain-Chatchat 0.2.x` 发布稳定版本`0.2.10`
后将停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`
+ `2024年6月`: `Langchain-Chatchat 0.3.0` 发布,带来全新项目架构。
+ 🔥 让我们一起期待未来 Chatchat 的故事 ···
@ -189,12 +186,12 @@ $ python startup.py -a
[![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white "langchain-chatglm")](https://t.me/+RjliQ3jnJ1YyN2E9)
### 项目交流群
<img src="img/qr_code_87.jpg" alt="二维码" width="300" />
<img src="docs/img/qr_code_96.jpg" alt="二维码" width="300" />
🎉 Langchain-Chatchat 项目微信交流群,如果你也对本项目感兴趣,欢迎加入群聊参与讨论交流。
### 公众号
<img src="img/official_wechat_mp_account.png" alt="二维码" width="300" />
<img src="docs/img/official_wechat_mp_account.png" alt="二维码" width="300" />
🎉 Langchain-Chatchat 项目官方公众号,欢迎扫码关注。
🎉 Langchain-Chatchat 项目官方公众号,欢迎扫码关注。

View File

@ -1,4 +1,4 @@
![](img/logo-long-chatchat-trans-v2.png)
![](docs/img/logo-long-chatchat-trans-v2.png)
🌍 [中文文档](README.md)
🌍 [日本語で読む](README_ja.md)
@ -9,7 +9,8 @@ A LLM application aims to implement knowledge and search engine based QA based o
LLM API.
⚠️`0.2.10` will be the last version of the `0.2.x` series. The `0.2.x` series will stop updating and technical support,
and strive to develop `Langchain-Chachat 0.3.x with stronger applicability. `.
and strive to develop `Langchain-Chachat 0.3.x` with stronger applicability.
Subsequent bug fixes for `0.2.10` will be pushed directly to the `master` branch without version updates.
---
@ -52,16 +53,16 @@ to `LLM` to generate an answer.
📺[video introduction](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
![实现原理图](img/langchain+chatglm.png)
![实现原理图](docs/img/langchain+chatglm.png)
The main process analysis from the aspect of document process:
![实现原理图2](img/langchain+chatglm2.png)
![实现原理图2](docs/img/langchain+chatglm2.png)
🚩 The training or fine-tuning are not involved in the project, but still, one always can improve performance by do
these.
🌐 [AutoDL image](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) is supported, and in v13 the codes are update to v0.2.9.
🌐 [AutoDL image](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) is supported, and in `0.2.10` the codes are update to v0.2.10.
🐳 [Docker image](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7) is supported to 0.2.7
@ -146,17 +147,17 @@ $ python startup.py -a
1. FastAPI docs interface
![](img/fastapi_docs_026.png)
![](docs/img/fastapi_docs_026.png)
2. webui page
- Web UI dialog page:
![img](img/LLM_success.png)
![img](docs/img/LLM_success.png)
- Web UI knowledge base management page:
![](img/init_knowledge_base.jpg)
![](docs/img/init_knowledge_base.jpg)
### Note
@ -191,8 +192,8 @@ please refer to the [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/
### WeChat Group
<img src="img/qr_code_87.jpg" alt="二维码" width="300" height="300" />
<img src="docs/img/qr_code_90.jpg" alt="二维码" width="300" height="300" />
### WeChat Official Account
<img src="img/official_wechat_mp_account.png" alt="图片" width="900" height="300" />
<img src="docs/img/official_wechat_mp_account.png" alt="二维码" width="300" />

View File

@ -1,11 +1,16 @@
![](img/logo-long-chatchat-trans-v2.png)
![](docs/img/logo-long-chatchat-trans-v2.png)
🌍 [中文文档](README.md)
🌍 [READ THIS IN ENGLISH](README_en.md)
📃 **LangChain-Chatchat** (旧名 Langchain-ChatGLM):
📃 **LangChain-Chatchat** (旧名 Langchain-ChatGLM)
LLM アプリケーションは、Langchain とオープンソースまたはリモートの LLM API に基づいて、知識と検索エンジンベースの QA を実装することを目的としています。
ChatGLM などの大規模な言語モデルや Langchain などのアプリケーション フレームワークに基づいた、オープン
ソースのオフライン展開可能な検索拡張生成 (RAG) 大規模モデル ナレッジ ベース プロジェクトです。
⚠️`0.2.10``0.2.x` シリーズの最終バージョンとなり、`0.2.x`
シリーズはアップデートと技術サポートを終了し、より適用性の高い `Langchain-Chachat 0.3.x` の開発に努めます。 。
`0.2.10` のその後のバグ修正は、バージョン更新なしで `master` ブランチに直接プッシュされます。
---
@ -23,32 +28,42 @@ LLM アプリケーションは、Langchain とオープンソースまたはリ
## イントロ
🤖️ [langchain](https://github.com/hwchase17/langchain) のアイデアを用いて実装された、ローカルナレッジベースに基づく Q&A アプリケーション。
目標は、中国のシナリオとオープンソースモデルに親和性があり、オフラインとオンラインの両方で実行可能な KBQAナレッジベースの Q&Aソリューションを構築することです。
🤖️ [langchain](https://github.com/hwchase17/langchain) のアイデアを用いて実装された、ローカルナレッジベースに基づく Q&A
アプリケーション。
目標は、中国のシナリオとオープンソースモデルに親和性があり、オフラインとオンラインの両方で実行可能な KBQAナレッジベースの
Q&Aソリューションを構築することです。
💡 [document.ai](https://github.com/GanymedeNil/document.ai) と [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) に触発され、
💡 [document.ai](https://github.com/GanymedeNil/document.ai)
と [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) に触発され、
プロセス全体を通してオープンソースモデルまたはリモート LLM api を使用して実装することができるローカルナレッジベースの質問応答アプリケーションを構築します。
このプロジェクトの最新バージョンでは、[FastChat](https://github.com/lm-sys/FastChat) を使用して、Vicuna、Alpaca、LLaMA、Koala、RWKV、その他多くのモデルにアクセスしています。
このプロジェクトは [langchain](https://github.com/langchain-ai/langchain) に依存し、[FastAPI](https://github.com/tiangolo/fastapi) に基づいて提供されるAPIを通してサービスを呼び出したり、
このプロジェクトの最新バージョンでは、[FastChat](https://github.com/lm-sys/FastChat)
を使用して、Vicuna、Alpaca、LLaMA、Koala、RWKV、その他多くのモデルにアクセスしています。
このプロジェクトは [langchain](https://github.com/langchain-ai/langchain)
に依存し、[FastAPI](https://github.com/tiangolo/fastapi) に基づいて提供されるAPIを通してサービスを呼び出したり、
[Streamlit](https://github.com/streamlit/streamlit) に基づいて WebUI を使ったりすることをサポートしています。
✅ オープンソースの LLM と Embedding モデルに依存して、このプロジェクトはフルプロセスの **オフラインプライベートデプロイメント** を実現することができます。
同時に、本プロジェクトは OpenAI GPT API や Zhipu API の呼び出しにも対応しており、今後も様々な機種やリモート API へのアクセスを拡大していきます。
✅ オープンソースの LLM と Embedding モデルに依存して、このプロジェクトはフルプロセスの **オフラインプライベートデプロイメント
** を実現することができます。
同時に、本プロジェクトは OpenAI GPT API や Zhipu API の呼び出しにも対応しており、今後も様々な機種やリモート API
へのアクセスを拡大していきます。
⛓️ このプロジェクトの実施原則を下のグラフに示します。主なプロセスは以下の通りです:
ファイルの読み込み -> テキストの読み込み -> テキストのセグメンテーション -> テキストのベクトル化 -> 質問のベクトル化 -> 質問ベクトルと最も似ている `top-k` をテキストベクトルでマッチング -> マッチしたテキストをコンテキストと質問として `prompt` に追加 -> 回答を生成するために `LLM` に送信。
ファイルの読み込み -> テキストの読み込み -> テキストのセグメンテーション -> テキストのベクトル化 -> 質問のベクトル化 ->
質問ベクトルと最も似ている `top-k` をテキストベクトルでマッチング ->
マッチしたテキストをコンテキストと質問として `prompt` に追加 -> 回答を生成するために `LLM` に送信。
📺[video introduction](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
![实现原理图](img/langchain+chatglm.png)
![实现原理图](docs/img/langchain+chatglm.png)
文書プロセスの側面からの主なプロセス分析:
![实现原理图2](img/langchain+chatglm2.png)
![实现原理图2](docs/img/langchain+chatglm2.png)
🚩 トレーニングやファインチューニングはプロジェクトには含まれないが、これらを行うことで必ずパフォーマンスを向上させることができます。
🌐 [AutoDL イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5)がサポートされ、v13 では v0.2.9 にアップデートされました。
🌐 [AutoDL イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5)がサポートされ、`0.2.10` では v0.2.10
にアップデートされました。
🐳 [Docker イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7)
@ -67,7 +82,7 @@ LLM アプリケーションは、Langchain とオープンソースまたはリ
```
$ python --version
Python 3.10.12
Python 3.11.7
```
次に、仮想環境を作成し、プロジェクトの依存関係を仮想環境内にインストールする。
@ -87,6 +102,7 @@ $ pip install -r requirements_webui.txt
# デフォルトの依存関係には、基本的な実行環境(FAISS ベクターライブラリ)が含まれます。milvus/pg_vector などのベクターライブラリを使用する場合は、requirements.txt 内の対応する依存関係のコメントを解除してからインストールしてください。
```
LangChain-Chachat `0.2.x` シリーズは Langchain `0.0.x` シリーズ用です。Langchain `0.1.x` シリーズをお使いの場合は、ダウングレードする必要があります。
### モデルをダウンロード
@ -94,9 +110,12 @@ LangChain-Chachat `0.2.x` シリーズは Langchain `0.0.x` シリーズ用で
このプロジェクトをローカルまたはオフライン環境で実行する必要がある場合は、まずプロジェクトに必要なモデルをダウンロードする必要があります。
通常、オープンソースの LLM と Embedding モデルは Hugging Face からダウンロードできる。
このプロジェクトで使用されているデフォルトの LLM モデルである [THUDM/chatglm2-6b](https://huggingface.co/THUDM/chatglm2-6b)と、Embedding モデル [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) を例にとると、次のようになります:
このプロジェクトで使用されているデフォルトの LLM
モデルである [THUDM/chatglm2-6b](https://huggingface.co/THUDM/chatglm2-6b)と、Embedding
モデル [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) を例にとると、次のようになります:
モデルをダウンロードするには、まず [Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage) をインストールし、次のように実行する必要があります:
モデルをダウンロードするには、まず [Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
をインストールし、次のように実行する必要があります:
```Shell
$ git lfs install
@ -125,21 +144,36 @@ $ python startup.py -a
1. FastAPI docs インターフェース
![](img/fastapi_docs_026.png)
![](docs/img/fastapi_docs_026.png)
2. webui ページ
- Web UI ダイアログページ:
![img](img/LLM_success.png)
![img](docs/img/LLM_success.png)
- Web UI ナレッジベースマネジメントページ:
![](img/init_knowledge_base.jpg)
![](docs/img/init_knowledge_base.jpg)
### 注
上記の手順はクイックスタートのために提供されています。より多くの機能が必要な場合や、起動方法をカスタマイズしたい場合は、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) を参照してください。
上記の手順はクイックスタートのために提供されています。より多くの機能が必要な場合や、起動方法をカスタマイズしたい場合は、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
を参照してください。
---
## プロジェクトのマイルストーン
+ `2023 年 4 月`: `Langchain-ChatGLM 0.1.0` がリリースされ、ChatGLM-6B モデルに基づくローカル ナレッジ ベースの質問と回答がサポートされました。
+ `2023 年 8 月`: `Langchain-ChatGLM``Langchain-Chatchat` に名前変更され、モデル読み込みソリューションとして `fastchat` を使用し、より多くのモデルとデータベースをサポートする `0.2.0` がリリースされました。
+ `2023 年 10 月`: `Langchain-Chachat 0.2.5` リリース、エージェント コンテンツ、オープンソース プロジェクトを`Founder Park & Zhipu AI & Zilliz`で開始
開催したハッカソンでは3位に入賞しました。
+ `2023 年 12 月`: `Langchain-Chachat`オープンソース プロジェクトは **20,000** つ以上のスターを獲得しました。
+ `2024 年 1 月`: `LangChain 0.1.x` がリリースされ、`Langchain-Chachat 0.2.x` が安定版 `0.2.10` をリリースしました。
今後はアップデートと技術サポートを停止し、より適用性の高い`Langchain-Chachat 0.3.x`の開発に努める予定です。
+ 🔥 これからのChatchatストーリーを一緒に楽しみにしましょう···
---
@ -151,8 +185,8 @@ $ python startup.py -a
### WeChat グループ
<img src="img/qr_code_67.jpg" alt="二维码" width="300" height="300" />
<img src="docs/img/qr_code_90.jpg" alt="二维码" width="300" height="300" />
### WeChat 公式アカウント
<img src="img/official_wechat_mp_account.png" alt="图片" width="900" height="300" />
<img src="docs/img/official_wechat_mp_account.png" alt="二维码" width="300" />

View File

@ -1,22 +0,0 @@
from server.utils import get_ChatOpenAI
from configs.model_config import LLM_MODELS, TEMPERATURE
from langchain.chains import LLMChain
from langchain.prompts.chat import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
)
model = get_ChatOpenAI(model_name=LLM_MODELS[0], temperature=TEMPERATURE)
human_prompt = "{input}"
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)
chat_prompt = ChatPromptTemplate.from_messages(
[("human", "我们来玩成语接龙,我先来,生龙活虎"),
("ai", "虎头虎脑"),
("human", "{input}")])
chain = LLMChain(prompt=chat_prompt, llm=model, verbose=True)
print(chain({"input": "恼羞成怒"}))

View File

@ -1,8 +0,0 @@
from .basic_config import *
from .model_config import *
from .kb_config import *
from .server_config import *
from .prompt_config import *
VERSION = "v0.2.10"

View File

@ -1,32 +0,0 @@
import logging
import os
import langchain
import tempfile
import shutil
# 是否显示详细日志
log_verbose = False
langchain.verbose = False
# 通常情况下不需要更改以下内容
# 日志格式
LOG_FORMAT = "%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.basicConfig(format=LOG_FORMAT)
# 日志存储路径
LOG_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "logs")
if not os.path.exists(LOG_PATH):
os.mkdir(LOG_PATH)
# 临时文件目录,主要用于文件对话
BASE_TEMP_DIR = os.path.join(tempfile.gettempdir(), "chatchat")
try:
shutil.rmtree(BASE_TEMP_DIR)
except Exception:
pass
os.makedirs(BASE_TEMP_DIR, exist_ok=True)

View File

@ -1,302 +0,0 @@
import os
# 可以指定一个绝对路径统一存放所有的Embedding和LLM模型。
# 每个模型可以是一个单独的目录,也可以是某个目录下的二级子目录。
# 如果模型目录名称和 MODEL_PATH 中的 key 或 value 相同,程序会自动检测加载,无需修改 MODEL_PATH 中的路径。
MODEL_ROOT_PATH = ""
# 选用的 Embedding 名称
EMBEDDING_MODEL = "bge-large-zh-v1.5"
# Embedding 模型运行设备。设为 "auto" 会自动检测(会有警告),也可手动设定为 "cuda","mps","cpu","xpu" 其中之一。
EMBEDDING_DEVICE = "auto"
# 选用的reranker模型
RERANKER_MODEL = "bge-reranker-large"
# 是否启用reranker模型
USE_RERANKER = False
RERANKER_MAX_LENGTH = 1024
# 如果需要在 EMBEDDING_MODEL 中增加自定义的关键字时配置
EMBEDDING_KEYWORD_FILE = "keywords.txt"
EMBEDDING_MODEL_OUTPUT_PATH = "output"
# 要运行的 LLM 名称,可以包括本地模型和在线模型。列表中本地模型将在启动项目时全部加载。
# 列表中第一个模型将作为 API 和 WEBUI 的默认模型。
# 在这里我们使用目前主流的两个离线模型其中chatglm3-6b 为默认加载模型。
# 如果你的显存不足,可使用 Qwen-1_8B-Chat, 该模型 FP16 仅需 3.8G显存。
LLM_MODELS = ["chatglm3-6b", "zhipu-api", "openai-api"]
Agent_MODEL = None
# LLM 模型运行设备。设为"auto"会自动检测(会有警告),也可手动设定为 "cuda","mps","cpu","xpu" 其中之一。
LLM_DEVICE = "auto"
HISTORY_LEN = 3
MAX_TOKENS = 2048
TEMPERATURE = 0.7
ONLINE_LLM_MODEL = {
"openai-api": {
"model_name": "gpt-4",
"api_base_url": "https://api.openai.com/v1",
"api_key": "",
"openai_proxy": "",
},
# 智谱AI API,具体注册及api key获取请前往 http://open.bigmodel.cn
"zhipu-api": {
"api_key": "",
"version": "glm-4",
"provider": "ChatGLMWorker",
},
# 具体注册及api key获取请前往 https://api.minimax.chat/
"minimax-api": {
"group_id": "",
"api_key": "",
"is_pro": False,
"provider": "MiniMaxWorker",
},
# 具体注册及api key获取请前往 https://xinghuo.xfyun.cn/
"xinghuo-api": {
"APPID": "",
"APISecret": "",
"api_key": "",
"version": "v3.0", # 你使用的讯飞星火大模型版本,可选包括 "v3.0", "v2.0", "v1.5"
"provider": "XingHuoWorker",
},
# 百度千帆 API申请方式请参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/4lilb2lpf
"qianfan-api": {
"version": "ERNIE-Bot", # 注意大小写。当前支持 "ERNIE-Bot" 或 "ERNIE-Bot-turbo" 更多的见官方文档。
"version_url": "", # 也可以不填写version直接填写在千帆申请模型发布的API地址
"api_key": "",
"secret_key": "",
"provider": "QianFanWorker",
},
# 火山方舟 API文档参考 https://www.volcengine.com/docs/82379
"fangzhou-api": {
"version": "chatglm-6b-model",
"version_url": "",
"api_key": "",
"secret_key": "",
"provider": "FangZhouWorker",
},
# 阿里云通义千问 API文档参考 https://help.aliyun.com/zh/dashscope/developer-reference/api-details
"qwen-api": {
"version": "qwen-max",
"api_key": "",
"provider": "QwenWorker",
"embed_model": "text-embedding-v1" # embedding 模型名称
},
# 百川 API申请方式请参考 https://www.baichuan-ai.com/home#api-enter
"baichuan-api": {
"version": "Baichuan2-53B",
"api_key": "",
"secret_key": "",
"provider": "BaiChuanWorker",
},
# Azure API
"azure-api": {
"deployment_name": "", # 部署容器的名字
"resource_name": "", # https://{resource_name}.openai.azure.com/openai/ 填写resource_name的部分其他部分不要填写
"api_version": "", # API的版本不是模型版本
"api_key": "",
"provider": "AzureWorker",
},
# 昆仑万维天工 API https://model-platform.tiangong.cn/
"tiangong-api": {
"version": "SkyChat-MegaVerse",
"api_key": "",
"secret_key": "",
"provider": "TianGongWorker",
},
# Gemini API https://makersuite.google.com/app/apikey
"gemini-api": {
"api_key": "",
"provider": "GeminiWorker",
}
}
# 在以下字典中修改属性值以指定本地embedding模型存储位置。支持3种设置方法
# 1、将对应的值修改为模型绝对路径
# 2、不修改此处的值以 text2vec 为例):
# 2.1 如果{MODEL_ROOT_PATH}下存在如下任一子目录:
# - text2vec
# - GanymedeNil/text2vec-large-chinese
# - text2vec-large-chinese
# 2.2 如果以上本地路径不存在则使用huggingface模型
MODEL_PATH = {
"embed_model": {
"ernie-tiny": "nghuyong/ernie-3.0-nano-zh",
"ernie-base": "nghuyong/ernie-3.0-base-zh",
"text2vec-base": "shibing624/text2vec-base-chinese",
"text2vec": "GanymedeNil/text2vec-large-chinese",
"text2vec-paraphrase": "shibing624/text2vec-base-chinese-paraphrase",
"text2vec-sentence": "shibing624/text2vec-base-chinese-sentence",
"text2vec-multilingual": "shibing624/text2vec-base-multilingual",
"text2vec-bge-large-chinese": "shibing624/text2vec-bge-large-chinese",
"m3e-small": "moka-ai/m3e-small",
"m3e-base": "moka-ai/m3e-base",
"m3e-large": "moka-ai/m3e-large",
"bge-small-zh": "BAAI/bge-small-zh",
"bge-base-zh": "BAAI/bge-base-zh",
"bge-large-zh": "BAAI/bge-large-zh",
"bge-large-zh-noinstruct": "BAAI/bge-large-zh-noinstruct",
"bge-base-zh-v1.5": "BAAI/bge-base-zh-v1.5",
"bge-large-zh-v1.5": "BAAI/bge-large-zh-v1.5",
"piccolo-base-zh": "sensenova/piccolo-base-zh",
"piccolo-large-zh": "sensenova/piccolo-large-zh",
"nlp_gte_sentence-embedding_chinese-large": "damo/nlp_gte_sentence-embedding_chinese-large",
"text-embedding-ada-002": "your OPENAI_API_KEY",
},
"llm_model": {
"chatglm2-6b": "THUDM/chatglm2-6b",
"chatglm2-6b-32k": "THUDM/chatglm2-6b-32k",
"chatglm3-6b": "THUDM/chatglm3-6b",
"chatglm3-6b-32k": "THUDM/chatglm3-6b-32k",
"Orion-14B-Chat": "OrionStarAI/Orion-14B-Chat",
"Orion-14B-Chat-Plugin": "OrionStarAI/Orion-14B-Chat-Plugin",
"Orion-14B-LongChat": "OrionStarAI/Orion-14B-LongChat",
"Llama-2-7b-chat-hf": "meta-llama/Llama-2-7b-chat-hf",
"Llama-2-13b-chat-hf": "meta-llama/Llama-2-13b-chat-hf",
"Llama-2-70b-chat-hf": "meta-llama/Llama-2-70b-chat-hf",
"Qwen-1_8B-Chat": "Qwen/Qwen-1_8B-Chat",
"Qwen-7B-Chat": "Qwen/Qwen-7B-Chat",
"Qwen-14B-Chat": "Qwen/Qwen-14B-Chat",
"Qwen-72B-Chat": "Qwen/Qwen-72B-Chat",
"baichuan-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
"baichuan-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
"baichuan2-7b-chat": "baichuan-inc/Baichuan2-7B-Chat",
"baichuan2-13b-chat": "baichuan-inc/Baichuan2-13B-Chat",
"internlm-7b": "internlm/internlm-7b",
"internlm-chat-7b": "internlm/internlm-chat-7b",
"internlm2-chat-7b": "internlm/internlm2-chat-7b",
"internlm2-chat-20b": "internlm/internlm2-chat-20b",
"BlueLM-7B-Chat": "vivo-ai/BlueLM-7B-Chat",
"BlueLM-7B-Chat-32k": "vivo-ai/BlueLM-7B-Chat-32k",
"Yi-34B-Chat": "https://huggingface.co/01-ai/Yi-34B-Chat",
"agentlm-7b": "THUDM/agentlm-7b",
"agentlm-13b": "THUDM/agentlm-13b",
"agentlm-70b": "THUDM/agentlm-70b",
"falcon-7b": "tiiuae/falcon-7b",
"falcon-40b": "tiiuae/falcon-40b",
"falcon-rw-7b": "tiiuae/falcon-rw-7b",
"aquila-7b": "BAAI/Aquila-7B",
"aquilachat-7b": "BAAI/AquilaChat-7B",
"open_llama_13b": "openlm-research/open_llama_13b",
"vicuna-13b-v1.5": "lmsys/vicuna-13b-v1.5",
"koala": "young-geng/koala",
"mpt-7b": "mosaicml/mpt-7b",
"mpt-7b-storywriter": "mosaicml/mpt-7b-storywriter",
"mpt-30b": "mosaicml/mpt-30b",
"opt-66b": "facebook/opt-66b",
"opt-iml-max-30b": "facebook/opt-iml-max-30b",
"gpt2": "gpt2",
"gpt2-xl": "gpt2-xl",
"gpt-j-6b": "EleutherAI/gpt-j-6b",
"gpt4all-j": "nomic-ai/gpt4all-j",
"gpt-neox-20b": "EleutherAI/gpt-neox-20b",
"pythia-12b": "EleutherAI/pythia-12b",
"oasst-sft-4-pythia-12b-epoch-3.5": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5",
"dolly-v2-12b": "databricks/dolly-v2-12b",
"stablelm-tuned-alpha-7b": "stabilityai/stablelm-tuned-alpha-7b",
},
"reranker": {
"bge-reranker-large": "BAAI/bge-reranker-large",
"bge-reranker-base": "BAAI/bge-reranker-base",
}
}
# 通常情况下不需要更改以下内容
# nltk 模型存储路径
NLTK_DATA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "nltk_data")
# 使用VLLM可能导致模型推理能力下降无法完成Agent任务
VLLM_MODEL_DICT = {
"chatglm2-6b": "THUDM/chatglm2-6b",
"chatglm2-6b-32k": "THUDM/chatglm2-6b-32k",
"chatglm3-6b": "THUDM/chatglm3-6b",
"chatglm3-6b-32k": "THUDM/chatglm3-6b-32k",
"Llama-2-7b-chat-hf": "meta-llama/Llama-2-7b-chat-hf",
"Llama-2-13b-chat-hf": "meta-llama/Llama-2-13b-chat-hf",
"Llama-2-70b-chat-hf": "meta-llama/Llama-2-70b-chat-hf",
"Qwen-1_8B-Chat": "Qwen/Qwen-1_8B-Chat",
"Qwen-7B-Chat": "Qwen/Qwen-7B-Chat",
"Qwen-14B-Chat": "Qwen/Qwen-14B-Chat",
"Qwen-72B-Chat": "Qwen/Qwen-72B-Chat",
"baichuan-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
"baichuan-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
"baichuan2-7b-chat": "baichuan-inc/Baichuan-7B-Chat",
"baichuan2-13b-chat": "baichuan-inc/Baichuan-13B-Chat",
"BlueLM-7B-Chat": "vivo-ai/BlueLM-7B-Chat",
"BlueLM-7B-Chat-32k": "vivo-ai/BlueLM-7B-Chat-32k",
"internlm-7b": "internlm/internlm-7b",
"internlm-chat-7b": "internlm/internlm-chat-7b",
"internlm2-chat-7b": "internlm/Models/internlm2-chat-7b",
"internlm2-chat-20b": "internlm/Models/internlm2-chat-20b",
"aquila-7b": "BAAI/Aquila-7B",
"aquilachat-7b": "BAAI/AquilaChat-7B",
"falcon-7b": "tiiuae/falcon-7b",
"falcon-40b": "tiiuae/falcon-40b",
"falcon-rw-7b": "tiiuae/falcon-rw-7b",
"gpt2": "gpt2",
"gpt2-xl": "gpt2-xl",
"gpt-j-6b": "EleutherAI/gpt-j-6b",
"gpt4all-j": "nomic-ai/gpt4all-j",
"gpt-neox-20b": "EleutherAI/gpt-neox-20b",
"pythia-12b": "EleutherAI/pythia-12b",
"oasst-sft-4-pythia-12b-epoch-3.5": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5",
"dolly-v2-12b": "databricks/dolly-v2-12b",
"stablelm-tuned-alpha-7b": "stabilityai/stablelm-tuned-alpha-7b",
"open_llama_13b": "openlm-research/open_llama_13b",
"vicuna-13b-v1.3": "lmsys/vicuna-13b-v1.3",
"koala": "young-geng/koala",
"mpt-7b": "mosaicml/mpt-7b",
"mpt-7b-storywriter": "mosaicml/mpt-7b-storywriter",
"mpt-30b": "mosaicml/mpt-30b",
"opt-66b": "facebook/opt-66b",
"opt-iml-max-30b": "facebook/opt-iml-max-30b",
}
SUPPORT_AGENT_MODEL = [
"openai-api", # GPT4 模型
"qwen-api", # Qwen Max模型
"zhipu-api", # 智谱AI GLM4模型
"Qwen", # 所有Qwen系列本地模型
"chatglm3-6b",
"internlm2-chat-20b",
"Orion-14B-Chat-Plugin",
]

View File

@ -1,127 +0,0 @@
# prompt模板使用Jinja2语法简单点就是用双大括号代替f-string的单大括号
# 本配置文件支持热加载修改prompt模板后无需重启服务。
# LLM对话支持的变量
# - input: 用户输入内容
# 知识库和搜索引擎对话支持的变量:
# - context: 从检索结果拼接的知识文本
# - question: 用户提出的问题
# Agent对话支持的变量
# - tools: 可用的工具列表
# - tool_names: 可用的工具名称列表
# - history: 用户和Agent的对话历史
# - input: 用户输入内容
# - agent_scratchpad: Agent的思维记录
PROMPT_TEMPLATES = {
"llm_chat": {
"default":
'{{ input }}',
"with_history":
'The following is a friendly conversation between a human and an AI. '
'The AI is talkative and provides lots of specific details from its context. '
'If the AI does not know the answer to a question, it truthfully says it does not know.\n\n'
'Current conversation:\n'
'{history}\n'
'Human: {input}\n'
'AI:',
"py":
'你是一个聪明的代码助手请你给我写出简单的py代码。 \n'
'{{ input }}',
},
"knowledge_base_chat": {
"default":
'<指令>根据已知信息,简洁和专业的来回答问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题”,'
'不允许在答案中添加编造成分,答案请使用中文。 </指令>\n'
'<已知信息>{{ context }}</已知信息>\n'
'<问题>{{ question }}</问题>\n',
"text":
'<指令>根据已知信息,简洁和专业的来回答问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题”,答案请使用中文。 </指令>\n'
'<已知信息>{{ context }}</已知信息>\n'
'<问题>{{ question }}</问题>\n',
"empty": # 搜不到知识库的时候使用
'请你回答我的问题:\n'
'{{ question }}\n\n',
},
"search_engine_chat": {
"default":
'<指令>这是我搜索到的互联网信息,请你根据这些信息进行提取并有调理,简洁的回答问题。'
'如果无法从中得到答案,请说 “无法搜索到能回答问题的内容”。 </指令>\n'
'<已知信息>{{ context }}</已知信息>\n'
'<问题>{{ question }}</问题>\n',
"search":
'<指令>根据已知信息,简洁和专业的来回答问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题”,答案请使用中文。 </指令>\n'
'<已知信息>{{ context }}</已知信息>\n'
'<问题>{{ question }}</问题>\n',
},
"agent_chat": {
"default":
'Answer the following questions as best you can. If it is in order, you can use some tools appropriately. '
'You have access to the following tools:\n\n'
'{tools}\n\n'
'Use the following format:\n'
'Question: the input question you must answer1\n'
'Thought: you should always think about what to do and what tools to use.\n'
'Action: the action to take, should be one of [{tool_names}]\n'
'Action Input: the input to the action\n'
'Observation: the result of the action\n'
'... (this Thought/Action/Action Input/Observation can be repeated zero or more times)\n'
'Thought: I now know the final answer\n'
'Final Answer: the final answer to the original input question\n'
'Begin!\n\n'
'history: {history}\n\n'
'Question: {input}\n\n'
'Thought: {agent_scratchpad}\n',
"ChatGLM3":
'You can answer using the tools, or answer directly using your knowledge without using the tools. '
'Respond to the human as helpfully and accurately as possible.\n'
'You have access to the following tools:\n'
'{tools}\n'
'Use a json blob to specify a tool by providing an action key (tool name) '
'and an action_input key (tool input).\n'
'Valid "action" values: "Final Answer" or [{tool_names}]'
'Provide only ONE action per $JSON_BLOB, as shown:\n\n'
'```\n'
'{{{{\n'
' "action": $TOOL_NAME,\n'
' "action_input": $INPUT\n'
'}}}}\n'
'```\n\n'
'Follow this format:\n\n'
'Question: input question to answer\n'
'Thought: consider previous and subsequent steps\n'
'Action:\n'
'```\n'
'$JSON_BLOB\n'
'```\n'
'Observation: action result\n'
'... (repeat Thought/Action/Observation N times)\n'
'Thought: I know what to respond\n'
'Action:\n'
'```\n'
'{{{{\n'
' "action": "Final Answer",\n'
' "action_input": "Final response to human"\n'
'}}}}\n'
'Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. '
'Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\n'
'history: {history}\n\n'
'Question: {input}\n\n'
'Thought: {agent_scratchpad}',
}
}

View File

@ -1,137 +0,0 @@
import sys
from configs.model_config import LLM_DEVICE
# httpx 请求默认超时时间(秒)。如果加载模型或对话较慢,出现超时错误,可以适当加大该值。
HTTPX_DEFAULT_TIMEOUT = 300.0
# API 是否开启跨域默认为False如果需要开启请设置为True
# is open cross domain
OPEN_CROSS_DOMAIN = False
# 各服务器默认绑定host。如改为"0.0.0.0"需要修改下方所有XX_SERVER的host
DEFAULT_BIND_HOST = "0.0.0.0" if sys.platform != "win32" else "127.0.0.1"
# webui.py server
WEBUI_SERVER = {
"host": DEFAULT_BIND_HOST,
"port": 8501,
}
# api.py server
API_SERVER = {
"host": DEFAULT_BIND_HOST,
"port": 7861,
}
# fastchat openai_api server
FSCHAT_OPENAI_API = {
"host": DEFAULT_BIND_HOST,
"port": 20000,
}
# fastchat model_worker server
# 这些模型必须是在model_config.MODEL_PATH或ONLINE_MODEL中正确配置的。
# 在启动startup.py时可用通过`--model-name xxxx yyyy`指定模型不指定则为LLM_MODELS
FSCHAT_MODEL_WORKERS = {
# 所有模型共用的默认配置,可在模型专项配置中进行覆盖。
"default": {
"host": DEFAULT_BIND_HOST,
"port": 20002,
"device": LLM_DEVICE,
# False,'vllm',使用的推理加速框架,使用vllm如果出现HuggingFace通信问题参见doc/FAQ
# vllm对一些模型支持还不成熟暂时默认关闭
"infer_turbo": False,
# model_worker多卡加载需要配置的参数
# "gpus": None, # 使用的GPU以str的格式指定如"0,1"如失效请使用CUDA_VISIBLE_DEVICES="0,1"等形式指定
# "num_gpus": 1, # 使用GPU的数量
# "max_gpu_memory": "20GiB", # 每个GPU占用的最大显存
# 以下为model_worker非常用参数可根据需要配置
# "load_8bit": False, # 开启8bit量化
# "cpu_offloading": None,
# "gptq_ckpt": None,
# "gptq_wbits": 16,
# "gptq_groupsize": -1,
# "gptq_act_order": False,
# "awq_ckpt": None,
# "awq_wbits": 16,
# "awq_groupsize": -1,
# "model_names": LLM_MODELS,
# "conv_template": None,
# "limit_worker_concurrency": 5,
# "stream_interval": 2,
# "no_register": False,
# "embed_in_truncate": False,
# 以下为vllm_worker配置参数,注意使用vllm必须有gpu仅在Linux测试通过
# tokenizer = model_path # 如果tokenizer与model_path不一致在此处添加
# 'tokenizer_mode':'auto',
# 'trust_remote_code':True,
# 'download_dir':None,
# 'load_format':'auto',
# 'dtype':'auto',
# 'seed':0,
# 'worker_use_ray':False,
# 'pipeline_parallel_size':1,
# 'tensor_parallel_size':1,
# 'block_size':16,
# 'swap_space':4 , # GiB
# 'gpu_memory_utilization':0.90,
# 'max_num_batched_tokens':2560,
# 'max_num_seqs':256,
# 'disable_log_stats':False,
# 'conv_template':None,
# 'limit_worker_concurrency':5,
# 'no_register':False,
# 'num_gpus': 1
# 'engine_use_ray': False,
# 'disable_log_requests': False
},
"Qwen-1_8B-Chat": {
"device": "cpu",
},
"chatglm3-6b": {
"device": "cuda",
},
# 以下配置可以不用修改在model_config中设置启动的模型
"zhipu-api": {
"port": 21001,
},
"minimax-api": {
"port": 21002,
},
"xinghuo-api": {
"port": 21003,
},
"qianfan-api": {
"port": 21004,
},
"fangzhou-api": {
"port": 21005,
},
"qwen-api": {
"port": 21006,
},
"baichuan-api": {
"port": 21007,
},
"azure-api": {
"port": 21008,
},
"tiangong-api": {
"port": 21009,
},
"gemini-api": {
"port": 21010,
},
}
FSCHAT_CONTROLLER = {
"host": DEFAULT_BIND_HOST,
"port": 20001,
"dispatch_method": "shortest_queue",
}

View File

@ -1,12 +0,0 @@
# 用于批量将configs下的.example文件复制并命名为.py文件
import os
import shutil
if __name__ == "__main__":
files = os.listdir("configs")
src_files = [os.path.join("configs", file) for file in files if ".example" in file]
for src_file in src_files:
tar_file = src_file.replace(".example", "")
shutil.copy(src_file, tar_file)

19
docker/Dockerfile Normal file
View File

@ -0,0 +1,19 @@
FROM python:3.11
RUN apt-get update
RUN apt-get install -y libgl1-mesa-glx
RUN mkdir /Langchain-Chatchat
COPY requirements.txt /Langchain-Chatchat
COPY requirements_api.txt /Langchain-Chatchat
COPY requirements_webui.txt /Langchain-Chatchat
WORKDIR /Langchain-Chatchat
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN pip install -r requirements_api.txt
RUN pip install -r requirements_webui.txt
EXPOSE 8501
EXPOSE 7861
EXPOSE 20000

View File

@ -0,0 +1,29 @@
# 创建代码根目录
mkdir /home/langchain
## 切换代码根目录
cd /home/langchain
## 拉取仓库代码
git clone https://github.com/chatchat-space/Langchain-Chatchat.git .
## 切换Configs文件夹复制所有的配置档并去除文档后缀.example
/home/langchain/configs/
## 配置key
/home/langchain/configs/model_config.py
## 切换代码根目录
cd /home/langchain
## 制作镜像(自行修改镜像名称与版本号)
docker build -t {image_name}:{image_tag} .
## 修改YAML里的镜像名称与版本号
langchain_sample.yaml
## 创建K8S资源
kubectl apply -f langchain_sample.yaml
## 删除K8S资源
kubectl delete -f langchain_sample.yaml

View File

@ -0,0 +1,91 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: langchain-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
local:
path: /home/langchain #填入代码所在的目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- instance-1
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: langchain-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: standard
resources:
requests:
storage: 10Gi
volumeName: langchain-pv
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: langchain
spec:
replicas: 1
selector:
matchLabels:
app: langchain
template:
metadata:
labels:
app: langchain
spec:
securityContext:
fsGroup: 101
containers:
- name: langchain
image:{image_name}:{image_tag} #填入镜像名称与版本号
command: ["python"]
args: ["startup.py","-a"] #启动命令
ports:
- containerPort: 8501
- containerPort: 7861
- containerPort: 20000
volumeMounts:
- name: langchain-vol
mountPath: /Langchain-Chatchat
nodeSelector:
kubernetes.io/hostname: instance-1
volumes:
- name: langchain-vol
persistentVolumeClaim:
claimName: langchain-pvc
---
apiVersion: v1
kind: Service
metadata:
name: langchain-service
spec:
selector:
app: langchain
type: NodePort
ports:
- name: webui
port: 8501
targetPort: 8501
nodePort: 8501
- name: api
port: 7861
targetPort: 7861
nodePort: 7861
- name: fastchat
port: 20000
targetPort: 20000
nodePort: 20000

View File

@ -1,29 +0,0 @@
# 实现基于ES的数据插入、检索、删除、更新
```shell
author: 唐国梁Tommy
e-mail: flytang186@qq.com
如果遇到任何问题,可以与我联系,我这边部署后服务是没有问题的。
```
## 第1步ES docker部署
```shell
docker network create elastic
docker run -id --name elasticsearch --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e "xpack.security.http.ssl.enabled=false" -t docker.elastic.co/elasticsearch/elasticsearch:8.8.2
```
### 第2步Kibana docker部署
**注意Kibana版本与ES保持一致**
```shell
docker pull docker.elastic.co/kibana/kibana:{version}
docker run --name kibana --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:{version}
```
### 第3步核心代码
```shell
1. 核心代码路径
server/knowledge_base/kb_service/es_kb_service.py
2. 需要在 configs/model_config.py 中 配置 ES参数IP PORT
```

View File

@ -0,0 +1,30 @@
### 贡献指南
各位开发者chatchat由个人组织经过了不断地迭代和完善作为一个不断进化的项目
我们欢迎您的参与无论是提交bug报告、功能请求、代码贡献、文档编写、测试、或者其他形式的贡献。
#### 贡献方式
这里列出了一些您可以为chatchat做出贡献的方式:
- [Code](code.md): 帮助我们编写代码修复bug或者改进基础设施。
- Documentation: 帮助我们编写文档使chatchat更容易使用。
- Discussions: 帮助回答用户的使用问题,讨论问题。
当您的贡献被接受后,我们会将您的名字添加到贡献者列表中。
在功能贡献达到2次以上我们会考虑将您加入到chatchat的开发团队中。
#### Github Issue
我们需要跟踪功能请求与bug报告
目前我们有使用Issue默认模板来让用户更好的描述问题但是目前这个大部分issue的用户可能依然选择只回复一句话
对于这样的情况我们需要告知用户如何更好的描述问题。在15天内没有回复的issue我们会关闭issue。
关于功能请求备受关注的RAG话题我们会考虑加入到我们的开发计划中。
我们努力保持issue的更新但是我们也需要您的帮助如果您发现有问题没有得到及时回复请在issue下@我们
#### 寻求帮助
我们尽量使开发者更容易上手,当您遇到问题时,请联系维护人员,我们会尽力帮助您。
类似的 diff、formatting、linting、testing等问题如果您不确定如何解决请随时联系我们
很多时候规则校验会阻碍一些开发者,您的思路如果足够优秀,我们会考虑调整规则。

60
docs/contributing/code.md Normal file
View File

@ -0,0 +1,60 @@
### 代码贡献
贡献此仓库的代码时,请查阅 ["fork and pull request"](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) 流程,除非您是项目的维护者。请不要直接提交到主分支。
在提交PR之前请检查按照pull request模板的指导进行操作。注意我们的CI系统会自动运行linting和测试以确保您的代码符合我们的标准。
更重要的是,我们需要保持良好的单元测试和文档,如果你做了如下操作:
- 添加新功能
更新受影响的操作文档
- 修复bug
尽可能添加一个单元测试在tests/integration_tests或tests/unit_tests中
#### 依赖管理Poetry与env/dependency管理方法
这个项目使用 Poetry 来管理依赖。
> 注意在安装Poetry之前如果您使用Conda请创建并激活一个新的Conda env例如`conda create -n chatchat python=3.9`
Install Poetry: [documentation on how to install it.](https://python-poetry.org/docs/#installing-with-pipx)
> 友情提示 不想安装pipx可以用pip安装poetryTips:如果你没有其它poetry的项目
> 注意: 如果您使用 Conda 或 Pyenv 作为您的环境/包管理器在安装Poetry之后
> 使用如下命令使 Poetry 使用 virtualenv python environment (`poetry config virtualenvs.prefer-active-python true`)
#### 本地开发环境安装
- 选择主项目目录
```shell
cd Langchain-Chatchat/libs/chatchat-server/
```
- 安装chatchat依赖(for running chatchat lint\tests):
```shell
poetry install --with lint,test
```
> Poetry install后会在你的site-packages安装一个chatchat-`<version>`.dist-info文件夹带有direct_url.json文件这个文件指向你的开发环境
#### 格式化和代码检查
在提交PR之前,请在本地运行以下命令;CI系统也会进行检查。
##### 代码格式化
本项目使用ruff进行代码格式化。
##### 关于
要对某个库进行格式化,请在相应的库目录下运行相同的命令:
```shell
cd {model-providers|chatchat-server|chatchat-frontend}
make format
```
此外,你可以使用format_diff命令仅对当前分支中与主分支相比已修改的文件进行格式化:
```shell
make format_diff
```
当你对项目的一部分进行了更改,并希望确保更改的部分格式正确,而不影响代码库的其他部分时,这个命令特别有用。

View File

@ -0,0 +1,39 @@
### 仓库结构
如果您想要贡献代码,您需要了解仓库的结构。这将有助于您找到您想要的文件,以及了解如何将您的代码提交到仓库。
chatchat沿用了 monorepo的组织方式, 项目的代码库包含了多个包。
以下是可视化为树的结构:
```shell
.
├── docker
├── docs # 文档
├── frontend # 前端
├── libs
│ ├── chatchat-server # 服务端
│ │ └── tests
│ │ ├── integration_tests # 集成测试 (每个包都有,为了简洁没有展示)
│ │ └── unit_tests # 单元测试 (每个包都有,为了简洁没有展示)
│ └── model-providers # 模型平台
```
根目录还包含以下文件:
pyproject.toml: 用于构建文档和文档linting的依赖项cookbook。
Makefile: 包含用于构建linting和文档和cookbook的快捷方式的文件。
根目录中还有其他文件,但它们的都应该是顾名思义的,请查看相应的文件夹以了解更多信息。
### 代码
代码库中的代码分为两个部分:
- libs/chatchat-server目录包含chatchat服务端代码。
- libs/model-providers目录包含对供应商模型转换的代码。
- frontend目录包含chatchat前端代码。
详细的

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 4.1 MiB

View File

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -1,51 +0,0 @@
from typing import List
from langchain.document_loaders.unstructured import UnstructuredFileLoader
from configs import PDF_OCR_THRESHOLD
from document_loaders.ocr import get_ocr
import tqdm
class RapidOCRPDFLoader(UnstructuredFileLoader):
def _get_elements(self) -> List:
def pdf2text(filepath):
import fitz # pyMuPDF里面的fitz包不要与pip install fitz混淆
import numpy as np
ocr = get_ocr()
doc = fitz.open(filepath)
resp = ""
b_unit = tqdm.tqdm(total=doc.page_count, desc="RapidOCRPDFLoader context page index: 0")
for i, page in enumerate(doc):
b_unit.set_description("RapidOCRPDFLoader context page index: {}".format(i))
b_unit.refresh()
text = page.get_text("")
resp += text + "\n"
img_list = page.get_image_info(xrefs=True)
for img in img_list:
if xref := img.get("xref"):
bbox = img["bbox"]
# 检查图片尺寸是否超过设定的阈值
if ((bbox[2] - bbox[0]) / (page.rect.width) < PDF_OCR_THRESHOLD[0]
or (bbox[3] - bbox[1]) / (page.rect.height) < PDF_OCR_THRESHOLD[1]):
continue
pix = fitz.Pixmap(doc, xref)
img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, -1)
result, _ = ocr(img_array)
if result:
ocr_result = [line[1] for line in result]
resp += "\n".join(ocr_result)
# 更新进度
b_unit.update(1)
return resp
text = pdf2text(self.file_path)
from unstructured.partition.text import partition_text
return partition_text(text=text, **self.unstructured_kwargs)
if __name__ == "__main__":
loader = RapidOCRPDFLoader(file_path="../tests/samples/ocr_test.pdf")
docs = loader.load()
print(docs)

View File

@ -1,79 +0,0 @@
'''
该功能是为了将关键词加入到embedding模型中以便于在embedding模型中进行关键词的embedding
该功能的实现是通过修改embedding模型的tokenizer来实现的
该功能仅仅对EMBEDDING_MODEL参数对应的的模型有效输出后的模型保存在原本模型
感谢@CharlesJu1和@charlesyju的贡献提出了想法和最基础的PR
保存的模型的位置位于原本嵌入模型的目录下模型的名称为原模型名称+Merge_Keywords_时间戳
'''
import sys
sys.path.append("..")
import os
import torch
from datetime import datetime
from configs import (
MODEL_PATH,
EMBEDDING_MODEL,
EMBEDDING_KEYWORD_FILE,
)
from safetensors.torch import save_model
from sentence_transformers import SentenceTransformer
from langchain_core._api import deprecated
@deprecated(
since="0.3.0",
message="自定义关键词 Langchain-Chatchat 0.3.x 重写, 0.2.x中相关功能将废弃",
removal="0.3.0"
)
def get_keyword_embedding(bert_model, tokenizer, key_words):
tokenizer_output = tokenizer(key_words, return_tensors="pt", padding=True, truncation=True)
input_ids = tokenizer_output['input_ids']
input_ids = input_ids[:, 1:-1]
keyword_embedding = bert_model.embeddings.word_embeddings(input_ids)
keyword_embedding = torch.mean(keyword_embedding, 1)
return keyword_embedding
def add_keyword_to_model(model_name=EMBEDDING_MODEL, keyword_file: str = "", output_model_path: str = None):
key_words = []
with open(keyword_file, "r") as f:
for line in f:
key_words.append(line.strip())
st_model = SentenceTransformer(model_name)
key_words_len = len(key_words)
word_embedding_model = st_model._first_module()
bert_model = word_embedding_model.auto_model
tokenizer = word_embedding_model.tokenizer
key_words_embedding = get_keyword_embedding(bert_model, tokenizer, key_words)
embedding_weight = bert_model.embeddings.word_embeddings.weight
embedding_weight_len = len(embedding_weight)
tokenizer.add_tokens(key_words)
bert_model.resize_token_embeddings(len(tokenizer), pad_to_multiple_of=32)
embedding_weight = bert_model.embeddings.word_embeddings.weight
with torch.no_grad():
embedding_weight[embedding_weight_len:embedding_weight_len + key_words_len, :] = key_words_embedding
if output_model_path:
os.makedirs(output_model_path, exist_ok=True)
word_embedding_model.save(output_model_path)
safetensors_file = os.path.join(output_model_path, "model.safetensors")
metadata = {'format': 'pt'}
save_model(bert_model, safetensors_file, metadata)
print("save model to {}".format(output_model_path))
def add_keyword_to_embedding_model(path: str = EMBEDDING_KEYWORD_FILE):
keyword_file = os.path.join(path)
model_name = MODEL_PATH["embed_model"][EMBEDDING_MODEL]
model_parent_directory = os.path.dirname(model_name)
current_time = datetime.now().strftime('%Y%m%d_%H%M%S')
output_model_name = "{}_Merge_Keywords_{}".format(EMBEDDING_MODEL, current_time)
output_model_path = os.path.join(model_parent_directory, output_model_name)
add_keyword_to_model(model_name, keyword_file, output_model_path)

View File

@ -1,3 +0,0 @@
Langchain-Chatchat
数据科学与大数据技术
人工智能与先进计算

3
frontend/.bunfig.toml Normal file
View File

@ -0,0 +1,3 @@
[install.lockfile]
save = false

1
frontend/.changelogrc.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@lobehub/lint').changelog;

View File

@ -0,0 +1 @@
module.exports = require('@lobehub/lint').commitlint;

11
frontend/.dockerignore Normal file
View File

@ -0,0 +1,11 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
.next
.git
scripts
docs
.github
*.md
.env.example

16
frontend/.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

106
frontend/.env.example Normal file
View File

@ -0,0 +1,106 @@
# add a access code to lock your lobe-chat application, you can set a long password to avoid leaking. If this value contains a comma, it is a password array.
#ACCESS_CODE=lobe66
# add your custom model name, multi model separate by comma. for example gpt-3.5-1106,gpt-4-1106
# CUSTOM_MODELS=model1,model2,model3
# Specify your API Key selection method, currently supporting `random` and `turn`.
# API_KEY_SELECT_MODE=random
# ---- only choose one from OpenAI Service and Azure OpenAI Service ---- #
########################################
############ OpenAI Service ############
########################################
# you openai api key
OPENAI_API_KEY=sk-xxxxxxxxx
# use a proxy to connect to the OpenAI API
# OPENAI_PROXY_URL=https://api.openai.com/v1
########################################
######### Azure OpenAI Service #########
########################################
# you can learn azure OpenAI Service on https://learn.microsoft.com/en-us/azure/ai-services/openai/overview
# use Azure OpenAI Service by uncomment the following line
# USE_AZURE_OPENAI=1
# The API key you applied for on the Azure OpenAI account page, which can be found in the "Keys and Endpoints" section.
# AZURE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# The endpoint you applied for on the Azure OpenAI account page, which can be found in the "Keys and Endpoints" section.
# OPENAI_PROXY_URL=https://docs-test-001.openai.azure.com
# Azure's API version, follows the YYYY-MM-DD format
# AZURE_API_VERSION=2023-08-01-preview
########################################
############ ZhiPu AI Service ##########
########################################
#ZHIPU_API_KEY=xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxx
########################################
########## Moonshot AI Service #########
########################################
#MOONSHOT_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
########### Google AI Service ##########
########################################
#GOOGLE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
######### AWS Bedrock Service ##########
########################################
#AWS_REGION=us-east-1
#AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxx
#AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
######### Ollama AI Service ##########
########################################
# You can use ollama to get and run LLM locally, learn more about it via https://github.com/ollama/ollama
# The local/remote ollama service url
# OLLAMA_PROXY_URL=http://127.0.0.1:11434/v1
########### Mistral AI Service ##########
########################################
#MISTRAL_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
######### Perplexity Service ##########
########################################
#PERPLEXITY_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
######### Anthropic Service ##########
########################################
#ANTHROPIC_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
########################################
############ Market Service ############
########################################
# The LobeChat agents market index url
# AGENTS_INDEX_URL=https://chat-agents.lobehub.com
########################################
############ Plugin Service ############
########################################
# The LobeChat plugins store index url
# PLUGINS_INDEX_URL=https://chat-plugins.lobehub.com
# set the plugin settings
# the format is `plugin-identifier:key1=value1;key2=value2`, multiple settings fields are separated by semicolons `;`, multiple plugin settings are separated by commas `,`.
# PLUGIN_SETTINGS=search-engine:SERPAPI_API_KEY=xxxxx

32
frontend/.eslintignore Normal file
View File

@ -0,0 +1,32 @@
# Eslintignore for LobeHub
################################################################
# dependencies
node_modules
# ci
coverage
.coverage
# test
jest*
_test_
__test__
*.test.ts
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
!.dumirc.ts
# production
dist
es
lib
logs
# misc
# add other ignore file below
.next

21
frontend/.eslintrc.js Normal file
View File

@ -0,0 +1,21 @@
const config = require('@lobehub/lint').eslint;
config.extends.push('plugin:@next/next/recommended');
config.rules['unicorn/no-negated-condition'] = 0;
config.rules['unicorn/prefer-type-error'] = 0;
config.rules['unicorn/prefer-logical-operator-over-ternary'] = 0;
config.rules['unicorn/no-null'] = 0;
config.rules['unicorn/no-typeof-undefined'] = 0;
config.rules['unicorn/explicit-length-check'] = 0;
config.rules['unicorn/prefer-code-point'] = 0;
config.rules['no-extra-boolean-cast'] = 0;
config.rules['unicorn/no-useless-undefined'] = 0;
config.rules['react/no-unknown-property'] = 0;
config.rules['unicorn/prefer-ternary'] = 0;
config.rules['unicorn/prefer-spread'] = 0;
config.rules['unicorn/catch-error-name'] = 0;
config.rules['unicorn/no-array-for-each'] = 0;
config.rules['unicorn/prefer-number-properties'] = 0;
module.exports = config;

61
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
# Gitignore for LobeHub
################################################################
# general
.DS_Store
.idea
.vscode
.history
.temp
.env.local
venv
temp
tmp
# dependencies
node_modules
*.log
*.lock
package-lock.json
# ci
coverage
.coverage
.eslintcache
.stylelintcache
# production
dist
es
lib
logs
test-output
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
# husky
.husky/prepare-commit-msg
# misc
# add other ignore file below
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
.next
.env
public/*.js
bun.lockb
sitemap*.xml
robots.txt

View File

@ -0,0 +1 @@
npx --no -- commitlint --edit ${1}

View File

@ -0,0 +1,2 @@
npm run type-check
npx --no-install lint-staged

41
frontend/.i18nrc.js Normal file
View File

@ -0,0 +1,41 @@
const { defineConfig } = require('@lobehub/i18n-cli');
module.exports = defineConfig({
entry: 'locales/zh-CN',
entryLocale: 'zh-CN',
output: 'locales',
outputLocales: [
'ar',
'zh-TW',
'en-US',
'ru-RU',
'ja-JP',
'ko-KR',
'fr-FR',
'tr-TR',
'es-ES',
'pt-BR',
'de-DE',
'it-IT',
'nl-NL',
'pl-PL',
'vi-VN',
],
temperature: 0,
modelName: 'gpt-3.5-turbo-1106',
splitToken: 1024,
experimental: {
jsonMode: true,
},
reference: '你需要保持 mdx 的组件格式,输出文本不需要在最外层包裹任何代码块语法',
markdown: {
entry: ['./README.zh-CN.md', './docs/**/*.zh-CN.md', './docs/**/*.zh-CN.mdx'],
entryLocale: 'zh-CN',
entryExtension: '.zh-CN.md',
outputLocales: ['en-US'],
outputExtensions: (locale, { getDefaultExtension }) => {
if (locale === 'en-US') return '.md';
return getDefaultExtension(locale);
},
},
});

14
frontend/.npmrc Normal file
View File

@ -0,0 +1,14 @@
lockfile=false
resolution-mode=highest
enable-pre-post-scripts=true
public-hoist-pattern[]=*@umijs/lint*
public-hoist-pattern[]=*changelog*
public-hoist-pattern[]=*commitlint*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*remark*
public-hoist-pattern[]=*semantic-release*
public-hoist-pattern[]=*stylelint*

1
frontend/.nvmrc Normal file
View File

@ -0,0 +1 @@
lts/hydrogen

63
frontend/.prettierignore Normal file
View File

@ -0,0 +1,63 @@
# Prettierignore for LobeHub
################################################################
# general
.DS_Store
.editorconfig
.idea
.vscode
.history
.temp
.env.local
.husky
.npmrc
.gitkeep
venv
temp
tmp
LICENSE
# dependencies
node_modules
*.log
*.lock
package-lock.json
# ci
coverage
.coverage
.eslintcache
.stylelintcache
test-output
__snapshots__
*.snap
# production
dist
es
lib
logs
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
# ignore files
.*ignore
# docker
docker
Dockerfile*
# image
*.webp
*.gif
*.png
*.jpg
*.svg
# misc
# add other ignore file below
.next

1
frontend/.prettierrc.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@lobehub/lint').prettier;

1
frontend/.releaserc.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@lobehub/lint').semanticRelease;

1
frontend/.remarkrc.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@lobehub/lint').remarklint;

8
frontend/.stylelintrc.js Normal file
View File

@ -0,0 +1,8 @@
const config = require('@lobehub/lint').stylelint;
module.exports = {
...config,
rules: {
'selector-id-pattern': null,
},
};

11709
frontend/CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

128
frontend/CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to participate in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community includes:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
## Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct that could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
[homepage]: https://www.contributor-covenant.org

88
frontend/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,88 @@
# Lobe Chat - Contributing Guide 🌟
We're thrilled that you want to contribute to Lobe Chat, the future of communication! 😄
Lobe Chat is an open-source project, and we welcome your collaboration. Before you jump in, let's make sure you're all set to contribute effectively and have loads of fun along the way!
## Table of Contents
- [Fork the Repository](#fork-the-repository)
- [Clone Your Fork](#clone-your-fork)
- [Create a New Branch](#create-a-new-branch)
- [Code Like a Wizard](#code-like-a-wizard)
- [Committing Your Work](#committing-your-work)
- [Sync with Upstream](#sync-with-upstream)
- [Open a Pull Request](#open-a-pull-request)
- [Review and Collaboration](#review-and-collaboration)
- [Celebrate 🎉](#celebrate-)
## Fork the Repository
🍴 Fork this repository to your GitHub account by clicking the "Fork" button at the top right. This creates a personal copy of the project you can work on.
## Clone Your Fork
📦 Clone your forked repository to your local machine using the `git clone` command:
```bash
git clone https://github.com/YourUsername/lobe-chat.git
```
## Create a New Branch
🌿 Create a new branch for your contribution. This helps keep your work organized and separate from the main codebase.
```bash
git checkout -b your-branch-name
```
Choose a meaningful branch name related to your work. It makes collaboration easier!
## Code Like a Wizard
🧙‍♀️ Time to work your magic! Write your code, fix bugs, or add new features. Be sure to follow our project's coding style. You can check if your code adheres to our style using:
```bash
yarn lint
```
This adds a bit of enchantment to your coding experience! ✨
## Committing Your Work
📝 Ready to save your progress? Commit your changes to your branch.
```bash
git add .
git commit -m "Your meaningful commit message"
```
Please keep your commits focused and clear. And remember to be kind to your fellow contributors; keep your commits concise.
## Sync with Upstream
⚙️ Periodically, sync your forked repository with the original (upstream) repository to stay up-to-date with the latest changes.
```bash
git remote add upstream https://github.com/lobehub/lobe-chat.git
git fetch upstream
git merge upstream/main
```
This ensures you're working on the most current version of Lobe Chat. Stay fresh! 💨
## Open a Pull Request
🚀 Time to share your contribution! Head over to the original Lobe Chat repository and open a Pull Request (PR). Our maintainers will review your work.
## Review and Collaboration
👓 Your PR will undergo thorough review and testing. The maintainers will provide feedback, and you can collaborate to make your contribution even better. We value teamwork!
## Celebrate 🎉
🎈 Congratulations! Your contribution is now part of Lobe Chat. 🥳
Thank you for making Lobe Chat even more magical. We can't wait to see what you create! 🌠
Happy Coding! 🚀🦄

95
frontend/Dockerfile Normal file
View File

@ -0,0 +1,95 @@
FROM node:20-slim AS base
## Sharp dependencies, copy all the files for production
FROM base AS sharp
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
WORKDIR /app
RUN pnpm add sharp
## Install dependencies only when needed
FROM base AS builder
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
WORKDIR /app
COPY package.json ./
# If you want to build docker in China
# RUN npm config set registry https://registry.npmmirror.com/
RUN pnpm i
COPY . .
RUN pnpm run build:docker # run build standalone for docker version
## Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=sharp --chown=nextjs:nodejs /app/node_modules/.pnpm ./node_modules/.pnpm
USER nextjs
EXPOSE 3210
# set hostname to localhost
ENV HOSTNAME "0.0.0.0"
ENV PORT=3210
# General Variables
ENV ACCESS_CODE ""
ENV CUSTOM_MODELS ""
ENV API_KEY_SELECT_MODE ""
# OpenAI
ENV OPENAI_API_KEY ""
ENV OPENAI_PROXY_URL ""
# Azure OpenAI
ENV USE_AZURE_OPENAI ""
ENV AZURE_API_KEY ""
ENV AZURE_API_VERSION ""
# Google
ENV GOOGLE_API_KEY ""
# Zhipu
ENV ZHIPU_API_KEY ""
# Moonshot
ENV MOONSHOT_API_KEY ""
# Ollama
ENV OLLAMA_PROXY_URL ""
# Perplexity
ENV PERPLEXITY_API_KEY ""
# Anthropic
ENV ANTHROPIC_API_KEY ""
# Mistral
ENV MISTRAL_API_KEY ""
CMD ["node", "server.js"]

21
frontend/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 - current LobeHub
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

755
frontend/README.md Normal file
View File

@ -0,0 +1,755 @@
<div align="center"><a name="readme-top"></a>
[![][image-banner]][vercel-link]
# Lobe Chat
An open-source, modern-design ChatGPT/LLMs UI/Framework.<br/>
Supports speech-synthesis, multi-modal, and extensible ([function call][docs-functionc-call]) plugin system.<br/>
One-click **FREE** deployment of your private ChatGPT/Gemini/Ollama chat application.
**English** · [简体中文](./README.zh-CN.md) · [Changelog](./CHANGELOG.md) · [Documents][docs] · [Report Bug][github-issues-link] · [Request Feature][github-issues-link]
<!-- SHIELD GROUP -->
[![][github-release-shield]][github-release-link]
[![][docker-release-shield]][docker-release-link]
[![][vercel-shield]][vercel-link]
[![][discord-shield]][discord-link]<br/>
[![][codecov-shield]][codecov-link]
[![][github-action-test-shield]][github-action-test-link]
[![][github-action-release-shield]][github-action-release-link]
[![][github-releasedate-shield]][github-releasedate-link]<br/>
[![][github-contributors-shield]][github-contributors-link]
[![][github-forks-shield]][github-forks-link]
[![][github-stars-shield]][github-stars-link]
[![][github-issues-shield]][github-issues-link]
[![][github-license-shield]][github-license-link]<br>
[![][sponsor-shield]][sponsor-link]
**Share LobeChat Repository**
[![][share-x-shield]][share-x-link]
[![][share-telegram-shield]][share-telegram-link]
[![][share-whatsapp-shield]][share-whatsapp-link]
[![][share-reddit-shield]][share-reddit-link]
[![][share-weibo-shield]][share-weibo-link]
[![][share-mastodon-shield]][share-mastodon-link]
[![][share-linkedin-shield]][share-linkedin-link]
<sup>Pioneering the new age of thinking and creating. Built for you, the Super Individual.</sup>
[![][github-trending-shield]][github-trending-url]
[![][image-overview]][vercel-link]
</div>
<details>
<summary><kbd>Table of contents</kbd></summary>
#### TOC
- [👋🏻 Getting Started & Join Our Community](#-getting-started--join-our-community)
- [✨ Features](#-features)
- [`1` Multi-Model Service Provider Support](#1-multi-model-service-provider-support)
- [`2` Local Large Language Model (LLM) Support](#2-local-large-language-model-llm-support)
- [`3` Model Visual Recognition](#3-model-visual-recognition)
- [`4` TTS & STT Voice Conversation](#4-tts--stt-voice-conversation)
- [`5` Text to Image Generation](#5-text-to-image-generation)
- [`6` Plugin System (Function Calling)](#6-plugin-system-function-calling)
- [`7` Agent Market (GPTs)](#7-agent-market-gpts)
- [`8` Progressive Web App (PWA)](#8-progressive-web-app-pwa)
- [`9` Mobile Device Adaptation](#9-mobile-device-adaptation)
- [`10` Custom Themes](#10-custom-themes)
- [`*` What's more](#-whats-more)
- [⚡️ Performance](#-performance)
- [🛳 Self Hosting](#-self-hosting)
- [`A` Deploying with Vercel, Zeabur or Sealos](#a-deploying-with-vercel-zeabur-or-sealos)
- [`B` Deploying with Docker](#b-deploying-with-docker)
- [Environment Variable](#environment-variable)
- [📦 Ecosystem](#-ecosystem)
- [🧩 Plugins](#-plugins)
- [⌨️ Local Development](#-local-development)
- [🤝 Contributing](#-contributing)
- [❤️ Sponsor](#-sponsor)
- [🔗 More Products](#-more-products)
####
<br/>
</details>
## 👋🏻 Getting Started & Join Our Community
We are a group of e/acc design-engineers, hoping to provide modern design components and tools for AIGC.
By adopting the Bootstrapping approach, we aim to provide developers and users with a more open, transparent, and user-friendly product ecosystem.
Whether for users or professional developers, LobeHub will be your AI Agent playground. Please be aware that LobeChat is currently under active development, and feedback is welcome for any [issues][issues-link] encountered.
| [![][vercel-shield-badge]][vercel-link] | No installation or registration necessary! Visit our website to experience it firsthand. |
| :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |
| [![][discord-shield-badge]][discord-link] | Join our Discord community! This is where you can connect with developers and other enthusiastic users of LobeHub. |
> \[!IMPORTANT]
>
> **Star Us**, You will receive all release notifications from GitHub without any delay \~ ⭐️
[![][image-star]][github-stars-link]
<details>
<summary><kbd>Star History</kbd></summary>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&theme=dark&type=Date">
<img width="100%" src="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&type=Date">
</picture>
</details>
## ✨ Features
[![][image-feat-privoder]][docs-feat-provider]
### `1` [Multi-Model Service Provider Support][docs-feat-provider]
In the continuous development of LobeChat, we deeply understand the importance of diversity in model service providers for meeting the needs of the community when providing AI conversation services. Therefore, we have expanded our support to multiple model service providers, rather than being limited to a single one, in order to offer users a more diverse and rich selection of conversations.
In this way, LobeChat can more flexibly adapt to the needs of different users, while also providing developers with a wider range of choices.
#### Supported Model Service Providers
We have implemented support for the following model service providers:
- **AWS Bedrock**: Integrated with AWS Bedrock service, supporting models such as **Claude / LLama2**, providing powerful natural language processing capabilities. [Learn more](https://aws.amazon.com/cn/bedrock)
- **Google AI (Gemini Pro, Gemini Vision)**: Access to Google's **Gemini** series models, including Gemini and Gemini Pro, to support advanced language understanding and generation. [Learn more](https://deepmind.google/technologies/gemini/)
- **ChatGLM**: Added the **ChatGLM** series models from Zhipuai (GLM-4/GLM-4-vision/GLM-3-turbo), providing users with another efficient conversation model choice. [Learn more](https://www.zhipuai.cn/)
- **Moonshot AI (Dark Side of the Moon)**: Integrated with the Moonshot series models, an innovative AI startup from China, aiming to provide deeper conversation understanding. [Learn more](https://www.moonshot.cn/)
At the same time, we are also planning to support more model service providers, such as Replicate and Perplexity, to further enrich our service provider library. If you would like LobeChat to support your favorite service provider, feel free to join our [community discussion](https://github.com/lobehub/lobe-chat/discussions/1284).
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-local]][docs-feat-local]
### `2` [Local Large Language Model (LLM) Support][docs-feat-local]
To meet the specific needs of users, LobeChat also supports the use of local models based on [Ollama](https://ollama.ai), allowing users to flexibly use their own or third-party models.
> \[!TIP]
>
> Learn more about [📘 Using Ollama in LobeChat][docs-usage-ollama] by checking it out.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-vision]][docs-feat-vision]
### `3` [Model Visual Recognition][docs-feat-vision]
LobeChat now supports OpenAI's latest [`gpt-4-vision`](https://platform.openai.com/docs/guides/vision) model with visual recognition capabilities,
a multimodal intelligence that can perceive visuals. Users can easily upload or drag and drop images into the dialogue box,
and the agent will be able to recognize the content of the images and engage in intelligent conversation based on this,
creating smarter and more diversified chat scenarios.
This feature opens up new interactive methods, allowing communication to transcend text and include a wealth of visual elements.
Whether it's sharing images in daily use or interpreting images within specific industries, the agent provides an outstanding conversational experience.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-tts]][docs-feat-tts]
### `4` [TTS & STT Voice Conversation][docs-feat-tts]
LobeChat supports Text-to-Speech (TTS) and Speech-to-Text (STT) technologies, enabling our application to convert text messages into clear voice outputs,
allowing users to interact with our conversational agent as if they were talking to a real person. Users can choose from a variety of voices to pair with the agent.
Moreover, TTS offers an excellent solution for those who prefer auditory learning or desire to receive information while busy.
In LobeChat, we have meticulously selected a range of high-quality voice options (OpenAI Audio, Microsoft Edge Speech) to meet the needs of users from different regions and cultural backgrounds.
Users can choose the voice that suits their personal preferences or specific scenarios, resulting in a personalized communication experience.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-t2i]][docs-feat-t2i]
### `5` [Text to Image Generation][docs-feat-t2i]
With support for the latest text-to-image generation technology, LobeChat now allows users to invoke image creation tools directly within conversations with the agent. By leveraging the capabilities of AI tools such as [`DALL-E 3`](https://openai.com/dall-e-3), [`MidJourney`](https://www.midjourney.com/), and [`Pollinations`](https://pollinations.ai/), the agents are now equipped to transform your ideas into images.
This enables a more private and immersive creative process, allowing for the seamless integration of visual storytelling into your personal dialogue with the agent.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-plugin]][docs-feat-plugin]
### `6` [Plugin System (Function Calling)][docs-feat-plugin]
The plugin ecosystem of LobeChat is an important extension of its core functionality, greatly enhancing the practicality and flexibility of the LobeChat assistant.
<video controls src="https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2" muted="false"></video>
By utilizing plugins, LobeChat assistants can obtain and process real-time information, such as searching for web information and providing users with instant and relevant news.
In addition, these plugins are not limited to news aggregation, but can also extend to other practical functions, such as quickly searching documents, generating images, obtaining data from various platforms like Bilibili, Steam, and interacting with various third-party services.
> \[!TIP]
>
> Learn more about [📘 Plugin Usage][docs-usage-plugin] by checking it out.
<!-- PLUGIN LIST -->
| Recent Submits | Description |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Charts & Diagrams](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **pyxl** on **2024-02-05**</sup> | Mermaid Diagrams, Schemes for Presentations, Analysis, research websites, pie charts.<br/>`chart` `diagram` |
| [Social Search](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-02-02**</sup> | The Social Search provides access to tweets, users, followers, images, media and more.<br/>`social` `twitter` `x` `search` |
| [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | Get realtime crypto price, BTC, ETH, BNB, and the latest insights.The latest coin news and airdrop opportunities.<br/>`crypto` `btc` `eth` `bnb` |
| [Bilibili](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | Dive into Bilibili's vast content with features like keyword video search, replay access, interactive danmaku, trending video recommendations, and hot-search insights, all at your fingertips.<br/>`video` `bilibili` `search` |
> 📊 Total plugins: [<kbd>**58**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
<!-- PLUGIN LIST -->
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-agent]][docs-feat-agent]
### `7` [Agent Market (GPTs)][docs-feat-agent]
In LobeChat Agent Marketplace, creators can discover a vibrant and innovative community that brings together a multitude of well-designed agents,
which not only play an important role in work scenarios but also offer great convenience in learning processes.
Our marketplace is not just a showcase platform but also a collaborative space. Here, everyone can contribute their wisdom and share the agents they have developed.
> \[!TIP]
>
> By [🤖/🏪 Submit Agents][submit-agents-link], you can easily submit your agent creations to our platform.
> Importantly, LobeChat has established a sophisticated automated internationalization (i18n) workflow,
> capable of seamlessly translating your agent into multiple language versions.
> This means that no matter what language your users speak, they can experience your agent without barriers.
> \[!IMPORTANT]
>
> We welcome all users to join this growing ecosystem and participate in the iteration and optimization of agents.
> Together, we can create more interesting, practical, and innovative agents, further enriching the diversity and practicality of the agent offerings.
<!-- AGENT LIST -->
| Recent Submits | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [日程管理助手](https://chat-preview.lobehub.com/market?agent=calendar-manager)<br/><sup>By **[ccdanpian](https://github.com/ccdanpian)** on **2024-03-07**</sup> | 日程管理助手,调用时间插件,处理新增、查询、删除日程请求,支持多种操作和提醒。<br/>`日程管理` `时间插件` `新增日程` `查询日程` `删除日程` |
| [Business Email Writing Expert](https://chat-preview.lobehub.com/market?agent=business-email)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2024-03-06**</sup> | Business email writing expert specializing in bilingual business emails in Chinese and English, cross-cultural communication, and engagement in the GitHub open-source community.<br/>`business-email-writing` `business-cooperation` `business-authorization` `cross-cultural-communication` `git-hub-and-open-source-community` |
| [Discord Style Copywriting Expert](https://chat-preview.lobehub.com/market?agent=discord-copywriting)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2024-03-06**</sup> | A copywriting expert in Discord style, prioritizing humor and user experience, specializing in personalized software copywriting.<br/>`copywriting` `creation` `user-experience` `humor` `software-system` |
| [AI Image Prompt Architect](https://chat-preview.lobehub.com/market?agent=9-somboon)<br/><sup>By **[9Somboon](https://github.com/9Somboon)** on **2024-03-05**</sup> | Specialises in creating detailed prompts for AI image generation.<br/>`stable-diffusion` `ai-image-generation` `prompts` `photography` `creative` `art` |
> 📊 Total agents: [<kbd>**199**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
<!-- AGENT LIST -->
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-pwa]][docs-feat-pwa]
### `8` [Progressive Web App (PWA)][docs-feat-pwa]
We deeply understand the importance of providing a seamless experience for users in today's multi-device environment.
Therefore, we have adopted Progressive Web Application ([PWA](https://support.google.com/chrome/answer/9658361)) technology,
a modern web technology that elevates web applications to an experience close to that of native apps.
Through PWA, LobeChat can offer a highly optimized user experience on both desktop and mobile devices while maintaining its lightweight and high-performance characteristics.
Visually and in terms of feel, we have also meticulously designed the interface to ensure it is indistinguishable from native apps,
providing smooth animations, responsive layouts, and adapting to different device screen resolutions.
> \[!NOTE]
>
> If you are unfamiliar with the installation process of PWA, you can add LobeChat as your desktop application (also applicable to mobile devices) by following these steps:
>
> - Launch the Chrome or Edge browser on your computer.
> - Visit the LobeChat webpage.
> - In the upper right corner of the address bar, click on the <kbd>Install</kbd> icon.
> - Follow the instructions on the screen to complete the PWA Installation.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-mobile]][docs-feat-mobile]
### `9` [Mobile Device Adaptation][docs-feat-mobile]
We have carried out a series of optimization designs for mobile devices to enhance the user's mobile experience. Currently, we are iterating on the mobile user experience to achieve smoother and more intuitive interactions. If you have any suggestions or ideas, we welcome you to provide feedback through GitHub Issues or Pull Requests.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-theme]][docs-feat-theme]
### `10` [Custom Themes][docs-feat-theme]
As a design-engineering-oriented application, LobeChat places great emphasis on users' personalized experiences,
hence introducing flexible and diverse theme modes, including a light mode for daytime and a dark mode for nighttime.
Beyond switching theme modes, a range of color customization options allow users to adjust the application's theme colors according to their preferences.
Whether it's a desire for a sober dark blue, a lively peach pink, or a professional gray-white, users can find their style of color choices in LobeChat.
> \[!TIP]
>
> The default configuration can intelligently recognize the user's system color mode and automatically switch themes to ensure a consistent visual experience with the operating system.
> For users who like to manually control details, LobeChat also offers intuitive setting options and a choice between chat bubble mode and document mode for conversation scenarios.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
### `*` What's more
Beside these features, LobeChat also have much better basic technique underground:
- [x] 💨 **Quick Deployment**: Using the Vercel platform or docker image, you can deploy with just one click and complete the process within 1 minute without any complex configuration.
- [x] 🌐 **Custom Domain**: If users have their own domain, they can bind it to the platform for quick access to the dialogue agent from anywhere.
- [x] 🔒 **Privacy Protection**: All data is stored locally in the user's browser, ensuring user privacy.
- [x] 💎 **Exquisite UI Design**: With a carefully designed interface, it offers an elegant appearance and smooth interaction. It supports light and dark themes and is mobile-friendly. PWA support provides a more native-like experience.
- [x] 🗣️ **Smooth Conversation Experience**: Fluid responses ensure a smooth conversation experience. It fully supports Markdown rendering, including code highlighting, LaTex formulas, Mermaid flowcharts, and more.
> ✨ more features will be added when LobeChat evolve.
---
> \[!NOTE]
>
> You can find our upcoming [Roadmap][github-project-link] plans in the Projects section.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ⚡️ Performance
> \[!NOTE]
>
> The complete list of reports can be found in the [📘 Lighthouse Reports][docs-lighthouse]
| Desktop | Mobile |
| :-----------------------------------------: | :----------------------------------------: |
| ![][chat-desktop] | ![][chat-mobile] |
| [📑 Lighthouse Report][chat-desktop-report] | [📑 Lighthouse Report][chat-mobile-report] |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🛳 Self Hosting
LobeChat provides Self-Hosted Version with Vercel and [Docker Image][docker-release-link]. This allows you to deploy your own chatbot within a few minutes without any prior knowledge.
> \[!TIP]
>
> Learn more about [📘 Build your own LobeChat][docs-self-hosting] by checking it out.
### `A` Deploying with Vercel, Zeabur or Sealos
If you want to deploy this service yourself on either Vercel or Zeabur, you can follow these steps:
- Prepare your [OpenAI API Key](https://platform.openai.com/account/api-keys).
- Click the button below to start deployment: Log in directly with your GitHub account, and remember to fill in the `OPENAI_API_KEY`(required) and `ACCESS_CODE` (recommended) on the environment variable section.
- After deployment, you can start using it.
- Bind a custom domain (optional): The DNS of the domain assigned by Vercel is polluted in some areas; binding a custom domain can connect directly.
<div align="center">
| Deploy with Vercel | Deploy with Zeabur | Deploy with Sealos |
| :-------------------------------------: | :---------------------------------------------------------: | :---------------------------------------------------------: |
| [![][deploy-button-image]][deploy-link] | [![][deploy-on-zeabur-button-image]][deploy-on-zeabur-link] | [![][deploy-on-sealos-button-image]][deploy-on-sealos-link] |
</div>
#### After Fork
After fork, only retain the upstream sync action and disable other actions in your repository on GitHub.
#### Keep Updated
If you have deployed your own project following the one-click deployment steps in the README, you might encounter constant prompts indicating "updates available." This is because Vercel defaults to creating a new project instead of forking this one, resulting in an inability to detect updates accurately.
> \[!TIP]
>
> We suggest you redeploy using the following steps, [📘 Auto Sync With Latest][docs-upstream-sync]
<br/>
### `B` Deploying with Docker
[![][docker-release-shield]][docker-release-link]
[![][docker-size-shield]][docker-size-link]
[![][docker-pulls-shield]][docker-pulls-link]
We provide a Docker image for deploying the LobeChat service on your own private device. Use the following command to start the LobeChat service:
```fish
$ docker run -d -p 3210:3210 \
-e OPENAI_API_KEY=sk-xxxx \
-e ACCESS_CODE=lobe66 \
--name lobe-chat \
lobehub/lobe-chat
```
> \[!TIP]
>
> If you need to use the OpenAI service through a proxy, you can configure the proxy address using the `OPENAI_PROXY_URL` environment variable:
```fish
$ docker run -d -p 3210:3210 \
-e OPENAI_API_KEY=sk-xxxx \
-e OPENAI_PROXY_URL=https://api-proxy.com/v1 \
-e ACCESS_CODE=lobe66 \
--name lobe-chat \
lobehub/lobe-chat
```
> \[!NOTE]
>
> For detailed instructions on deploying with Docker, please refer to the [📘 Docker Deployment Guide][docs-docker]
<br/>
### Environment Variable
This project provides some additional configuration items set with environment variables:
| Environment Variable | Required | Description | Example |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `OPENAI_API_KEY` | Yes | This is the API key you apply on the OpenAI account page | `sk-xxxxxx...xxxxxx` |
| `OPENAI_PROXY_URL` | No | If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL | `https://api.chatanywhere.cn` or `https://aihubmix.com/v1` <br/>The default value is<br/>`https://api.openai.com/v1` |
| `ACCESS_CODE` | No | Add a password to access this service; you can set a long password to avoid leaking. If this value contains a comma, it is a password array. | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` |
| `CUSTOM_MODELS` | No | Used to control the model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model, separated by commas. | `qwen-7b-chat,+glm-6b,-gpt-3.5-turbo` |
> \[!NOTE]
>
> The complete list of environment variables can be found in the [📘 Environment Variables][docs-env-var]
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 📦 Ecosystem
| NPM | Repository | Description | Version |
| --------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| [@lobehub/ui][lobe-ui-link] | [lobehub/lobe-ui][lobe-ui-github] | Open-source UI component library dedicated to building AIGC web applications. | [![][lobe-ui-shield]][lobe-ui-link] |
| [@lobehub/icons][lobe-icons-link] | [lobehub/lobe-icons][lobe-icons-github] | Popular AI / LLM Model Brand SVG Logo and Icon Collection. | [![][lobe-icons-shield]][lobe-icons-link] |
| [@lobehub/tts][lobe-tts-link] | [lobehub/lobe-tts][lobe-tts-github] | High-quality & reliable TTS/STT React Hooks library | [![][lobe-tts-shield]][lobe-tts-link] |
| [@lobehub/lint][lobe-lint-link] | [lobehub/lobe-lint][lobe-lint-github] | Configurations for ESlint, Stylelint, Commitlint, Prettier, Remark, and Semantic Release for LobeHub. | [![][lobe-lint-shield]][lobe-lint-link] |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🧩 Plugins
Plugins provide a means to extend the [Function Calling][docs-functionc-call] capabilities of LobeChat. They can be used to introduce new function calls and even new ways to render message results. If you are interested in plugin development, please refer to our [📘 Plugin Development Guide][docs-plugin-dev] in the Wiki.
- [lobe-chat-plugins][lobe-chat-plugins]: This is the plugin index for LobeChat. It accesses index.json from this repository to display a list of available plugins for LobeChat to the user.
- [chat-plugin-template][chat-plugin-template]: This is the plugin template for LobeChat plugin development.
- [@lobehub/chat-plugin-sdk][chat-plugin-sdk]: The LobeChat Plugin SDK assists you in creating exceptional chat plugins for Lobe Chat.
- [@lobehub/chat-plugins-gateway][chat-plugins-gateway]: The LobeChat Plugins Gateway is a backend service that provides a gateway for LobeChat plugins. We deploy this service using Vercel. The primary API POST /api/v1/runner is deployed as an Edge Function.
> \[!NOTE]
>
> The plugin system is currently undergoing major development. You can learn more in the following issues:
>
> - [x] [**Plugin Phase 1**](https://github.com/lobehub/lobe-chat/issues/73): Implement separation of the plugin from the main body, split the plugin into an independent repository for maintenance, and realize dynamic loading of the plugin.
> - [x] [**Plugin Phase 2**](https://github.com/lobehub/lobe-chat/issues/97): The security and stability of the plugin's use, more accurately presenting abnormal states, the maintainability of the plugin architecture, and developer-friendly.
> - [x] [**Plugin Phase 3**](https://github.com/lobehub/lobe-chat/issues/149): Higher-level and more comprehensive customization capabilities, support for plugin authentication, and examples.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ⌨️ Local Development
You can use GitHub Codespaces for online development:
[![][codespaces-shield]][codespaces-link]
Or clone it for local development:
```fish
$ git clone https://github.com/lobehub/lobe-chat.git
$ cd lobe-chat
$ pnpm install
$ pnpm dev
```
If you would like to learn more details, please feel free to look at our [📘 Development Guide][docs-dev-guide].
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🤝 Contributing
Contributions of all types are more than welcome; if you are interested in contributing code, feel free to check out our GitHub [Issues][github-issues-link] and [Projects][github-project-link] to get stuck in to show us what youre made of.
> \[!TIP]
>
> We are creating a technology-driven forum, fostering knowledge interaction and the exchange of ideas that may culminate in mutual inspiration and collaborative innovation.
>
> Help us make LobeChat better. Welcome to provide product design feedback, user experience discussions directly to us.
>
> **Principal Maintainers:** [@arvinxx](https://github.com/arvinxx) [@canisminor1990](https://github.com/canisminor1990)
[![][pr-welcome-shield]][pr-welcome-link]
[![][submit-agents-shield]][submit-agents-link]
[![][submit-plugin-shield]][submit-plugin-link]
<a href="https://github.com/lobehub/lobe-chat/graphs/contributors" target="_blank">
<table>
<tr>
<th colspan="2">
<br><img src="https://contrib.rocks/image?repo=lobehub/lobe-chat"><br><br>
</th>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=light">
</picture>
</td>
<td rowspan="2">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=4x7&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=4x7&color_scheme=light">
</picture>
</td>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=light">
</picture>
</td>
</tr>
</table>
</a>
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ❤️ Sponsor
Every bit counts and your one-time donation sparkles in our galaxy of support! You're a shooting star, making a swift and bright impact on our journey. Thank you for believing in us your generosity guides us toward our mission, one brilliant flash at a time.
<a href="https://opencollective.com/lobehub" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/lobehub/.github/blob/main/static/sponsor-dark.png?raw=true">
<img src="https://github.com/lobehub/.github/blob/main/static/sponsor-light.png?raw=true">
</picture>
</a>
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🔗 More Products
- **[🅰️ Lobe SD Theme][lobe-theme]:** Modern theme for Stable Diffusion WebUI, exquisite interface design, highly customizable UI, and efficiency-boosting features.
- **[⛵️ Lobe Midjourney WebUI][lobe-midjourney-webui]:** WebUI for Midjourney, leverages AI to quickly generate a wide array of rich and diverse images from text prompts, sparking creativity and enhancing conversations.
- **[🌏 Lobe i18n][lobe-i18n] :** Lobe i18n is an automation tool for the i18n (internationalization) translation process, powered by ChatGPT. It supports features such as automatic splitting of large files, incremental updates, and customization options for the OpenAI model, API proxy, and temperature.
- **[💌 Lobe Commit][lobe-commit]:** Lobe Commit is a CLI tool that leverages Langchain/ChatGPT to generate Gitmoji-based commit messages.
<div align="right">
[![][back-to-top]](#readme-top)
</div>
---
<details><summary><h4>📝 License</h4></summary>
[![][fossa-license-shield]][fossa-license-link]
</details>
Copyright © 2023 [LobeHub][profile-link]. <br />
This project is [MIT](./LICENSE) licensed.
<!-- LINK GROUP -->
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/chat_preview_lobehub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/chat_preview_lobehub_com_chat.html
[chat-plugin-sdk]: https://github.com/lobehub/chat-plugin-sdk
[chat-plugin-template]: https://github.com/lobehub/chat-plugin-template
[chat-plugins-gateway]: https://github.com/lobehub/chat-plugins-gateway
[codecov-link]: https://codecov.io/gh/lobehub/lobe-chat
[codecov-shield]: https://img.shields.io/codecov/c/github/lobehub/lobe-chat?labelColor=black&style=flat-square&logo=codecov&logoColor=white
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg
[deploy-button-image]: https://vercel.com/button
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-on-sealos-button-image]: https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg
[deploy-on-sealos-link]: https://cloud.sealos.io/?openapp=system-template%3FtemplateName%3Dlobe-chat
[deploy-on-zeabur-button-image]: https://zeabur.com/button.svg
[deploy-on-zeabur-link]: https://zeabur.com/templates/VZGGTI
[discord-link]: https://discord.gg/AYFPHvv2jT
[discord-shield]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square
[discord-shield-badge]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=for-the-badge
[docker-pulls-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-pulls-shield]: https://img.shields.io/docker/pulls/lobehub/lobe-chat?color=45cc11&labelColor=black&style=flat-square
[docker-release-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-release-shield]: https://img.shields.io/docker/v/lobehub/lobe-chat?color=369eff&label=docker&labelColor=black&logo=docker&logoColor=white&style=flat-square
[docker-size-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-size-shield]: https://img.shields.io/docker/image-size/lobehub/lobe-chat?color=369eff&labelColor=black&style=flat-square
[docs]: https://chat-docs.lobehub.com/en
[docs-dev-guide]: https://github.com/lobehub/lobe-chat/wiki/index
[docs-docker]: https://chat-docs.lobehub.com/en/self-hosting/platform/docker
[docs-env-var]: https://chat-docs.lobehub.com/en/self-hosting/environment-variables
[docs-feat-agent]: https://chat-docs.lobehub.com/en/usage/features/agent-market
[docs-feat-local]: https://chat-docs.lobehub.com/en/usage/features/local-llm
[docs-feat-mobile]: https://chat-docs.lobehub.com/en/usage/features/mobile
[docs-feat-plugin]: https://chat-docs.lobehub.com/en/usage/features/plugin-system
[docs-feat-provider]: https://chat-docs.lobehub.com/en/usage/features/multi-ai-providers
[docs-feat-pwa]: https://chat-docs.lobehub.com/en/usage/features/pwa
[docs-feat-t2i]: https://chat-docs.lobehub.com/en/usage/features/text-to-image
[docs-feat-theme]: https://chat-docs.lobehub.com/en/usage/features/theme
[docs-feat-tts]: https://chat-docs.lobehub.com/en/usage/features/tts
[docs-feat-vision]: https://chat-docs.lobehub.com/en/usage/features/vision
[docs-functionc-call]: https://platform.openai.com/docs/guides/function-calling
[docs-lighthouse]: https://github.com/lobehub/lobe-chat/wiki/Lighthouse
[docs-plugin-dev]: https://chat-docs.lobehub.com/en/usage/plugins/development
[docs-self-hosting]: https://chat-docs.lobehub.com/en/self-hosting/start
[docs-upstream-sync]: https://chat-docs.lobehub.com/en/self-hosting/advanced/upstream-sync
[docs-usage-ollama]: https://chat-docs.lobehub.com/en/usage/providers/ollama
[docs-usage-plugin]: https://chat-docs.lobehub.com/en/usage/plugins/basic
[fossa-license-link]: https://app.fossa.com/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat
[fossa-license-shield]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat.svg?type=large
[github-action-release-link]: https://github.com/actions/workflows/lobehub/lobe-chat/release.yml
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/lobe-chat/release.yml?label=release&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
[github-action-test-link]: https://github.com/actions/workflows/lobehub/lobe-chat/test.yml
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/lobe-chat/test.yml?label=test&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
[github-contributors-link]: https://github.com/lobehub/lobe-chat/graphs/contributors
[github-contributors-shield]: https://img.shields.io/github/contributors/lobehub/lobe-chat?color=c4f042&labelColor=black&style=flat-square
[github-forks-link]: https://github.com/lobehub/lobe-chat/network/members
[github-forks-shield]: https://img.shields.io/github/forks/lobehub/lobe-chat?color=8ae8ff&labelColor=black&style=flat-square
[github-issues-link]: https://github.com/lobehub/lobe-chat/issues
[github-issues-shield]: https://img.shields.io/github/issues/lobehub/lobe-chat?color=ff80eb&labelColor=black&style=flat-square
[github-license-link]: https://github.com/lobehub/lobe-chat/blob/main/LICENSE
[github-license-shield]: https://img.shields.io/github/license/lobehub/lobe-chat?color=white&labelColor=black&style=flat-square
[github-project-link]: https://github.com/lobehub/lobe-chat/projects
[github-release-link]: https://github.com/lobehub/lobe-chat/releases
[github-release-shield]: https://img.shields.io/github/v/release/lobehub/lobe-chat?color=369eff&labelColor=black&logo=github&style=flat-square
[github-releasedate-link]: https://github.com/lobehub/lobe-chat/releases
[github-releasedate-shield]: https://img.shields.io/github/release-date/lobehub/lobe-chat?labelColor=black&style=flat-square
[github-stars-link]: https://github.com/lobehub/lobe-chat/network/stargazers
[github-stars-shield]: https://img.shields.io/github/stars/lobehub/lobe-chat?color=ffcb47&labelColor=black&style=flat-square
[github-trending-shield]: https://trendshift.io/api/badge/repositories/2256
[github-trending-url]: https://trendshift.io/repositories/2256
[image-banner]: https://github.com/lobehub/lobe-chat/assets/28616219/9f155dff-4737-429f-9cad-a70a1a860c5f
[image-feat-agent]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/268670869-f1ffbf66-42b6-42cf-a937-9ce1f8328514.png
[image-feat-local]: https://github.com/lobehub/lobe-chat/assets/28616219/ca9a21bc-ea6c-4c90-bf4a-fa53b4fb2b5c
[image-feat-mobile]: https://gw.alipayobjects.com/zos/kitchen/R441AuFS4W/mobile.webp
[image-feat-plugin]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/268670883-33c43a5c-a512-467e-855c-fa299548cce5.png
[image-feat-privoder]: https://github.com/lobehub/lobe-chat/assets/28616219/b164bc54-8ba2-4c1e-b2f2-f4d7f7e7a551
[image-feat-pwa]: https://gw.alipayobjects.com/zos/kitchen/69x6bllkX3/pwa.webp
[image-feat-t2i]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/297746445-0ff762b9-aa08-4337-afb7-12f932b6efbb.png
[image-feat-theme]: https://gw.alipayobjects.com/zos/kitchen/pvus1lo%26Z7/darkmode.webp
[image-feat-tts]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/284072124-c9853d8d-f1b5-44a8-a305-45ebc0f6d19a.png
[image-feat-vision]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/284072129-382bdf30-e3d6-4411-b5a0-249710b8ba08.png
[image-overview]: https://github.com/lobehub/lobe-chat/assets/28616219/8b04c3c9-3d71-4fb4-bd9b-a4f415c5876d
[image-star]: https://github.com/lobehub/lobe-chat/assets/17870709/cb06b748-513f-47c2-8740-d876858d7855
[issues-link]: https://img.shields.io/github/issues/lobehub/lobe-chat.svg?style=flat
[lobe-chat-plugins]: https://github.com/lobehub/lobe-chat-plugins
[lobe-commit]: https://github.com/lobehub/lobe-commit/tree/master/packages/lobe-commit
[lobe-i18n]: https://github.com/lobehub/lobe-commit/tree/master/packages/lobe-i18n
[lobe-icons-github]: https://github.com/lobehub/lobe-icons
[lobe-icons-link]: https://www.npmjs.com/package/@lobehub/icons
[lobe-icons-shield]: https://img.shields.io/npm/v/@lobehub/icons?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-lint-github]: https://github.com/lobehub/lobe-lint
[lobe-lint-link]: https://www.npmjs.com/package/@lobehub/lint
[lobe-lint-shield]: https://img.shields.io/npm/v/@lobehub/lint?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-midjourney-webui]: https://github.com/lobehub/lobe-midjourney-webui
[lobe-theme]: https://github.com/lobehub/sd-webui-lobe-theme
[lobe-tts-github]: https://github.com/lobehub/lobe-tts
[lobe-tts-link]: https://www.npmjs.com/package/@lobehub/tts
[lobe-tts-shield]: https://img.shields.io/npm/v/@lobehub/tts?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-ui-github]: https://github.com/lobehub/lobe-ui
[lobe-ui-link]: https://www.npmjs.com/package/@lobehub/ui
[lobe-ui-shield]: https://img.shields.io/npm/v/@lobehub/ui?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[pr-welcome-link]: https://github.com/lobehub/lobe-chat/pulls
[pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge
[profile-link]: https://github.com/lobehub
[share-linkedin-link]: https://linkedin.com/feed
[share-linkedin-shield]: https://img.shields.io/badge/-share%20on%20linkedin-black?labelColor=black&logo=linkedin&logoColor=white&style=flat-square
[share-mastodon-link]: https://mastodon.social/share?text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source,%20extensible%20(Function%20Calling),%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT/LLM%20web%20application.%20https://github.com/lobehub/lobe-chat%20#chatbot%20#chatGPT%20#openAI
[share-mastodon-shield]: https://img.shields.io/badge/-share%20on%20mastodon-black?labelColor=black&logo=mastodon&logoColor=white&style=flat-square
[share-reddit-link]: https://www.reddit.com/submit?title=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-reddit-shield]: https://img.shields.io/badge/-share%20on%20reddit-black?labelColor=black&logo=reddit&logoColor=white&style=flat-square
[share-telegram-link]: https://t.me/share/url"?text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-telegram-shield]: https://img.shields.io/badge/-share%20on%20telegram-black?labelColor=black&logo=telegram&logoColor=white&style=flat-square
[share-weibo-link]: http://service.weibo.com/share/share.php?sharesource=weibo&title=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-weibo-shield]: https://img.shields.io/badge/-share%20on%20weibo-black?labelColor=black&logo=sinaweibo&logoColor=white&style=flat-square
[share-whatsapp-link]: https://api.whatsapp.com/send?text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.%20https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat%20%23chatbot%20%23chatGPT%20%23openAI
[share-whatsapp-shield]: https://img.shields.io/badge/-share%20on%20whatsapp-black?labelColor=black&logo=whatsapp&logoColor=white&style=flat-square
[share-x-link]: https://x.com/intent/tweet?hashtags=chatbot%2CchatGPT%2CopenAI&text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-x-shield]: https://img.shields.io/badge/-share%20on%20x-black?labelColor=black&logo=x&logoColor=white&style=flat-square
[sponsor-link]: https://opencollective.com/lobehub 'Become ❤️ LobeHub Sponsor'
[sponsor-shield]: https://img.shields.io/badge/-Sponsor%20LobeHub-f04f88?logo=opencollective&logoColor=white&style=flat-square
[submit-agents-link]: https://github.com/lobehub/lobe-chat-agents
[submit-agents-shield]: https://img.shields.io/badge/🤖/🏪_submit_agent-%E2%86%92-c4f042?labelColor=black&style=for-the-badge
[submit-plugin-link]: https://github.com/lobehub/lobe-chat-plugins
[submit-plugin-shield]: https://img.shields.io/badge/🧩/🏪_submit_plugin-%E2%86%92-95f3d9?labelColor=black&style=for-the-badge
[vercel-link]: https://chat-preview.lobehub.com
[vercel-shield]: https://img.shields.io/website?down_message=offline&label=vercel&labelColor=black&logo=vercel&style=flat-square&up_message=online&url=https%3A%2F%2Fchat-preview.lobehub.com
[vercel-shield-badge]: https://img.shields.io/website?down_message=offline&label=try%20lobechat&labelColor=black&logo=vercel&style=for-the-badge&up_message=online&url=https%3A%2F%2Fchat-preview.lobehub.com

775
frontend/README.zh-CN.md Normal file
View File

@ -0,0 +1,775 @@
<div align="center"><a name="readme-top"></a>
[![][image-banner]][vercel-link]
<h1>Lobe Chat</h1>
开源、现代化设计的 ChatGPT/LLMs 聊天应用与开发框架<br/>
支持语音合成、多模态、可扩展的([function call][docs-functionc-call])插件系统<br/>
一键**免费**拥有你自己的 ChatGPT/Gemini/Ollama 应用
[English](./README.md) · **简体中文** · [更新日志](./CHANGELOG.md) · [文档][github-document-link] · [报告问题][github-issues-link] · [请求功能][github-issues-link]
<!-- SHIELD GROUP -->
[![][github-release-shield]][github-release-link]
[![][docker-release-shield]][docker-release-link]
[![][vercel-shield]][vercel-link]
[![][discord-shield]][discord-link]<br/>
[![][codecov-shield]][codecov-link]
[![][github-action-test-shield]][github-action-test-link]
[![][github-action-release-shield]][github-action-release-link]
[![][github-releasedate-shield]][github-releasedate-link]<br/>
[![][github-contributors-shield]][github-contributors-link]
[![][github-forks-shield]][github-forks-link]
[![][github-stars-shield]][github-stars-link]
[![][github-issues-shield]][github-issues-link]
[![][github-license-shield]][github-license-link]<br>
[![][sponsor-shield]][sponsor-link]
**分享 LobeChat 给你的好友**
[![][share-x-shield]][share-x-link]
[![][share-telegram-shield]][share-telegram-link]
[![][share-whatsapp-shield]][share-whatsapp-link]
[![][share-reddit-shield]][share-reddit-link]
[![][share-weibo-shield]][share-weibo-link]
[![][share-mastodon-shield]][share-mastodon-link]
<sup>探索私人生产力的未来。在个体崛起的时代中为你打造.</sup>
[![][github-trending-shield]][github-trending-url]
[![][image-overview]][vercel-link]
</div>
<details>
<summary><kbd>目录树</kbd></summary>
#### TOC
- [👋🏻 开始使用 & 交流](#-开始使用--交流)
- [✨ 特性一览](#-特性一览)
- [`1` 多模型服务商支持](#1-多模型服务商支持)
- [`2` 支持本地大语言模型 (LLM)](#2-支持本地大语言模型-llm)
- [`3` 模型视觉识别 (Model Visual)](#3-模型视觉识别-model-visual)
- [`4` TTS & STT 语音会话](#4-tts--stt-语音会话)
- [`5` Text to Image 文生图](#5-text-to-image-文生图)
- [`6` 插件系统 (Function Calling)](#6-插件系统-function-calling)
- [`7` 助手市场 (GPTs)](#7-助手市场-gpts)
- [`8` 渐进式 Web 应用 (PWA)](#8-渐进式-web-应用-pwa)
- [`9` 移动设备适配](#9-移动设备适配)
- [`10` 自定义主题](#10-自定义主题)
- [更多特性](#更多特性)
- [⚡️ 性能测试](#-性能测试)
- [🛳 开箱即用](#-开箱即用)
- [`A` 使用 Vercel、Zeabur 或 Sealos 部署](#a-使用-vercelzeabur-或-sealos-部署)
- [`B` 使用 Docker 部署](#b-使用-docker-部署)
- [环境变量](#环境变量)
- [获取 OpenAI API Key](#获取-openai-api-key)
- [📦 生态系统](#-生态系统)
- [🧩 插件体系](#-插件体系)
- [⌨️ 本地开发](#-本地开发)
- [🤝 参与贡献](#-参与贡献)
- [❤ 社区赞助](#-社区赞助)
- [🔗 更多工具](#-更多工具)
####
<br/>
</details>
## 👋🏻 开始使用 & 交流
我们是一群充满热情的设计工程师,希望为 AIGC 提供现代化的设计组件和工具,并以开源的方式分享。
同时通过 Bootstrapping 的方式,我们希望能够为开发者和用户提供一个更加开放、更加透明友好的产品生态。
不论普通用户与专业开发者 LobeHub 旨在成为所有人的 AI Agent 实验场LobeChat 目前正在积极开发中,有需求或者问题,欢迎提交 [issues][issues-link]
| [![][vercel-shield-badge]][vercel-link] | 无需安装或注册!访问我们的网站,快速体验 |
| :---------------------------------------- | :--------------------------------------------------------------------------- |
| [![][discord-shield-badge]][discord-link] | 加入我们的 Discord 社区!这是你可以与开发者和其他 LobeHub 热衷用户交流的地方 |
> \[!IMPORTANT]
>
> **收藏项目**,你将从 GitHub 上无延迟地接收所有发布通知~⭐️
[![][image-star]][github-stars-link]
<details><summary><kbd>Star History</kbd></summary>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&theme=dark&type=Date">
<img src="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&type=Date">
</picture>
</details>
## ✨ 特性一览
[![][image-feat-privoder]][docs-feat-provider]
### `1` [多模型服务商支持][docs-feat-provider]
在 LobeChat 的不断发展过程中,我们深刻理解到在提供 AI 会话服务时模型服务商的多样性对于满足社区需求的重要性。因此,我们不再局限于单一的模型服务商,而是拓展了对多种模型服务商的支持,以便为用户提供更为丰富和多样化的会话选择。
通过这种方式LobeChat 能够更灵活地适应不同用户的需求,同时也为开发者提供了更为广泛的选择空间。
#### 已支持的模型服务商
我们已经实现了对以下模型服务商的支持:
- **AWS Bedrock**:集成了 AWS Bedrock 服务,支持了 **Claude / LLama2** 等模型,提供了强大的自然语言处理能力。[了解更多](https://aws.amazon.com/cn/bedrock)
- **Google AI (Gemini Pro、Gemini Vision)**:接入了 Google 的 **Gemini** 系列模型,包括 Gemini 和 Gemini Pro以支持更高级的语言理解和生成。[了解更多](https://deepmind.google/technologies/gemini/)
- **ChatGLM**:加入了智谱的 **ChatGLM** 系列模型GLM-4/GLM-4-vision/GLM-3-turbo为用户提供了另一种高效的会话模型选择。[了解更多](https://www.zhipuai.cn/)
- **Moonshot AI (月之暗面)**:集成了 Moonshot 系列模型,这是一家来自中国的创新性 AI 创业公司,旨在提供更深层次的会话理解。[了解更多](https://www.moonshot.cn/)
同时,我们也在计划支持更多的模型服务商,如 Replicate 和 Perplexity 等,以进一步丰富我们的服务商库。如果你希望让 LobeChat 支持你喜爱的服务商,欢迎加入我们的[社区讨论](https://github.com/lobehub/lobe-chat/discussions/1284)。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-local]][docs-feat-local]
### `2` [支持本地大语言模型 (LLM)][docs-feat-local]
为了满足特定用户的需求LobeChat 还基于 [Ollama](https://ollama.ai) 支持了本地模型的使用,让用户能够更灵活地使用自己的或第三方的模型。
> \[!TIP]
>
> 查阅 [📘 在 LobeChat 中使用 Ollama][docs-usage-ollama] 获得更多信息
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-vision]][docs-feat-vision]
### `3` [模型视觉识别 (Model Visual)][docs-feat-vision]
LobeChat 已经支持 OpenAI 最新的 [`gpt-4-vision`](https://platform.openai.com/docs/guides/vision) 支持视觉识别的模型,这是一个具备视觉识别能力的多模态应用。
用户可以轻松上传图片或者拖拽图片到对话框中,助手将能够识别图片内容,并在此基础上进行智能对话,构建更智能、更多元化的聊天场景。
这一特性打开了新的互动方式,使得交流不再局限于文字,而是可以涵盖丰富的视觉元素。无论是日常使用中的图片分享,还是在特定行业内的图像解读,助手都能提供出色的对话体验。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-tts]][docs-feat-tts]
### `4` [TTS & STT 语音会话][docs-feat-tts]
LobeChat 支持文字转语音Text-to-SpeechTTS和语音转文字Speech-to-TextSTT技术我们的应用能够将文本信息转化为清晰的语音输出用户可以像与真人交谈一样与我们的对话代理进行交流。
用户可以从多种声音中选择,给助手搭配合适的音源。 同时对于那些倾向于听觉学习或者想要在忙碌中获取信息的用户来说TTS 提供了一个极佳的解决方案。
在 LobeChat 中,我们精心挑选了一系列高品质的声音选项 (OpenAI Audio, Microsoft Edge Speech),以满足不同地域和文化背景用户的需求。用户可以根据个人喜好或者特定场景来选择合适的语音,从而获得个性化的交流体验。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-t2i]][docs-feat-t2i]
### `5` [Text to Image 文生图][docs-feat-t2i]
支持最新的文本到图片生成技术LobeChat 现在能够让用户在与助手对话中直接调用文成图工具进行创作。
通过利用 [`DALL-E 3`](https://openai.com/dall-e-3)、[`MidJourney`](https://www.midjourney.com/) 和 [`Pollinations`](https://pollinations.ai/) 等 AI 工具的能力, 助手们现在可以将你的想法转化为图像。
同时可以更私密和沉浸式的完成你的创造过程。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-plugin]][docs-feat-plugin]
### `6` [插件系统 (Function Calling)][docs-feat-plugin]
LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地增强了 ChatGPT 的实用性和灵活性。
<video controls src="https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2" muted="false"></video>
通过利用插件ChatGPT 能够实现实时信息的获取和处理,例如自动获取最新新闻头条,为用户提供即时且相关的资讯。
此外,这些插件不仅局限于新闻聚合,还可以扩展到其他实用的功能,如快速检索文档、获取电商平台数据、以及其他各式各样的第三方服务。
> 通过文档了解更多 [📘 插件使用][docs-usage-plugin]
<!-- PLUGIN LIST -->
| 最近新增 | 插件描述 |
| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| [图表和图示](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **pyxl** on **2024-02-05**</sup> | 美人鱼图表,演示文稿方案,分析,研究网站,饼图。<br/>`图表` `图示` |
| [社交搜索](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **say-apps** on **2024-02-02**</sup> | 社交搜索提供访问推文、用户、关注者、图片、媒体等功能。<br/>`社交` `推特` `x` `搜索` |
| [TokenInsights](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **feednews** on **2024-01-27**</sup> | 获取实时加密货币价格BTCETHBNB 和最新见解。最新的币新闻和空投机会。<br/>`加密货币` `btc` `eth` `bnb` |
| [哔哩哔哩](https://chat-preview.lobehub.com/settings/agent)<br/><sup>By **LobeHub** on **2024-01-27**</sup> | 通过关键词视频搜索、回放访问、互动弹幕、热门视频推荐和热搜洞察等功能,深入体验哔哩哔哩丰富的内容,尽在您的指尖。<br/>`视频` `哔哩哔哩` `搜索` |
> 📊 Total plugins: [<kbd>**58**</kbd>](https://github.com/lobehub/lobe-chat-plugins)
<!-- PLUGIN LIST -->
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-agent]][docs-feat-agent]
### `7` [助手市场 (GPTs)][docs-feat-agent]
在 LobeChat 的助手市场中,创作者们可以发现一个充满活力和创新的社区,它汇聚了众多精心设计的助手,这些助手不仅在工作场景中发挥着重要作用,也在学习过程中提供了极大的便利。
我们的市场不仅是一个展示平台,更是一个协作的空间。在这里,每个人都可以贡献自己的智慧,分享个人开发的助手。
> \[!TIP]
>
> 通过 [🤖/🏪 提交助手][submit-agents-link] 你可以轻松地将你的助手作品提交到我们的平台。我们特别强调的是LobeChat 建立了一套精密的自动化国际化i18n工作流程 它的强大之处在于能够无缝地将你的助手转化为多种语言版本。
> 这意味着,不论你的用户使用何种语言,他们都能无障碍地体验到你的助手。
> \[!IMPORTANT]
>
> 我欢迎所有用户加入这个不断成长的生态系统,共同参与到助手的迭代与优化中来。共同创造出更多有趣、实用且具有创新性的助手,进一步丰富助手的多样性和实用性。
<!-- AGENT LIST -->
| 最近新增 | 助手说明 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| [日程管理助手](https://chat-preview.lobehub.com/market?agent=calendar-manager)<br/><sup>By **[ccdanpian](https://github.com/ccdanpian)** on **2024-03-07**</sup> | 日程管理助手,调用时间插件,处理新增、查询、删除日程请求,支持多种操作和提醒。<br/>`日程管理` `时间插件` `新增日程` `查询日程` `删除日程` |
| [商务邮件撰写专家](https://chat-preview.lobehub.com/market?agent=business-email)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2024-03-06**</sup> | 商务邮件撰写专家擅长中英文商务邮件跨文化沟通GitHub 开源社区交流。<br/>`商务邮件撰写` `商业合作` `商务授权` `跨文化沟通` `git-hub和开源社区` |
| [Discord 风格文案大师](https://chat-preview.lobehub.com/market?agent=discord-copywriting)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2024-03-06**</sup> | Discord 风格文案专家,幽默风趣、用户体验优先,个性化设计软件文案。<br/>`文案生成` `创作` `用户体验` `幽默风趣` `软件系统` |
| [AI 图像提示建筑师](https://chat-preview.lobehub.com/market?agent=9-somboon)<br/><sup>By **[9Somboon](https://github.com/9Somboon)** on **2024-03-05**</sup> | 专门为 AI 图像生成创建详细提示。<br/>`stable-diffusion` `ai-image-generation` `prompts` `photography` `creative` `art` |
> 📊 Total agents: [<kbd>**199**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
<!-- AGENT LIST -->
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-pwa]][docs-feat-pwa]
### `8` [渐进式 Web 应用 (PWA)][docs-feat-pwa]
我们利深知在当今多设备环境下为用户提供无缝体验的重要性。为此,我们采用了渐进式 Web 应用 [PWA](https://support.google.com/chrome/answer/9658361) 技术,
这是一种能够将网页应用提升至接近原生应用体验的现代 Web 技术。通过 PWALobeChat 能够在桌面和移动设备上提供高度优化的用户体验,同时保持轻量级和高性能的特点。
在视觉和感觉上,我们也经过精心设计,以确保它的界面与原生应用无差别,提供流畅的动画、响应式布局和适配不同设备的屏幕分辨率。
> \[!NOTE]
>
> 若您未熟悉 PWA 的安装过程,您可以按照以下步骤将 LobeChat 添加为您的桌面应用(也适用于移动设备):
>
> - 在电脑上运行 Chrome 或 Edge 浏览器 .
> - 访问 LobeChat 网页 .
> - 在地址栏的右上角,单击 <kbd>安装</kbd> 图标 .
> - 根据屏幕上的指示完成 PWA 的安装 .
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-mobile]][docs-feat-mobile]
### `9` [移动设备适配][docs-feat-mobile]
针对移动设备进行了一系列的优化设计,以提升用户的移动体验。目前,我们正在对移动端的用户体验进行版本迭代,以实现更加流畅和直观的交互。如果您有任何建议或想法,我们非常欢迎您通过 GitHub Issues 或者 Pull Requests 提供反馈。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
[![][image-feat-theme]][docs-feat-theme]
### `10` [自定义主题][docs-feat-theme]
作为设计工程师出身 LobeChat 在界面设计上十分考虑用户的个性化体验,因此引入了灵活多变的主题模式,其中包括日间的亮色模式和夜间的深色模式。
除了主题模式的切换,还提供了一系列的颜色定制选项,允许用户根据自己的喜好来调整应用的主题色彩。无论是想要沉稳的深蓝,还是希望活泼的桃粉,或者是专业的灰白,用户都能够在 LobeChat 中找到匹配自己风格的颜色选择。
> \[!TIP]
>
> 默认配置能够智能地识别用户系统的颜色模式自动进行主题切换以确保应用界面与操作系统保持一致的视觉体验。对于喜欢手动调控细节的用户LobeChat 同样提供了直观的设置选项,针对聊天场景也提供了对话气泡模式和文档模式的选择。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
### 更多特性
除了上述功能特性以外,我们的所具有的设计和技术能力将为你带来了更多使用保障:
- [x] 💎 **精致 UI 设计**:经过精心设计的界面,具有优雅的外观和流畅的交互效果,支持亮暗色主题,适配移动端。支持 PWA提供更加接近原生应用的体验。
- [x] 🗣️ **流畅的对话体验**:流式响应带来流畅的对话体验,并且支持完整的 Markdown 渲染包括代码高亮、LaTex 公式、Mermaid 流程图等。
- [x] 💨 **快速部署**:使用 Vercel 平台或者我们的 Docker 镜像,只需点击一键部署按钮,即可在 1 分钟内完成部署,无需复杂的配置过程。
- [x] 🔒 **隐私安全**:所有数据保存在用户浏览器本地,保证用户的隐私安全。
- [x] 🌐 **自定义域名**:如果用户拥有自己的域名,可以将其绑定到平台上,方便在任何地方快速访问对话助手。
> ✨ 随着产品迭代持续更新,我们将会带来更多更多令人激动的功能!
---
> \[!NOTE]
>
> 你可以在 Projects 中找到我们后续的 [Roadmap][github-project-link] 计划
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ⚡️ 性能测试
> \[!NOTE]
>
> 完整测试报告可见 [📘 Lighthouse 性能测试][docs-lighthouse]
| Desktop | Mobile |
| :-------------------------------------------: | :------------------------------------------: |
| ![][chat-desktop] | ![][chat-mobile] |
| [📑 Lighthouse 测试报告][chat-desktop-report] | [📑 Lighthouse 测试报告][chat-mobile-report] |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🛳 开箱即用
LobeChat 提供了 Vercel 的 自托管版本 和 [Docker 镜像][docker-release-link],这使你可以在几分钟内构建自己的聊天机器人,无需任何基础知识。
> \[!TIP]
>
> 完整教程请查阅 [📘 构建属于自己的 Lobe Chat][docs-self-hosting]
### `A` 使用 Vercel、Zeabur 或 Sealos 部署
如果想在 Vercel 或 Zeabur 上部署该服务,可以按照以下步骤进行操作:
- 准备好你的 [OpenAI API Key](https://platform.openai.com/account/api-keys) 。
- 点击下方按钮开始部署: 直接使用 GitHub 账号登录即可,记得在环境变量页填入 `OPENAI_API_KEY` (必填) and `ACCESS_CODE`(推荐);
- 部署完毕后,即可开始使用;
- 绑定自定义域名可选Vercel 分配的域名 DNS 在某些区域被污染了,绑定自定义域名即可直连。目前 Zeabur 提供的域名还未被污染,大多数地区都可以直连。
<div align="center">
| 使用 Vercel 部署 | 使用 Zeabur 部署 | 使用 Sealos 部署 |
| :-------------------------------------: | :---------------------------------------------------------: | :---------------------------------------------------------: |
| [![][deploy-button-image]][deploy-link] | [![][deploy-on-zeabur-button-image]][deploy-on-zeabur-link] | [![][deploy-on-sealos-button-image]][deploy-on-sealos-link] |
</div>
#### Fork 之后
在 Fork 后,请只保留 "upstream sync" Action 并在你 fork 的 GitHub Repo 中禁用其他 Action。
#### 保持更新
如果你根据 README 中的一键部署步骤部署了自己的项目,你可能会发现总是被提示 “有可用更新”。这是因为 Vercel 默认为你创建新项目而非 fork 本项目,这将导致无法准确检测更新。
> \[!TIP]
>
> 我们建议按照 [📘 自动同步更新][docs-upstream-sync] 步骤重新部署。
<br/>
### `B` 使用 Docker 部署
[![][docker-release-shield]][docker-release-link]
[![][docker-size-shield]][docker-size-link]
[![][docker-pulls-shield]][docker-pulls-link]
我们提供了 Docker 镜像,供你在自己的私有设备上部署 LobeChat 服务。使用以下命令即可使用一键启动 LobeChat 服务:
```fish
$ docker run -d -p 3210:3210 \
-e OPENAI_API_KEY=sk-xxxx \
-e ACCESS_CODE=lobe66 \
--name lobe-chat \
lobehub/lobe-chat
```
> \[!TIP]
>
> 如果你需要通过代理使用 OpenAI 服务,你可以使用 `OPENAI_PROXY_URL` 环境变量来配置代理地址:
```fish
$ docker run -d -p 3210:3210 \
-e OPENAI_API_KEY=sk-xxxx \
-e OPENAI_PROXY_URL=https://api-proxy.com/v1 \
-e ACCESS_CODE=lobe66 \
--name lobe-chat \
lobehub/lobe-chat
```
> \[!NOTE]
>
> 有关 Docker 部署的详细说明,详见 [📘 使用 Docker 部署][docs-docker]
<br/>
### 环境变量
本项目提供了一些额外的配置项,使用环境变量进行设置:
| 环境变量 | 类型 | 描述 | 示例 |
| ------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `OPENAI_API_KEY` | 必选 | 这是你在 OpenAI 账户页面申请的 API 密钥 | `sk-xxxxxx...xxxxxx` |
| `OPENAI_PROXY_URL` | 可选 | 如果你手动配置了 OpenAI 接口代理,可以使用此配置项来覆盖默认的 OpenAI API 请求基础 URL | `https://api.chatanywhere.cn``https://aihubmix.com/v1`<br/>默认值:<br/>`https://api.openai.com/v1` |
| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,你可以设置一个长密码以防被爆破,该值用逗号分隔时为密码数组 | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` |
| `CUSTOM_MODELS` | 可选 | 用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。 | `qwen-7b-chat,+glm-6b,-gpt-3.5-turbo` |
> \[!NOTE]
>
> 完整环境变量可见 [📘 环境变量][docs-env-var]
<br/>
### 获取 OpenAI API Key
API Key 是使用 LobeChat 进行大语言模型会话的必要信息,本节以 OpenAI 模型服务商为例,简要介绍获取 API Key 的方式。
#### `A` 通过 OpenAI 官方渠道
- 注册一个 [OpenAI 账户](https://platform.openai.com/signup),你需要使用国际手机号、非大陆邮箱进行注册;
- 注册完毕后,前往 [API Keys](https://platform.openai.com/api-keys) 页面,点击 `Create new secret key` 创建新的 API Key:
| 步骤 1打开创建窗口 | 步骤 2创建 API Key | 步骤 3获取 API Key |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/296253192-ff2193dd-f125-4e58-82e8-91bc376c0d68.png" height="200"/> | <img src="https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/296254170-803bacf0-4471-4171-ae79-0eab08d621d1.png" height="200"/> | <img src="https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/296255167-f2745f2b-f083-4ba8-bc78-9b558e0002de.png" height="200"/> |
- 将此 API Key 填写到 LobeChat 的 API Key 配置中,即可开始使用。
> \[!TIP]
>
> 账户注册后,一般有 5 美元的免费额度,但有效期只有三个月。
> 如果你希望长期使用你的 API Key你需要完成支付的信用卡绑定。由于 OpenAI 只支持外币信用卡,因此你需要找到合适的支付渠道,此处不再详细展开。
<br/>
#### `B` 通过 OpenAI 第三方代理商
如果你发现注册 OpenAI 账户或者绑定外币信用卡比较麻烦,可以考虑借助一些知名的 OpenAI 第三方代理商来获取 API Key
这可以有效降低获取 OpenAI API Key 的门槛。但与此同时,一旦使用三方服务,你可能也需要承担潜在的风险,
请根据你自己的实际情况自行决策。以下是常见的第三方模型代理商列表,供你参考:
| | 服务商 | 特性说明 | Proxy 代理地址 | 链接 |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------- | ------------------------- | ------------------------------- |
| <img src="https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/296272721-c3ac0bf3-e433-4496-89c4-ebdc20689c17.jpg" width="48" /> | **AiHubMix** | 使用 OpenAI 企业接口,全站模型价格为官方 **6 折**(含 GPT-4 | `https://aihubmix.com/v1` | [获取](https://lobe.li/XHnZIUP) |
> \[!WARNING]
>
> **免责申明**: 在此推荐的 OpenAI API Key 由第三方代理商提供,所以我们不对 API Key 的 **有效性****安全性** 负责,请你自行承担购买和使用 API Key 的风险。
> \[!NOTE]
>
> 如果你是模型服务商,并认为自己的服务足够稳定且价格实惠,欢迎联系我们,我们会在自行体验和测试后酌情推荐。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 📦 生态系统
| NPM | 仓库 | 描述 | 版本 |
| --------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------- |
| [@lobehub/ui][lobe-ui-link] | [lobehub/lobe-ui][lobe-ui-github] | 构建 AIGC 网页应用程序而设计的开源 UI 组件库 | [![][lobe-ui-shield]][lobe-ui-link] |
| [@lobehub/icons][lobe-icons-link] | [lobehub/lobe-icons][lobe-icons-github] | 主流 AI / LLM 模型和公司 SVG Logo 与 Icon 合集 | [![][lobe-icons-shield]][lobe-icons-link] |
| [@lobehub/tts][lobe-tts-link] | [lobehub/lobe-tts][lobe-tts-github] | AI TTS / STT 语音合成 / 识别 React Hooks 库 | [![][lobe-tts-shield]][lobe-tts-link] |
| [@lobehub/lint][lobe-lint-link] | [lobehub/lobe-lint][lobe-lint-github] | LobeHub 代码样式规范 ESlintStylelintCommitlintPrettierRemark 和 Semantic Release | [![][lobe-lint-shield]][lobe-lint-link] |
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🧩 插件体系
插件提供了扩展 LobeChat [Function Calling][docs-functionc-call] 能力的方法。可以用于引入新的 Function Calling甚至是新的消息结果渲染方式。如果你对插件开发感兴趣请在 Wiki 中查阅我们的 [📘 插件开发指引][docs-plugin-dev] 。
- [lobe-chat-plugins][lobe-chat-plugins]:插件索引从该仓库的 index.json 中获取插件列表并显示给用户。
- [chat-plugin-template][chat-plugin-template]:插件开发模版,你可以通过项目模版快速新建插件项目。
- [@lobehub/chat-plugin-sdk][chat-plugin-sdk]:插件 SDK 可帮助您创建出色的 Lobe Chat 插件。
- [@lobehub/chat-plugins-gateway][chat-plugins-gateway]:插件网关是一个后端服务,作为 LobeChat 插件的网关。我们使用 Vercel 部署此服务。主要的 API POST /api/v1/runner 被部署为 Edge Function。
> \[!NOTE]
>
> 插件系统目前正在进行重大开发。您可以在以下 Issues 中了解更多信息:
>
> - [x] [**插件一期**](https://github.com/lobehub/lobe-chat/issues/73): 实现插件与主体分离,将插件拆分为独立仓库维护,并实现插件的动态加载
> - [x] [**插件二期**](https://github.com/lobehub/lobe-chat/issues/97): 插件的安全性与使用的稳定性,更加精准地呈现异常状态,插件架构的可维护性与开发者友好
> - [x] [**插件三期**](https://github.com/lobehub/lobe-chat/issues/149):更高阶与完善的自定义能力,支持插件鉴权与示例
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ⌨️ 本地开发
可以使用 GitHub Codespaces 进行在线开发:
[![][codespaces-shield]][codespaces-link]
或者使用以下命令进行本地开发:
```fish
$ git clone https://github.com/lobehub/lobe-chat.git
$ cd lobe-chat
$ pnpm install
$ pnpm run dev
```
如果你希望了解更多详情,欢迎可以查阅我们的 [📘 开发指南][docs-dev-guide]
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🤝 参与贡献
我们非常欢迎各种形式的贡献。如果你对贡献代码感兴趣,可以查看我们的 GitHub [Issues][github-issues-link] 和 [Projects][github-project-link],大展身手,向我们展示你的奇思妙想。
> \[!TIP]
>
> 我们希望创建一个技术分享型社区,一个可以促进知识共享、想法交流,激发彼此鼓励和协作的环境。
> 同时欢迎联系我们提供产品功能和使用体验反馈,帮助我们将 LobeChat 建设得更好。
>
> **组织维护者:** [@arvinxx](https://github.com/arvinxx) [@canisminor1990](https://github.com/canisminor1990)
[![][pr-welcome-shield]][pr-welcome-link]
[![][submit-agents-shield]][submit-agents-link]
[![][submit-plugin-shield]][submit-plugin-link]
<a href="https://github.com/lobehub/lobe-chat/graphs/contributors" target="_blank">
<table>
<tr>
<th colspan="2">
<br><img src="https://contrib.rocks/image?repo=lobehub/lobe-chat"><br><br>
</th>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=light">
</picture>
</td>
<td rowspan="2">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=4x7&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=active&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=4x7&color_scheme=light">
</picture>
</td>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=dark">
<img src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=131470832&repo_ids=643445235&image_size=2x3&color_scheme=light">
</picture>
</td>
</tr>
</table>
</a>
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## ❤ 社区赞助
每一分支持都珍贵无比,汇聚成我们支持的璀璨银河!你就像一颗划破夜空的流星,瞬间点亮我们前行的道路。感谢你对我们的信任 —— 你的支持笔就像星辰导航,一次又一次地为项目指明前进的光芒。
<a href="https://opencollective.com/lobehub" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/lobehub/.github/blob/main/static/sponsor-dark.png?raw=true">
<img src="https://github.com/lobehub/.github/blob/main/static/sponsor-light.png?raw=true">
</picture>
</a>
<div align="right">
[![][back-to-top]](#readme-top)
</div>
## 🔗 更多工具
- **[🅰️ Lobe SD Theme][lobe-theme]:** Stable Diffusion WebUI 的现代主题,精致的界面设计,高度可定制的 UI以及提高效率的功能。
- **[⛵️ Lobe Midjourney WebUI][lobe-midjourney-webui]:** Midjourney WebUI, 能够根据文本提示快速生成丰富多样的图像,激发创造力,增强对话交流。
- **[🌏 Lobe i18n][lobe-i18n]:** Lobe i18n 是一个由 ChatGPT 驱动的 i18n国际化翻译过程的自动化工具。它支持自动分割大文件、增量更新以及为 OpenAI 模型、API 代理和温度提供定制选项的功能。
- **[💌 Lobe Commit][lobe-commit]:** Lobe Commit 是一个 CLI 工具,它利用 Langchain/ChatGPT 生成基于 Gitmoji 的提交消息。
<div align="right">
[![][back-to-top]](#readme-top)
</div>
---
<details><summary><h4>📝 License</h4></summary>
[![][fossa-license-shield]][fossa-license-link]
</details>
Copyright © 2023 [LobeHub][profile-link]. <br />
This project is [MIT](./LICENSE) licensed.
<!-- LINK GROUP -->
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/chat_preview_lobehub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/chat_preview_lobehub_com_chat.html
[chat-plugin-sdk]: https://github.com/lobehub/chat-plugin-sdk
[chat-plugin-template]: https://github.com/lobehub/chat-plugin-template
[chat-plugins-gateway]: https://github.com/lobehub/chat-plugins-gateway
[codecov-link]: https://codecov.io/gh/lobehub/lobe-chat
[codecov-shield]: https://img.shields.io/codecov/c/github/lobehub/lobe-chat?labelColor=black&style=flat-square&logo=codecov&logoColor=white
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg
[deploy-button-image]: https://vercel.com/button
[deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
[deploy-on-sealos-button-image]: https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg
[deploy-on-sealos-link]: https://cloud.sealos.io/?openapp=system-template%3FtemplateName%3Dlobe-chat
[deploy-on-zeabur-button-image]: https://zeabur.com/button.svg
[deploy-on-zeabur-link]: https://zeabur.com/templates/VZGGTI
[discord-link]: https://discord.gg/AYFPHvv2jT
[discord-shield]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square
[discord-shield-badge]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=for-the-badge
[docker-pulls-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-pulls-shield]: https://img.shields.io/docker/pulls/lobehub/lobe-chat?color=45cc11&labelColor=black&style=flat-square
[docker-release-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-release-shield]: https://img.shields.io/docker/v/lobehub/lobe-chat?color=369eff&label=docker&labelColor=black&logo=docker&logoColor=white&style=flat-square
[docker-size-link]: https://hub.docker.com/r/lobehub/lobe-chat
[docker-size-shield]: https://img.shields.io/docker/image-size/lobehub/lobe-chat?color=369eff&labelColor=black&style=flat-square
[docs-dev-guide]: https://github.com/lobehub/lobe-chat/wiki/index
[docs-docker]: https://chat-docs.lobehub.com/zh/self-hosting/platform/docker
[docs-env-var]: https://chat-docs.lobehub.com/zh/self-hosting/environment-variables
[docs-feat-agent]: https://chat-docs.lobehub.com/zh/usage/features/agent-market
[docs-feat-local]: https://chat-docs.lobehub.com/zh/usage/features/local-llm
[docs-feat-mobile]: https://chat-docs.lobehub.com/zh/usage/features/mobile
[docs-feat-plugin]: https://chat-docs.lobehub.com/zh/usage/features/plugin-system
[docs-feat-provider]: https://chat-docs.lobehub.com/zh/usage/features/multi-ai-providers
[docs-feat-pwa]: https://chat-docs.lobehub.com/zh/usage/features/pwa
[docs-feat-t2i]: https://chat-docs.lobehub.com/zh/usage/features/text-to-image
[docs-feat-theme]: https://chat-docs.lobehub.com/zh/usage/features/theme
[docs-feat-tts]: https://chat-docs.lobehub.com/zh/usage/features/tts
[docs-feat-vision]: https://chat-docs.lobehub.com/zh/usage/features/vision
[docs-functionc-call]: https://platform.openai.com/docs/guides/function-calling
[docs-lighthouse]: https://github.com/lobehub/lobe-chat/wiki/Lighthouse.zh-CN
[docs-plugin-dev]: https://chat-docs.lobehub.com/zh/usage/plugins/development
[docs-self-hosting]: https://chat-docs.lobehub.com/zh/self-hosting/start
[docs-upstream-sync]: https://chat-docs.lobehub.com/zh/self-hosting/advanced/upstream-sync
[docs-usage-ollama]: https://chat-docs.lobehub.com/zh/usage/providers/ollama
[docs-usage-plugin]: https://chat-docs.lobehub.com/zh/usage/plugins/basic
[fossa-license-link]: https://app.fossa.com/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat
[fossa-license-shield]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat.svg?type=large
[github-action-release-link]: https://github.com/lobehub/lobe-chat/actions/workflows/release.yml
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/lobe-chat/release.yml?label=release&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
[github-action-test-link]: https://github.com/lobehub/lobe-chat/actions/workflows/test.yml
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/lobe-chat/test.yml?label=test&labelColor=black&logo=githubactions&logoColor=white&style=flat-square
[github-contributors-link]: https://github.com/lobehub/lobe-chat/graphs/contributors
[github-contributors-shield]: https://img.shields.io/github/contributors/lobehub/lobe-chat?color=c4f042&labelColor=black&style=flat-square
[github-document-link]: https://chat-docs.lobehub.com/zh
[github-forks-link]: https://github.com/lobehub/lobe-chat/network/members
[github-forks-shield]: https://img.shields.io/github/forks/lobehub/lobe-chat?color=8ae8ff&labelColor=black&style=flat-square
[github-issues-link]: https://github.com/lobehub/lobe-chat/issues
[github-issues-shield]: https://img.shields.io/github/issues/lobehub/lobe-chat?color=ff80eb&labelColor=black&style=flat-square
[github-license-link]: https://github.com/lobehub/lobe-chat/blob/main/LICENSE
[github-license-shield]: https://img.shields.io/github/license/lobehub/lobe-chat?color=white&labelColor=black&style=flat-square
[github-project-link]: https://github.com/lobehub/lobe-chat/projects
[github-release-link]: https://github.com/lobehub/lobe-chat/releases
[github-release-shield]: https://img.shields.io/github/v/release/lobehub/lobe-chat?color=369eff&labelColor=black&logo=github&style=flat-square
[github-releasedate-link]: https://github.com/lobehub/lobe-chat/releases
[github-releasedate-shield]: https://img.shields.io/github/release-date/lobehub/lobe-chat?labelColor=black&style=flat-square
[github-stars-link]: https://github.com/lobehub/lobe-chat/network/stargazers
[github-stars-shield]: https://img.shields.io/github/stars/lobehub/lobe-chat?color=ffcb47&labelColor=black&style=flat-square
[github-trending-shield]: https://trendshift.io/api/badge/repositories/2256
[github-trending-url]: https://trendshift.io/repositories/2256
[image-banner]: https://github.com/lobehub/lobe-chat/assets/28616219/9f155dff-4737-429f-9cad-a70a1a860c5f
[image-feat-agent]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/268670869-f1ffbf66-42b6-42cf-a937-9ce1f8328514.png
[image-feat-local]: https://github.com/lobehub/lobe-chat/assets/28616219/ca9a21bc-ea6c-4c90-bf4a-fa53b4fb2b5c
[image-feat-mobile]: https://gw.alipayobjects.com/zos/kitchen/R441AuFS4W/mobile.webp
[image-feat-plugin]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/268670883-33c43a5c-a512-467e-855c-fa299548cce5.png
[image-feat-privoder]: https://github.com/lobehub/lobe-chat/assets/28616219/b164bc54-8ba2-4c1e-b2f2-f4d7f7e7a551
[image-feat-pwa]: https://gw.alipayobjects.com/zos/kitchen/69x6bllkX3/pwa.webp
[image-feat-t2i]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/297746445-0ff762b9-aa08-4337-afb7-12f932b6efbb.png
[image-feat-theme]: https://gw.alipayobjects.com/zos/kitchen/pvus1lo%26Z7/darkmode.webp
[image-feat-tts]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/284072124-c9853d8d-f1b5-44a8-a305-45ebc0f6d19a.png
[image-feat-vision]: https://github-production-user-asset-6210df.s3.amazonaws.com/17870709/284072129-382bdf30-e3d6-4411-b5a0-249710b8ba08.png
[image-overview]: https://github.com/lobehub/lobe-chat/assets/28616219/8b04c3c9-3d71-4fb4-bd9b-a4f415c5876d
[image-star]: https://github.com/lobehub/lobe-chat/assets/17870709/cb06b748-513f-47c2-8740-d876858d7855
[issues-link]: https://img.shields.io/github/issues/lobehub/lobe-chat.svg?style=flat
[lobe-chat-plugins]: https://github.com/lobehub/lobe-chat-plugins
[lobe-commit]: https://github.com/lobehub/lobe-commit/tree/master/packages/lobe-commit
[lobe-i18n]: https://github.com/lobehub/lobe-commit/tree/master/packages/lobe-i18n
[lobe-icons-github]: https://github.com/lobehub/lobe-icons
[lobe-icons-link]: https://www.npmjs.com/package/@lobehub/icons
[lobe-icons-shield]: https://img.shields.io/npm/v/@lobehub/icons?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-lint-github]: https://github.com/lobehub/lobe-lint
[lobe-lint-link]: https://www.npmjs.com/package/@lobehub/lint
[lobe-lint-shield]: https://img.shields.io/npm/v/@lobehub/lint?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-midjourney-webui]: https://github.com/lobehub/lobe-midjourney-webui
[lobe-theme]: https://github.com/lobehub/sd-webui-lobe-theme
[lobe-tts-github]: https://github.com/lobehub/lobe-tts
[lobe-tts-link]: https://www.npmjs.com/package/@lobehub/tts
[lobe-tts-shield]: https://img.shields.io/npm/v/@lobehub/tts?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[lobe-ui-github]: https://github.com/lobehub/lobe-ui
[lobe-ui-link]: https://www.npmjs.com/package/@lobehub/ui
[lobe-ui-shield]: https://img.shields.io/npm/v/@lobehub/ui?color=369eff&labelColor=black&logo=npm&logoColor=white&style=flat-square
[pr-welcome-link]: https://github.com/lobehub/lobe-chat/pulls
[pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge
[profile-link]: https://github.com/lobehub
[share-mastodon-link]: https://mastodon.social/share?text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source,%20extensible%20(Function%20Calling),%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT/LLM%20web%20application.%20https://github.com/lobehub/lobe-chat%20#chatbot%20#chatGPT%20#openAI
[share-mastodon-shield]: https://img.shields.io/badge/-share%20on%20mastodon-black?labelColor=black&logo=mastodon&logoColor=white&style=flat-square
[share-reddit-link]: https://www.reddit.com/submit?title=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-reddit-shield]: https://img.shields.io/badge/-share%20on%20reddit-black?labelColor=black&logo=reddit&logoColor=white&style=flat-square
[share-telegram-link]: https://t.me/share/url"?text=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-telegram-shield]: https://img.shields.io/badge/-share%20on%20telegram-black?labelColor=black&logo=telegram&logoColor=white&style=flat-square
[share-weibo-link]: http://service.weibo.com/share/share.php?sharesource=weibo&title=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%20%23chatbot%20%23chatGPT%20%23openAI&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-weibo-shield]: https://img.shields.io/badge/-share%20on%20weibo-black?labelColor=black&logo=sinaweibo&logoColor=white&style=flat-square
[share-whatsapp-link]: https://api.whatsapp.com/send?text=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%20https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat%20%23chatbot%20%23chatGPT%20%23openAI
[share-whatsapp-shield]: https://img.shields.io/badge/-share%20on%20whatsapp-black?labelColor=black&logo=whatsapp&logoColor=white&style=flat-square
[share-x-link]: https://x.com/intent/tweet?hashtags=chatbot%2CchatGPT%2CopenAI&text=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
[share-x-shield]: https://img.shields.io/badge/-share%20on%20x-black?labelColor=black&logo=x&logoColor=white&style=flat-square
[sponsor-link]: https://opencollective.com/lobehub 'Become ❤ LobeHub Sponsor'
[sponsor-shield]: https://img.shields.io/badge/-Sponsor%20LobeHub-f04f88?logo=opencollective&logoColor=white&style=flat-square
[submit-agents-link]: https://github.com/lobehub/lobe-chat-agents
[submit-agents-shield]: https://img.shields.io/badge/🤖/🏪_submit_agent-%E2%86%92-c4f042?labelColor=black&style=for-the-badge
[submit-plugin-link]: https://github.com/lobehub/lobe-chat-plugins
[submit-plugin-shield]: https://img.shields.io/badge/🧩/🏪_submit_plugin-%E2%86%92-95f3d9?labelColor=black&style=for-the-badge
[vercel-link]: https://chat-preview.lobehub.com
[vercel-shield]: https://img.shields.io/website?down_message=offline&label=vercel&labelColor=black&logo=vercel&style=flat-square&up_message=online&url=https%3A%2F%2Fchat-preview.lobehub.com
[vercel-shield-badge]: https://img.shields.io/website?down_message=offline&label=try%20lobechat&labelColor=black&logo=vercel&style=for-the-badge&up_message=online&url=https%3A%2F%2Fchat-preview.lobehub.com

View File

@ -0,0 +1,25 @@
import { act } from 'react-dom/test-utils';
import { beforeEach } from 'vitest';
import { createWithEqualityFn as actualCreate } from 'zustand/traditional';
// a variable to hold reset functions for all stores declared in the app
const storeResetFns = new Set<() => void>();
// when creating a store, we get its initial state, create a reset function and add it in the set
const createImpl = (createState: any) => {
const store = actualCreate(createState, Object.is);
const initialState = store.getState();
storeResetFns.add(() => store.setState(initialState, true));
return store;
};
// Reset all stores after each test run
beforeEach(() => {
act(() => {
for (const resetFn of storeResetFns) {
resetFn();
}
});
});
export const createWithEqualityFn = (f: any) => (f === undefined ? createImpl : createImpl(f));

View File

@ -0,0 +1,193 @@
# New Authentication Provider Guide
LobeChat uses [Auth.js v5](https://authjs.dev/) as the external authentication service. Auth.js is an open-source authentication library that provides a simple way to implement authentication and authorization features. This document will introduce how to use Auth.js to implement a new authentication provider.
### TOC
- [Add New Authentication Provider](#add-new-authentication-provider)
- [Pre-requisites: Check the Official Provider List](#pre-requisites-check-the-official-provider-list)
- [Step 1: Add Authenticator Core Code](#step-1-add-authenticator-core-code)
- [Step 2: Update Server Configuration Code](#step-2-update-server-configuration-code)
- [Step 3: Change Frontend Pages](#step-3-change-frontend-pages)
- [Step 4: Configure the Environment Variables](#step-4-configure-the-environment-variables)
- [Step 5: Modify server-side user information processing logic](#step-5-modify-server-side-user-information-processing-logic)
## Add New Authentication Provider
To add a new authentication provider in LobeChat (for example, adding Okta), you need to follow the steps below:
### Pre-requisites: Check the Official Provider List
First, you need to check the [Auth.js Provider List](https://authjs.dev/reference/core/providers) to see if your provider is already supported. If yes, you can directly use the SDK provided by Auth.js to implement the authentication feature.
Next, I will use [Okta](https://authjs.dev/reference/core/providers/okta) as an example to introduce how to add a new authentication provider.
### Step 1: Add Authenticator Core Code
Open the `src/app/api/auth/next-auth.ts` file and import `next-auth/providers/okta`.
```ts
import { NextAuth } from 'next-auth';
import Auth0 from 'next-auth/providers/auth0';
import Okta from 'next-auth/providers/okta';
// Import Okta provider
```
Add the predefined server configuration.
```ts
// Import server configuration
const { OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_ISSUER } = getServerConfig();
const nextAuth = NextAuth({
providers: [
// ... Other providers
Okta({
clientId: OKTA_CLIENT_ID,
clientSecret: OKTA_CLIENT_SECRET,
issuer: OKTA_ISSUER,
}),
],
});
```
### Step 2: Update Server Configuration Code
Open the `src/config/server/app.ts` file and add Okta-related environment variables in the `getAppConfig` function.
```ts
export const getAppConfig = () => {
// ... Other code
return {
// ... Other environment variables
OKTA_CLIENT_ID: process.env.OKTA_CLIENT_ID || '',
OKTA_CLIENT_SECRET: process.env.OKTA_CLIENT_SECRET || '',
OKTA_ISSUER: process.env.OKTA_ISSUER || '',
};
};
```
### Step 3: Change Frontend Pages
Modify the `signIn` function parameter in `src/Features/Conversation/Error/OAuthForm.tsx` and \`src/app/settings/common/Common.tsx
The default is `auth0`, which you can change to `okta` to switch to the Okta provider, or remove this parameter to support all added authentication services
This value is the id of the Auth.js provider, and you can read the source code of the corresponding `next-auth/providers` module to read the default ID.
### Step 4: Configure the Environment Variables
Add `OKTA_CLIENT_ID``OKTA_CLIENT_SECRET``OKTA_ISSUER` environment variables when you deploy.
### Step 5: Modify server-side user information processing logic
#### Get user information in the frontend
Use the `useOAuthSession()` method in the frontend page to get the user information `user` returned by the backend:
```ts
import { useOAuthSession } from '@/hooks/useOAuthSession';
const { user, isOAuthLoggedIn } = useOAuthSession();
```
The default type of `user` is `User`, and the type definition is:
```ts
interface User {
id?: string;
name?: string | null;
email?: string | null;
image?: string | null;
}
```
#### Modify user `id` handling logic
The `user.id` is used to identify users. When introducing a new OAuth identity provider, you need to handle the information carried in the OAuth callback in `src/app/api/auth/next-auth.ts`. You need to select the user's `id` from this information. Before that, we need to understand the data processing sequence of `Auth.js`:
```txt
authorize --> jwt --> session
```
By default, in the `jwt --> session` process, `Auth.js` will [automatically assign the user `id` to `account.providerAccountId` based on the login type](https://authjs.dev/reference/core/types#provideraccountid). If you need to select a different value as the user `id`, you need to implement the following handling logic:
```ts
callbacks: {
async jwt({ token, account, profile }) {
if (account) {
// You can select a different value from `account` or `profile`
token.userId = account.providerAccountId;
}
return token;
},
},
```
#### Customize `session` return
If you want to carry more information about `profile` and `account` in the `session`, according to the data processing order mentioned above in `Auth.js`, you must first copy this information to the `token`. For example, add the user avatar URL `profile.picture` to the `session`:
```diff
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
token.userId = account.providerAccountId;
+ token.avatar = profile.picture;
}
return token;
},
async session({ session, token }) {
if (session.user) {
session.user.id = token.userId ?? session.user.id;
+ session.user.avatar = token.avatar;
}
return session;
},
},
```
Then supplement the type definition for the new parameters:
```ts
declare module '@auth/core/jwt' {
interface JWT {
// ...
avatar?: string;
}
}
declare module 'next-auth' {
interface User {
avatar?: string;
}
}
```
> [More built-in type extensions in Auth.js](https://authjs.dev/getting-started/typescript#module-augmentation)
#### Differentiate multiple authentication providers in the processing logic
If you have configured multiple authentication providers and their `userId` mappings are different, you can use the `account.provider` parameter in the `jwt` method to get the default id of the identity provider and enter different processing logic.
```ts
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
if (account.provider === 'authing')
token.userId = account.providerAccountId ?? token.sub;
else if (acount.provider === 'auth0')
token.userId = profile.sub ?? token.sub;
else
// other providers
}
return token;
},
}
```
Now, you can use Okta as your provider to implement the authentication feature in LobeChat.

View File

@ -0,0 +1,192 @@
# 新身份验证方式开发指南
LobeChat 使用 [Auth.js v5](https://authjs.dev/) 作为外部身份验证服务。Auth.js 是一个开源的身份验证库,它提供了一种简单的方式来实现身份验证和授权功能。本文档将介绍如何使用 Auth.js 来实现新的身份验证方式。
### TOC
- [添加新的身份验证提供者](#添加新的身份验证提供者)
- [准备工作:查阅官方的提供者列表](#准备工作查阅官方的提供者列表)
- [步骤 1: 新增关键代码](#步骤-1-新增关键代码)
- [步骤 2: 更新服务端配置代码](#步骤-2-更新服务端配置代码)
- [步骤 3: 修改前端页面](#步骤-3-修改前端页面)
- [步骤 4: 配置环境变量](#步骤-4-配置环境变量)
- [步骤 5: 修改服务端用户信息处理逻辑](#步骤-5-修改服务端用户信息处理逻辑)
## 添加新的身份验证提供者
为了在 LobeChat 中添加新的身份验证提供者(例如添加 Okta),你需要完成以下步骤:
### 准备工作:查阅官方的提供者列表
首先,你需要查阅 [Auth.js 提供者列表](https://authjs.dev/reference/core/providers) 来了解是否你的提供者已经被支持。如果你的提供者已经被支持,你可以直接使用 Auth.js 提供的 SDK 来实现身份验证功能。
接下来我会以 [Okta](https://authjs.dev/reference/core/providers/okta) 为例来介绍如何添加新的身份验证提供者
### 步骤 1: 新增关键代码
打开 `src/app/api/auth/next-auth.ts` 文件,引入 `next-auth/providers/okta`
```ts
import { NextAuth } from 'next-auth';
import Auth0 from 'next-auth/providers/auth0';
import Okta from 'next-auth/providers/okta';
// 引入 Okta 提供者
```
新增预定义的服务端配置
```ts
// 导入服务器配置
const { OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_ISSUER } = getServerConfig();
const nextAuth = NextAuth({
providers: [
// ... 其他提供者
Okta({
clientId: OKTA_CLIENT_ID,
clientSecret: OKTA_CLIENT_SECRET,
issuer: OKTA_ISSUER,
}),
],
});
```
### 步骤 2: 更新服务端配置代码
打开 `src/config/server/app.ts` 文件,在 `getAppConfig` 函数中新增 Okta 相关的环境变量
```ts
export const getAppConfig = () => {
// ... 其他代码
return {
// ... 其他环境变量
OKTA_CLIENT_ID: process.env.OKTA_CLIENT_ID || '',
OKTA_CLIENT_SECRET: process.env.OKTA_CLIENT_SECRET || '',
OKTA_ISSUER: process.env.OKTA_ISSUER || '',
};
};
```
### 步骤 3: 修改前端页面
修改在 `src/features/Conversation/Error/OAuthForm.tsx``src/app/settings/common/Common.tsx` 中的 `signIn` 函数参数
默认为 `auth0`,你可以将其修改为 `okta` 以切换到 Okta 提供者,或删除该参数以支持所有已添加的身份验证服务
该值为 Auth.js 提供者 的 id你可以阅读相应的 `next-auth/providers` 模块源码以读取默认 ID
### 步骤 4: 配置环境变量
在部署时新增 Okta 相关的环境变量 `OKTA_CLIENT_ID``OKTA_CLIENT_SECRET``OKTA_ISSUER`,并填入相应的值,即可使用
### 步骤 5: 修改服务端用户信息处理逻辑
#### 在前端获取用户信息
在前端页面中使用 `useOAuthSession()` 方法获取后端返回的用户信息 `user`
```ts
import { useOAuthSession } from '@/hooks/useOAuthSession';
const { user, isOAuthLoggedIn } = useOAuthSession();
```
默认的 `user` 类型为 `User`,类型定义为:
```ts
interface User {
id?: string;
name?: string | null;
email?: string | null;
image?: string | null;
}
```
#### 修改用户 `id` 处理逻辑
`user.id` 用于标识用户。当引入新身份 OAuth 提供者后,您需要在 `src/app/api/auth/next-auth.ts` 中处理 OAuth 回调所携带的信息。您需要从中选取用户的 `id`。在此之前,我们需要了解 `Auth.js` 的数据处理顺序:
```txt
authorize --> jwt --> session
```
默认情况下,在 `jwt --> session` 过程中,`Auth.js` 会[自动根据登陆类型](https://authjs.dev/reference/core/types#provideraccountid)将用户 `id` 赋值到 `account.providerAccountId` 中。 如果您需要选取其他值作为用户 `id` ,您需要实现以下处理逻辑。
```ts
callbacks: {
async jwt({ token, account, profile }) {
if (account) {
// 您可以从 `account``profile` 中选取其他值
token.userId = account.providerAccountId;
}
return token;
},
},
```
#### 自定义 `session` 返回
如果您想在 `session` 中携带更多关于 `profile``account` 的信息,根据上面提到的 `Auth.js` 数据处理顺序,那必须先将该信息复制到 `token` 上。
示例:把用户头像 URL`profile.picture` 添加到`session` 中:
```diff
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
token.userId = account.providerAccountId;
+ token.avatar = profile.picture;
}
return token;
},
async session({ session, token }) {
if (session.user) {
session.user.id = token.userId ?? session.user.id;
+ session.user.avatar = token.avatar;
}
return session;
},
},
```
然后补充对新增参数的类型定义:
```ts
declare module '@auth/core/jwt' {
interface JWT {
// ...
avatar?: string;
}
}
declare module 'next-auth' {
interface User {
avatar?: string;
}
}
```
> [更多`Auth.js`内置类型拓展](https://authjs.dev/getting-started/typescript#module-augmentation)
#### 在处理逻辑中区分多个身份验证提供者
如果您配置了多个身份验证提供者,并且他们的 `userId` 映射各不相同,可以在 `jwt` 方法中的 `account.provider` 参数获取身份提供者的默认 id ,从而进入不同的处理逻辑。
```ts
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
if (account.provider === 'Authing')
token.userId = account.providerAccountId ?? token.sub;
else if (acount.provider === 'Okta')
token.userId = profile.sub ?? token.sub;
else
// other providers
}
return token;
},
}
```

View File

@ -0,0 +1,47 @@
# Architecture Design
LobeChat is an AI conversation application built on the Next.js framework, aiming to provide an AI productivity platform that enables users to interact with AI through natural language. The following is an overview of the architecture design of LobeChat:
#### TOC
- [Application Architecture Overview](#application-architecture-overview)
- [Frontend Architecture](#frontend-architecture)
- [Edge Runtime API](#edge-runtime-api)
- [Agents Market](#agents-market)
- [Plugin Market](#plugin-market)
- [Security and Performance Optimization](#security-and-performance-optimization)
- [Development and Deployment Process](#development-and-deployment-process)
## Application Architecture Overview
The overall architecture of LobeChat consists of the frontend, EdgeRuntime API, Agents Market, Plugin Market, and independent plugins. These components collaborate to provide a complete AI experience.
## Frontend Architecture
The frontend of LobeChat adopts the Next.js framework, leveraging its powerful server-side rendering (SSR) capability and routing functionality. The frontend utilizes a stack of technologies, including the antd component library, lobe-ui AIGC component library, zustand state management, swr request library, i18next internationalization library, and more. These technologies collectively support the functionality and features of LobeChat.
The components in the frontend architecture include app, components, config, const, features, helpers, hooks, layout, locales, migrations, prompts, services, store, styles, types, and utils. Each component has specific responsibilities and collaborates with others to achieve different functionalities.
## Edge Runtime API
The Edge Runtime API is one of the core components of LobeChat, responsible for handling the core logic of AI conversations. It provides interaction interfaces with the AI engine, including natural language processing, intent recognition, and response generation. The EdgeRuntime API communicates with the frontend, receiving user input and returning corresponding responses.
## Agents Market
The Agents Market is a crucial part of LobeChat, providing various AI agents for different scenarios to handle specific tasks and domains. The Agents Market also offers functionality for discovering and uploading agents, allowing users to find agents created by others and easily share their own agents in the market.
## Plugin Market
The Plugin Market is another key component of LobeChat, offering various plugins to extend the functionality and features of LobeChat. Plugins can be independent functional modules or integrated with agents from the Agents Market. During conversations, the assistant automatically identifies user input, recognizes suitable plugins, and passes them to the corresponding plugins for processing and returns the results.
## Security and Performance Optimization
LobeChat's security strategy includes authentication and permission management. Users need to authenticate before using LobeChat, and operations are restricted based on the user's permissions.
To optimize performance, LobeChat utilizes Next.js SSR functionality to achieve fast page loading and response times. Additionally, a series of performance optimization measures are implemented, including code splitting, caching, and resource compression.
## Development and Deployment Process
LobeChat's development process includes version control, testing, continuous integration, and continuous deployment. The development team uses version control systems for code management and conducts unit and integration testing to ensure code quality. Continuous integration and deployment processes ensure rapid delivery and deployment of code.
The above is a brief introduction to the architecture design of LobeChat, detailing the responsibilities and collaboration of each component, as well as the impact of design decisions on application functionality and performance.

View File

@ -0,0 +1,47 @@
# 架构设计
LobeChat 是一个基于 Next.js 框架构建的 AI 会话应用,旨在提供一个 AI 生产力平台,使用户能够与 AI 进行自然语言交互。以下是 LobeChat 的架构设计介稿:
#### TOC
- [应用架构概览](#应用架构概览)
- [前端架构](#前端架构)
- [Edge Runtime API](#edge-runtime-api)
- [Agents 市场](#agents-市场)
- [插件市场](#插件市场)
- [安全性和性能优化](#安全性和性能优化)
- [开发和部署流程](#开发和部署流程)
## 应用架构概览
LobeChat 的整体架构由前端、EdgeRuntime API、Agents 市场、插件市场和独立插件组成。这些组件相互协作,以提供完整的 AI 体验。
## 前端架构
LobeChat 的前端采用 Next.js 框架,利用其强大的 SSR服务器端渲染能力和路由功能。前端使用了一系列技术栈包括 antd 组件库和 lobe-ui AIGC 组件库、zustand 状态管理、swr 请求库、i18next 国际化库等。这些技术栈共同支持了 LobeChat 的功能和特性。
前端架构中的组件包括 app、components、config、const、features、helpers、hooks、layout、locales、migrations、prompts、services、store、styles、types 和 utils。每个组件都有特定的职责并与其他组件协同工作以实现不同的功能。
## Edge Runtime API
Edge Runtime API 是 LobeChat 的核心组件之一,负责处理 AI 会话的核心逻辑。它提供了与 AI 引擎的交互接口包括自然语言处理、意图识别和回复生成等。EdgeRuntime API 与前端进行通信,接收用户的输入并返回相应的回复。
## Agents 市场
Agents 市场是 LobeChat 的一个重要组成部分,它提供了各种不同场景的 AI Agent用于处理特定的任务和领域。Agents 市场还提供了使用和上传 Agent 的功能,使用户能够发现其他人制作的 Agent ,也可以一键分享自己的 Agent 到市场上。
## 插件市场
插件市场是 LobeChat 的另一个关键组件,它提供了各种插件,用于扩展 LobeChat 的功能和特性。插件可以是独立的功能模块,也可以与 Agents 市场的 Agent 进行集成。在会话中,助手将自动识别用户的输入,并识别适合的插件并传递给相应的插件进行处理,并返回处理结果。
## 安全性和性能优化
LobeChat 的安全性策略包括身份验证和权限管理。用户需要进行身份验证后才能使用 LobeChat同时根据用户的权限进行相应的操作限制。
为了优化性能LobeChat 使用了 Next.js 的 SSR 功能,实现了快速的页面加载和响应时间。此外,还采用了一系列的性能优化措施,包括代码分割、缓存和资源压缩等。
## 开发和部署流程
LobeChat 的开发流程包括版本控制、测试、持续集成和持续部署。开发团队使用版本控制系统进行代码管理,并进行单元测试和集成测试以确保代码质量。持续集成和持续部署流程确保了代码的快速交付和部署。
以上是 LobeChat 的架构设计介绍简介,详细解释了各个组件的职责和协作方式,以及设计决策对应用功能和性能的影响。

View File

@ -0,0 +1,136 @@
# Conversation API Implementation Logic
The implementation of LobeChat's large model AI mainly relies on OpenAI's API, including the core conversation API on the backend and the integrated API on the frontend. Next, we will introduce the implementation approach and code for the backend and frontend separately.
#### TOC
- [Backend Implementation](#backend-implementation)
- [Core Conversation API](#core-conversation-api)
- [Conversation Result Processing](#conversation-result-processing)
- [Frontend Implementation](#frontend-implementation)
- [Frontend Integration](#frontend-integration)
- [Using Streaming to Get Results](#using-streaming-to-get-results)
## Backend Implementation
The following code removes authentication, error handling, and other logic, retaining only the core functionality logic.
### Core Conversation API
In the file `src/app/api/openai/chat/handler.ts`, we define a `POST` method, which first parses the payload data from the request (i.e., the conversation content sent by the client), and then retrieves the authorization information from the request. Then, we create an `openai` object and call the `createChatCompletion` method, which is responsible for sending the conversation request to OpenAI and returning the result.
```ts
export const POST = async (req: Request) => {
const payload = await req.json();
const { apiKey, endpoint } = getOpenAIAuthFromRequest(req);
const openai = createOpenai(apiKey, endpoint);
return createChatCompletion({ openai, payload });
};
```
### Conversation Result Processing
In the file `src/app/api/openai/chat/createChatCompletion.ts`, we define the `createChatCompletion` method, which first preprocesses the payload data, then calls OpenAI's `chat.completions.create` method to send the request, and uses the `OpenAIStream` from the [Vercel AI SDK](https://sdk.vercel.ai/docs) to convert the returned result into a streaming response.
```ts
import { OpenAIStream, StreamingTextResponse } from 'ai';
export const createChatCompletion = async ({ payload, openai }: CreateChatCompletionOptions) => {
const { messages, ...params } = payload;
const formatMessages = messages.map((m) => ({
content: m.content,
name: m.name,
role: m.role,
}));
const response = await openai.chat.completions.create(
{
messages: formatMessages,
...params,
stream: true,
},
{ headers: { Accept: '*/*' } },
);
const stream = OpenAIStream(response);
return new StreamingTextResponse(stream);
};
```
## Frontend Implementation
### Frontend Integration
In the `src/services/chatModel.ts` file, we define the `fetchChatModel` method, which first preprocesses the payload data, then sends a POST request to the `/chat` endpoint on the backend, and returns the request result.
```ts
export const fetchChatModel = (
{ plugins: enabledPlugins, ...params }: Partial<OpenAIStreamPayload>,
options?: FetchChatModelOptions,
) => {
const payload = merge(
{
model: initialLobeAgentConfig.model,
stream: true,
...initialLobeAgentConfig.params,
},
params,
);
const filterFunctions: ChatCompletionFunctions[] = pluginSelectors.enabledSchema(enabledPlugins)(
usePluginStore.getState(),
);
const functions = filterFunctions.length === 0 ? undefined : filterFunctions;
return fetch(OPENAI_URLS.chat, {
body: JSON.stringify({ ...payload, functions }),
headers: createHeaderWithOpenAI({ 'Content-Type': 'application/json' }),
method: 'POST',
signal: options?.signal,
});
};
```
### Using Streaming to Get Results
In the `src/utils/fetch.ts` file, we define the `fetchSSE` method, which uses a streaming approach to retrieve data. When a new data chunk is read, it calls the `onMessageHandle` callback function to process the data chunk, achieving a typewriter-like output effect.
```ts
export const fetchSSE = async (fetchFn: () => Promise<Response>, options: FetchSSEOptions = {}) => {
const response = await fetchFn();
if (!response.ok) {
const chatMessageError = await getMessageError(response);
options.onErrorHandle?.(chatMessageError);
return;
}
const returnRes = response.clone();
const data = response.body;
if (!data) return;
const reader = data.getReader();
const decoder = new TextDecoder();
let done = false;
while (!done) {
const { value, done: doneReading } = await reader.read();
done = doneReading;
const chunkValue = decoder.decode(value);
options.onMessageHandle?.(chunkValue);
}
return returnRes;
};
```
The above is the core implementation of the LobeChat session API. With an understanding of these core codes, further expansion and optimization of LobeChat's AI functionality can be achieved.

View File

@ -0,0 +1,174 @@
# 会话 API 实现逻辑
LobeChat 的大模型 AI 实现主要依赖于 OpenAI 的 API包括后端的核心会话 API 和前端的集成 API。接下来我们将分别介绍后端和前端的实现思路和代码。
#### TOC
- [后端实现](#后端实现)
- [核心会话 API](#核心会话-api)
- [会话结果处理](#会话结果处理)
- [前端实现](#前端实现)
- [前端集成](#前端集成)
- [使用流式获取结果](#使用流式获取结果)
## 后端实现
以下代码中移除了鉴权、错误处理等逻辑,仅保留了核心的主要功能逻辑。
### 核心会话 API
`src/app/api/openai/chat/route.ts` 中,定义了一个处理 POST 请求的方法,主要负责从请求体中提取 `OpenAIChatStreamPayload` 类型的 payload并使用 `createBizOpenAI` 函数根据请求和模型信息创建 OpenAI 实例。随后,该方法调用 `createChatCompletion` 来处理实际的会话,并返回响应结果。如果创建 OpenAI 实例过程中出现错误,则直接返回错误响应。
```ts
export const POST = async (req: Request) => {
const payload = (await req.json()) as OpenAIChatStreamPayload;
const openaiOrErrResponse = createBizOpenAI(req, payload.model);
// if resOrOpenAI is a Response, it means there is an error,just return it
if (openaiOrErrResponse instanceof Response) return openaiOrErrResponse;
return createChatCompletion({ openai: openaiOrErrResponse, payload });
};
```
### 会话结果处理
而在 `src/app/api/openai/chat/createChatCompletion.ts` 文件中,`createChatCompletion` 方法主要负责与 OpenAI API 进行交互,处理会话请求。它首先对 payload 中的消息进行预处理,然后通过 `openai.chat.completions.create` 方法发送 API 请求,并使用 `OpenAIStream` 将返回的响应转换为流式格式。如果在 API 调用过程中出现错误,方法将生成并处理相应的错误响应。
```ts
import { OpenAIStream, StreamingTextResponse } from 'ai';
export const createChatCompletion = async ({ payload, openai }: CreateChatCompletionOptions) => {
// 预处理消息
const { messages, ...params } = payload;
// 发送 API 请求
try {
const response = await openai.chat.completions.create(
{
messages,
...params,
stream: true,
} as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
{ headers: { Accept: '*/*' } },
);
const stream = OpenAIStream(response);
return new StreamingTextResponse(stream);
} catch (error) {
// 检查错误是否为 OpenAI APIError
if (error instanceof OpenAI.APIError) {
let errorResult: any;
// 如果错误是 OpenAI APIError那么会有一个 error 对象
if (error.error) {
errorResult = error.error;
} else if (error.cause) {
errorResult = error.cause;
}
// 如果没有其他请求错误,错误对象是一个类似 Response 的对象
else {
errorResult = { headers: error.headers, stack: error.stack, status: error.status };
}
console.error(errorResult);
// 返回错误响应
return createErrorResponse(ChatErrorType.OpenAIBizError, {
endpoint: openai.baseURL,
error: errorResult,
});
}
console.error(error);
return createErrorResponse(ChatErrorType.InternalServerError, {
endpoint: openai.baseURL,
error: JSON.stringify(error),
});
}
};
```
## 前端实现
### 前端集成
`src/services/chat.ts` 文件中,我们定义了 `ChatService` 类。这个类提供了一些方法来处理与 OpenAI 聊天 API 的交互。
`createAssistantMessage` 方法用于创建一个新的助手消息。它接收一个包含插件、消息和其他参数的对象,以及一个可选的 `FetchOptions` 对象。这个方法会合并默认的代理配置和传入的参数,预处理消息和工具,然后调用 `getChatCompletion` 方法获取聊天完成任务。
`getChatCompletion` 方法用于获取聊天完成任务。它接收一个 `OpenAIChatStreamPayload` 对象和一个可选的 `FetchOptions` 对象。这个方法会合并默认的代理配置和传入的参数,然后发送 POST 请求到 OpenAI 的聊天 API。
`runPluginApi` 方法用于运行插件 API 并获取结果。它接收一个 `PluginRequestPayload` 对象和一个可选的 `FetchOptions` 对象。这个方法会从工具存储中获取状态,通过插件标识符获取插件设置和清单,然后发送 POST 请求到插件的网关 URL。
`fetchPresetTaskResult` 方法用于获取预设任务的结果。它使用 `fetchAIFactory` 工厂函数创建一个新的函数,这个函数接收一个聊天完成任务的参数,并返回一个 Promise。当 Promise 解析时,返回的结果是聊天完成任务的结果。
`processMessages` 方法用于处理聊天消息。它接收一个聊天消息数组,一个可选的模型名称,和一个可选的工具数组。这个方法会处理消息内容,将输入的 `messages` 数组映射为 `OpenAIChatMessage` 类型的数组,如果存在启用的工具,将工具的系统角色添加到系统消息中。
```ts
class ChatService {
// 创建一个新的助手消息
createAssistantMessage(params: object, fetchOptions?: FetchOptions) {
// 实现细节...
}
// 获取聊天完成任务
getChatCompletion(payload: OpenAIChatStreamPayload, fetchOptions?: FetchOptions) {
// 实现细节...
}
// 运行插件 API 并获取结果
runPluginApi(payload: PluginRequestPayload, fetchOptions?: FetchOptions) {
// 实现细节...
}
// 获取预设任务的结果
fetchPresetTaskResult() {
// 实现细节...
}
// 处理聊天消息
processMessages(messages: ChatMessage[], modelName?: string, tools?: Tool[]) {
// 实现细节...
}
}
```
### 使用流式获取结果
`src/utils/fetch.ts` 文件中,我们定义了 `fetchSSE` 方法,该方法使用流式方法获取数据,当读取到新的数据块时,会调用 `onMessageHandle` 回调函数处理数据块,进而实现打字机输出效果。
```ts
export const fetchSSE = async (fetchFn: () => Promise<Response>, options: FetchSSEOptions = {}) => {
const response = await fetchFn();
// 如果不 ok 说明有请求错误
if (!response.ok) {
const chatMessageError = await getMessageError(response);
options.onErrorHandle?.(chatMessageError);
return;
}
const returnRes = response.clone();
const data = response.body;
if (!data) return;
let output = '';
const reader = data.getReader();
const decoder = new TextDecoder();
let done = false;
while (!done) {
const { value, done: doneReading } = await reader.read();
done = doneReading;
const chunkValue = decoder.decode(value, { stream: true });
output += chunkValue;
options.onMessageHandle?.(chunkValue);
}
await options?.onFinish?.(output);
return returnRes;
};
```
以上就是 LobeChat 会话 API 的核心实现。在理解了这些核心代码的基础上,便可以进一步扩展和优化 LobeChat 的 AI 功能。

View File

@ -0,0 +1,83 @@
# Code Style and Contribution Guidelines
Welcome to the Code Style and Contribution Guidelines for LobeChat. This guide will help you understand our code standards and contribution process, ensuring code consistency and smooth project progression.
## TOC
- [Code Style](#code-style)
- [ESLint](#eslint)
- [Prettier](#prettier)
- [remarklint](#remarklint)
- [stylelint](#stylelint)
- [Contribution Process](#contribution-process)
- [Gitmoji](#gitmoji)
- [Semantic Release](#semantic-release)
- [Commitlint](#commitlint)
- [How to Contribute](#how-to-contribute)
## Code Style
In LobeChat, we use the `@lobehub/lint` package to maintain a unified code style. This package incorporates configurations for `ESLint`, `Prettier`, `remarklint`, and `stylelint` to ensure that our JavaScript, Markdown, and CSS files adhere to the same coding standards.
### ESLint
We use ESLint to check for issues in our JavaScript code. You can find the `.eslintrc.js` file in the project's root directory, which contains our extensions and custom rules for the ESLint configuration of `@lobehub/lint`.
To ensure your code aligns with the project's standards, run ESLint before committing your code.
### Prettier
Prettier is responsible for code formatting to maintain consistency. Our Prettier configuration can be found in `.prettierrc.js`, imported from `@lobehub/lint`.
It's recommended to configure your editor to run Prettier automatically upon saving files or manually run it before committing.
### remarklint
For Markdown files, we use remarklint to ensure consistent document formatting. You can find the corresponding configuration file in the project.
### stylelint
We utilize stylelint to standardize the style of our CSS code. In the configuration file for stylelint, we have made some custom rule adjustments based on `@lobehub/lint` configuration.
Ensure that your style code passes stylelint checks before committing.
## Contribution Process
LobeChat follows the gitmoji and semantic release as our code submission and release process.
### Gitmoji
When committing code, please use gitmoji to label your commit messages. This helps other contributors quickly understand the content and purpose of your submission.
Gitmoji commit messages use specific emojis to represent the type or intent of the commit. Here's an example:
```
📝 Update README with contribution guidelines
- Added section about code style preferences
- Included instructions for running tests
- Corrected typos and improved formatting
```
In this example, the 📝 emoji represents a documentation update. The commit message clearly describes the changes and provides specific details.
### Semantic Release
We use semantic release to automate version control and release processes. Ensure that your commit messages adhere to the semantic release specifications so that when the code is merged into the main branch, the system can automatically create a new version and release it.
### Commitlint
To ensure consistency in commit messages, we use `commitlint` to check the format of commit messages. You can find the relevant rules in the `.commitlintrc.js` configuration file.
Before committing your code, ensure that your commit messages adhere to our standards.
### How to Contribute
1. Fork the project to your account.
2. Create a new branch for development.
3. After completing the development, ensure that your code passes the aforementioned code style checks.
4. Commit your changes and use appropriate gitmoji to label your commit message.
5. Create a Pull Request to the main branch of the original project.
6. Await code review and make necessary modifications based on feedback.
Thank you for following these guidelines, as they help us maintain the quality and consistency of the project. We look forward to your contributions!

View File

@ -0,0 +1,85 @@
# 代码风格与贡献指南
欢迎来到 LobeChat 的代码风格与贡献指南。本指南将帮助您理解我们的代码规范和贡献流程,确保代码的一致性和项目的顺利进行。
## TOC
- [代码风格](#代码风格)
- [ESLint](#eslint)
- [Prettier](#prettier)
- [remarklint](#remarklint)
- [stylelint](#stylelint)
- [贡献流程](#贡献流程)
- [Gitmoji](#gitmoji)
- [Semantic Release](#semantic-release)
- [Commitlint](#commitlint)
- [如何贡献](#如何贡献)
## 代码风格
在 LobeChat 中,我们使用 `@lobehub/lint` 程序包来统一代码风格。该程序包内置了 `ESLint``Prettier``remarklint``stylelint` 的配置,以确保我们的 JavaScript、Markdown 和 CSS 文件遵循相同的编码标准。
### ESLint
我们的项目使用 ESLint 来检查 JavaScript 代码中的问题。您可以在项目根目录下找到 `.eslintrc.js` 文件,其中包含了我们对 `@lobehub/lint` 的 ESLint 配置的扩展和自定义规则。
为了与 Next.js 框架兼容,我们在配置中添加了 `plugin:@next/next/recommended`。此外,我们禁用了一些规则,以适应我们项目的特定需求。
请在提交代码前运行 ESLint以确保您的代码符合项目规范。
### Prettier
Prettier 负责代码格式化,以保证代码的一致性。您可以在 `.prettierrc.js` 中找到我们的 Prettier 配置,它是从 `@lobehub/lint` 导入的。
在保存文件时,建议您配置您的编辑器以自动运行 Prettier或者在提交前手动运行它。
### remarklint
对于 Markdown 文件,我们使用 remarklint 来确保文档格式的统一。您可以在项目中找到相应的配置文件。
### stylelint
我们使用 stylelint 来规范 CSS 代码的风格。在 `stylelint` 的配置文件中,我们基于 `@lobehub/lint` 的配置进行了一些自定义规则的调整。
确保您的样式代码在提交前通过了 stylelint 的检查。
## 贡献流程
LobeChat 采用 gitmoji 和 semantic release 作为我们的代码提交和发布流程。
### Gitmoji
在提交代码时,请使用 gitmoji 来标注您的提交信息。这有助于其他贡献者快速理解您提交的内容和目的。
Gitmoji commit messages 使用特定的 emoji 来表示提交的类型或意图。以下是一个示例:
```
📝 Update README with contribution guidelines
- Added section about code style preferences
- Included instructions for running tests
- Corrected typos and improved formatting
```
在这个示例中,📝 emoji 代表了文档的更新。提交信息清晰地描述了更改的内容,提供了具体的细节。
### Semantic Release
我们使用 semantic release 来自动化版本控制和发布流程。请确保您的提交信息遵循 semantic release 的规范,这样当代码合并到主分支后,系统就可以自动创建新的版本并发布。
### Commitlint
为了确保提交信息的一致性,我们使用 `commitlint` 来检查提交信息格式。您可以在 `.commitlintrc.js` 配置文件中找到相关规则。
在您提交代码之前,请确保您的提交信息遵循我们的规范。
### 如何贡献
1. Fork 项目到您的账户。
2. 创建一个新的分支进行开发。
3. 开发完成后,确保您的代码通过了上述的代码风格检查。
4. 提交您的更改,并使用合适的 gitmoji 标注您的提交信息。
5. 创建一个 Pull Request 到原项目的主分支。
6. 等待代码审查,并根据反馈进行必要的修改。
感谢您遵循这些指导原则,它们有助于我们维护项目的质量和一致性。我们期待您的贡献!

View File

@ -0,0 +1,126 @@
# How to Develop a New Feature
LobeChat is built on the Next.js framework and uses TypeScript as the primary development language. When developing a new feature, we need to follow a certain development process to ensure the quality and stability of the code. The general process can be divided into the following five steps:
1. Routing: Define routes (`src/app`).
2. Data Structure: Define data structures (`src/types`).
3. Business Logic Implementation: Zustand store (`src/store`).
4. Page Display: Write static components/pages (`src/app/<new-page>/features/<new-feature>.tsx`).
5. Function Binding: Bind the store with page triggers (`const [state, function] = useNewStore(s => [s.state, s.function])`).
Taking the "Chat Messages" feature as an example, here are the brief steps to implement this feature:
#### TOC
- [1. Define Routes](#1-define-routes)
- [2. Define Data Structure](#2-define-data-structure)
- [3. Create Zustand Store](#3-create-zustand-store)
- [4. Create Page and Components](#4-create-page-and-components)
- [5. Function Binding](#5-function-binding)
## 1. Define Routes
In the `src/app` directory, we need to define a new route to host the "Chat Messages" page. Generally, we would create a new folder under `src/app`, for example, `chat`, and create a `page.tsx` file within this folder to export a React component as the main body of the page.
```tsx
// src/app/chat/page.tsx
import ChatPage from './features/chat';
export default ChatPage;
```
## 2. Define Data Structure
In the `src/types` directory, we need to define the data structure for "Chat Messages". For example, we create a `chat.ts` file and define the `ChatMessage` type within it:
```ts
// src/types/chat.ts
export type ChatMessage = {
id: string;
content: string;
timestamp: number;
sender: 'user' | 'bot';
};
```
## 3. Create Zustand Store
In the `src/store` directory, we need to create a new Zustand Store to manage the state of "Chat Messages". For example, we create a `chatStore.ts` file and define a Zustand Store within it:
```ts
// src/store/chatStore.ts
import create from 'zustand';
type ChatState = {
messages: ChatMessage[];
addMessage: (message: ChatMessage) => void;
};
export const useChatStore = create<ChatState>((set) => ({
messages: [],
addMessage: (message) => set((state) => ({ messages: [...state.messages, message] })),
}));
```
## 4. Create Page and Components
In `src/app/<new-page>/features/<new-feature>.tsx`, we need to create a new page or component to display "Chat Messages". In this file, we can use the Zustand Store created earlier and Ant Design components to build the UI:
```jsx
// src/features/chat/index.tsx
import { List, Typography } from 'antd';
import { useChatStore } from 'src/store/chatStore';
const ChatPage = () => {
const messages = useChatStore((state) => state.messages);
return (
<List
dataSource={messages}
renderItem={(message) => (
<List.Item>
<Typography.Text>{message.content}</Typography.Text>
</List.Item>
)}
/>
);
};
export default ChatPage;
```
## 5. Function Binding
In a page or component, we need to bind the Zustand Store's state and methods to the UI. In the example above, we have already bound the `messages` state to the `dataSource` property of the list. Now, we also need a method to add new messages. We can define this method in the Zustand Store and then use it in the page or component:
```jsx
import { Button } from 'antd';
const ChatPage = () => {
const messages = useChatStore((state) => state.messages);
const addMessage = useChatStore((state) => state.addMessage);
const handleSend = () => {
addMessage({ id: '1', content: 'Hello, world!', timestamp: Date.now(), sender: 'user' });
};
return (
<>
<List
dataSource={messages}
renderItem={(message) => (
<List.Item>
<Typography.Text>{message.content}</Typography.Text>
</List.Item>
)}
/>
<Button onClick={handleSend}>Send</Button>
</>
);
};
export default ChatPage;
```
The above is the step to implement the "chat message" feature in LobeChat. Of course, in the actual development of LobeChat, the business requirements and scenarios faced in real situations are far more complex than the above demo. Please develop according to the actual situation.

View File

@ -0,0 +1,126 @@
# 如何开发一个新功能:前端实现
LobeChat 基于 Next.js 框架构建,使用 TypeScript 作为主要开发语言。在开发新功能时,我们需要遵循一定的开发流程,以确保代码的质量和稳定性。大致的流程分为以下五步:
1. 路由:定义路由 (`src/app`)
2. 数据结构: 定义数据结构 ( `src/types` )
3. 业务功能实现: zustand store (`src/store`)
4. 页面展示:书写静态组件 / 页面 (`src/app/<new-page>/features/<new-feature>.tsx`)
5. 功能绑定:绑定 store 与页面的触发 (`const [state,function]= useNewStore(s=>[s.state,s.function])`)
我们以 "会话消息" 功能为例,以下是实现这个功能的简要步骤:
#### TOC
- [1. 定义路由](#1-定义路由)
- [2. 定义数据结构](#2-定义数据结构)
- [3. 创建 Zustand Store](#3-创建-zustand-store)
- [4. 创建页面与组件](#4-创建页面与组件)
- [5. 功能绑定](#5-功能绑定)
## 1. 定义路由
`src/app` 目录下,我们需要定义一个新的路由来承载 "会话消息" 页面。一般来说,我们会在 `src/app` 下创建一个新的文件夹,例如 `chat`,并且在这个文件夹中创建 `page.tsx`文件,在该文件中导出 React 组件作为页面的主体。
```tsx
// src/app/chat/page.tsx
import ChatPage from './features/chat';
export default ChatPage;
```
## 2. 定义数据结构
`src/types` 目录下,我们需要定义 "会话消息" 的数据结构。例如,我们创建一个 `chat.ts` 文件,并在其中定义 `ChatMessage` 类型:
```ts
// src/types/chat.ts
export type ChatMessage = {
id: string;
content: string;
timestamp: number;
sender: 'user' | 'bot';
};
```
## 3. 创建 Zustand Store
`src/store` 目录下,我们需要创建一个新的 Zustand Store 来管理 "会话消息" 的状态。例如,我们创建一个 `chatStore.ts` 文件,并在其中定义一个 Zustand Store
```ts
// src/store/chatStore.ts
import create from 'zustand';
type ChatState = {
messages: ChatMessage[];
addMessage: (message: ChatMessage) => void;
};
export const useChatStore = create<ChatState>((set) => ({
messages: [],
addMessage: (message) => set((state) => ({ messages: [...state.messages, message] })),
}));
```
## 4. 创建页面与组件
`src/app/<new-page>/features/<new-feature>.tsx` 中,我们需要创建一个新的页面或组件来显示 "会话消息"。在这个文件中,我们可以使用上面创建的 Zustand Store以及 Ant Design 的组件来构建 UI
```jsx
// src/features/chat/index.tsx
import { List, Typography } from 'antd';
import { useChatStore } from 'src/store/chatStore';
const ChatPage = () => {
const messages = useChatStore((state) => state.messages);
return (
<List
dataSource={messages}
renderItem={(message) => (
<List.Item>
<Typography.Text>{message.content}</Typography.Text>
</List.Item>
)}
/>
);
};
export default ChatPage;
```
## 5. 功能绑定
在页面或组件中,我们需要将 Zustand Store 的状态和方法绑定到 UI 上。在上面的示例中,我们已经将 `messages` 状态绑定到了列表的 `dataSource` 属性上。现在,我们还需要一个方法来添加新的消息。我们可以在 Zustand Store 中定义这个方法,然后在页面或组件中使用它:
```jsx
import { Button } from 'antd';
const ChatPage = () => {
const messages = useChatStore((state) => state.messages);
const addMessage = useChatStore((state) => state.addMessage);
const handleSend = () => {
addMessage({ id: '1', content: 'Hello, world!', timestamp: Date.now(), sender: 'user' });
};
return (
<>
<List
dataSource={messages}
renderItem={(message) => (
<List.Item>
<Typography.Text>{message.content}</Typography.Text>
</List.Item>
)}
/>
<Button onClick={handleSend}>Send</Button>
</>
);
};
export default ChatPage;
```
以上就是在 LobeChat 中实现 "会话消息" 功能的步骤。当然,在 LobeChat 的实际开发中,真实场景所面临的业务诉求和场景远比上述 demo 复杂,请根据实际情况进行开发。

View File

@ -0,0 +1,713 @@
# Complete Guide to LobeChat Feature Development
This document aims to guide developers on how to develop a complete feature requirement in LobeChat.
We will use the implementation of sessionGroup as an example: [✨ feat: add session group manager](https://github.com/lobehub/lobe-chat/pull/1055), and explain the complete implementation process through the following six main sections:
1. Data Model / Database Definition
2. Service Implementation / Model Implementation
3. Frontend Data Flow Store Implementation
4. UI Implementation and Action Binding
5. Data Migration
6. Data Import and Export
## 1. Database Section
To implement the Session Group feature, it is necessary to define the relevant data model and indexes at the database level.
Define a new sessionGroup table in 3 steps:
### 1. Establish Data Model Schema
Define the data model of `DB_SessionGroup` in `src/database/schema/sessionGroup.ts`:
```typescript
import { z } from 'zod';
export const DB_SessionGroupSchema = z.object({
name: z.string(),
sort: z.number().optional(),
});
export type DB_SessionGroup = z.infer<typeof DB_SessionGroupSchema>;
```
### 2. Create Database Indexes
Since a new table needs to be added, an index needs to be added to the database schema for the `sessionGroup` table.
Add `dbSchemaV4` in `src/database/core/schema.ts`:
```diff
// ... previous implementations
// ************************************** //
// ******* Version 3 - 2023-12-06 ******* //
// ************************************** //
// - Added `plugin` table
export const dbSchemaV3 = {
...dbSchemaV2,
plugins:
'&identifier, type, manifest.type, manifest.meta.title, manifest.meta.description, manifest.meta.author, createdAt, updatedAt',
};
+ // ************************************** //
+ // ******* Version 4 - 2024-01-21 ******* //
+ // ************************************** //
+ // - Added `sessionGroup` table
+ export const dbSchemaV4 = {
+ ...dbSchemaV3,
+ sessionGroups: '&id, name, sort, createdAt, updatedAt',
+ sessions: '&id, type, group, pinned, meta.title, meta.description, meta.tags, createdAt, updatedAt',
};
```
> \[!Note]
>
> In addition to `sessionGroups`, the definition of `sessions` has also been modified here due to data migration. However, as this section only focuses on schema definition and does not delve into the implementation of data migration, please refer to section five for details.
> \[!Important]
>
> If you are unfamiliar with the need to create indexes here and the syntax of schema definition, you may need to familiarize yourself with the basics of Dexie.js. You can refer to the [📘 Local Database](./Local-Database.zh-CN) section for relevant information.
### 3. Add the sessionGroups Table to the Local DB
Extend the local database class to include the new `sessionGroups` table:
```diff
import { dbSchemaV1, dbSchemaV2, dbSchemaV3, dbSchemaV4 } from './schemas';
interface LobeDBSchemaMap {
files: DB_File;
messages: DB_Message;
plugins: DB_Plugin;
+ sessionGroups: DB_SessionGroup;
sessions: DB_Session;
topics: DB_Topic;
}
// Define a local DB
export class LocalDB extends Dexie {
public files: LobeDBTable<'files'>;
public sessions: LobeDBTable<'sessions'>;
public messages: LobeDBTable<'messages'>;
public topics: LobeDBTable<'topics'>;
public plugins: LobeDBTable<'plugins'>;
+ public sessionGroups: LobeDBTable<'sessionGroups'>;
constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
this.version(1).stores(dbSchemaV1);
this.version(2).stores(dbSchemaV2);
this.version(3).stores(dbSchemaV3);
+ this.version(4).stores(dbSchemaV4);
this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
+ this.sessionGroups = this.table('sessionGroups');
}
}
```
As a result, you can now view the `sessionGroups` table in the `LOBE_CHAT_DB` in `Application` -> `Storage` -> `IndexedDB`.
![](https://github.com/lobehub/lobe-chat/assets/28616219/aea50f66-4060-4a32-88c8-b3c672d05be8)
## 2. Model and Service Section
### Define Model
When building the LobeChat application, the Model is responsible for interacting with the database. It defines how to read, insert, update, and delete data from the database, as well as defining specific business logic.
In `src/database/model/sessionGroup.ts`, the `SessionGroupModel` is defined as follows:
```typescript
import { BaseModel } from '@/database/core';
import { DB_SessionGroup, DB_SessionGroupSchema } from '@/database/schemas/sessionGroup';
import { nanoid } from '@/utils/uuid';
class _SessionGroupModel extends BaseModel {
constructor() {
super('sessions', DB_SessionGroupSchema);
}
async create(name: string, sort?: number, id = nanoid()) {
return this._add({ name, sort }, id);
}
// ... Implementation of other CRUD methods
}
export const SessionGroupModel = new _SessionGroupModel();
```
### Service Implementation
In LobeChat, the Service layer is mainly responsible for communicating with the backend service, encapsulating business logic, and providing data to other layers in the frontend. `SessionService` is a service class specifically handling business logic related to sessions. It encapsulates operations such as creating sessions, querying sessions, and updating sessions.
To maintain code maintainability and extensibility, we place the logic related to session grouping in the `SessionService`. This helps to keep the business logic of the session domain cohesive. When business requirements increase or change, it becomes easier to modify and extend within this domain.
`SessionService` implements session group-related request logic by calling methods from `SessionGroupModel`. The following is the implementation of Session Group-related request logic in `sessionService`:
```typescript
class SessionService {
// ... Omitted session business logic
// ************************************** //
// *********** SessionGroup *********** //
// ************************************** //
async createSessionGroup(name: string, sort?: number) {
const item = await SessionGroupModel.create(name, sort);
if (!item) {
throw new Error('session group create Error');
}
return item.id;
}
// ... Other SessionGroup related implementations
}
```
## 3. Store Action Section
In the LobeChat application, the Store module is used to manage the frontend state of the application. The Actions within it are functions that trigger state updates, usually by calling methods in the service layer to perform actual data processing operations and then updating the state in the Store. We use `zustand` as the underlying dependency for the Store module. For a detailed practical introduction to state management, you can refer to [📘 Best Practices for State Management](../State-Management/State-Management-Intro.zh-CN.md).
### sessionGroup CRUD
CRUD operations for session groups are the core behaviors for managing session group data. In `src/store/session/slice/sessionGroup`, we will implement the state logic related to session groups, including adding, deleting, updating session groups, and their sorting.
The following are the methods of the `SessionGroupAction` interface that need to be implemented in the `action.ts` file:
```ts
export interface SessionGroupAction {
// Add session group
addSessionGroup: (name: string) => Promise<string>;
// Remove session group
removeSessionGroup: (id: string) => Promise<void>;
// Update session group ID for a session
updateSessionGroupId: (sessionId: string, groupId: string) => Promise<void>;
// Update session group name
updateSessionGroupName: (id: string, name: string) => Promise<void>;
// Update session group sorting
updateSessionGroupSort: (items: SessionGroupItem[]) => Promise<void>;
}
```
Taking the `addSessionGroup` method as an example, we first call the `createSessionGroup` method of `sessionService` to create a new session group, and then use the `refreshSessions` method to refresh the sessions state:
```ts
export const createSessionGroupSlice: StateCreator<
SessionStore,
[['zustand/devtools', never]],
[],
SessionGroupAction
> = (set, get) => ({
// Implement the logic for adding a session group
addSessionGroup: async (name) => {
// Call the createSessionGroup method in the service layer and pass in the session group name
const id = await sessionService.createSessionGroup(name);
// Call the get method to get the current Store state and execute the refreshSessions method to refresh the session data
await get().refreshSessions();
// Return the ID of the newly created session group
return id;
},
// ... Other action implementations
});
```
With the above implementation, we can ensure that after adding a new session group, the application's state will be updated in a timely manner, and the relevant components will receive the latest state and re-render. This approach improves the predictability and maintainability of the data flow, while also simplifying communication between components.
### Sessions Group Logic Refactoring
This requirement involves upgrading the Sessions feature to transform it from a single list to three different groups: `pinnedSessions` (pinned list), `customSessionGroups` (custom groups), and `defaultSessions` (default list).
To handle these groups, we need to refactor the implementation logic of `useFetchSessions`. Here are the key changes:
1. Use the `sessionService.getSessionsWithGroup` method to call the backend API and retrieve the grouped session data.
2. Save the retrieved data into three different state fields: `pinnedSessions`, `customSessionGroups`, and `defaultSessions`.
#### `useFetchSessions` Method
This method is defined in `createSessionSlice` as follows:
```typescript
export const createSessionSlice: StateCreator<
SessionStore,
[['zustand/devtools', never]],
[],
SessionAction
> = (set, get) => ({
// ... other methods
useFetchSessions: () =>
useSWR<ChatSessionList>(FETCH_SESSIONS_KEY, sessionService.getSessionsWithGroup, {
onSuccess: (data) => {
set(
{
customSessionGroups: data.customGroup,
defaultSessions: data.default,
isSessionsFirstFetchFinished: true,
pinnedSessions: data.pinned,
sessions: data.all,
},
false,
n('useFetchSessions/onSuccess', data),
);
},
}),
});
```
After successfully retrieving the data, we use the `set` method to update the `customSessionGroups`, `defaultSessions`, `pinnedSessions`, and `sessions` states. This ensures that the states are synchronized with the latest session data.
#### `sessionService.getSessionsWithGroup` Method
The `sessionService.getSessionsWithGroup` method is responsible for calling the backend API `SessionModel.queryWithGroups()`.
```typescript
class SessionService {
// ... other SessionGroup related implementations
async getSessionsWithGroup(): Promise<ChatSessionList> {
return SessionModel.queryWithGroups();
}
}
```
#### `SessionModel.queryWithGroups` Method
This method is the core method called by `sessionService.getSessionsWithGroup`, and it is responsible for querying and organizing session data. The code is as follows:
```typescript
class _SessionModel extends BaseModel {
// ... other methods
/**
* Query session data and categorize sessions based on groups.
* @returns {Promise<ChatSessionList>} An object containing all sessions and categorized session lists.
*/
async queryWithGroups(): Promise<ChatSessionList> {
// Query session group data
const groups = await SessionGroupModel.query();
// Query custom session groups based on session group IDs
const customGroups = await this.queryByGroupIds(groups.map((item) => item.id));
// Query default session list
const defaultItems = await this.querySessionsByGroupId(SessionDefaultGroup.Default);
// Query pinned sessions
const pinnedItems = await this.getPinnedSessions();
// Query all sessions
const all = await this.query();
// Combine and return all sessions and their group information
return {
all, // Array containing all sessions
customGroup: groups.map((group) => ({ ...group, children: customGroups[group.id] })), // Custom groups
default: defaultItems, // Default session list
pinned: pinnedItems, // Pinned session list
};
}
}
```
The `queryWithGroups` method first queries all session groups, then based on the IDs of these groups, it queries custom session groups, as well as default and pinned sessions. Finally, it returns an object containing all sessions and categorized session lists.
### Adjusting sessions selectors
Due to changes in the logic of grouping within sessions, we need to adjust the logic of the `sessions` selectors to ensure they can correctly handle the new data structure.
Original selectors:
```ts
// Default group
const defaultSessions = (s: SessionStore): LobeSessions => s.sessions;
// Pinned group
const pinnedSessionList = (s: SessionStore) =>
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Pinned);
// Unpinned group
const unpinnedSessionList = (s: SessionStore) =>
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Default);
```
Revised:
```ts
const defaultSessions = (s: SessionStore): LobeSessions => s.defaultSessions;
const pinnedSessions = (s: SessionStore): LobeSessions => s.pinnedSessions;
const customSessionGroups = (s: SessionStore): CustomSessionGroup[] => s.customSessionGroups;
```
Since all data retrieval in the UI is implemented using syntax like `useSessionStore(sessionSelectors.defaultSessions)`, we only need to modify the selector implementation of `defaultSessions` to complete the data structure change. The data retrieval code in the UI layer does not need to be changed at all, which can greatly reduce the cost and risk of refactoring.
> !\[Important]
>
> If you are not familiar with the concept and functionality of selectors, you can refer to the section [📘 Data Storage and Retrieval Module](./State-Management-Selectors.en-US) for relevant information.
## IV. UI Section
Bind Store Action in the UI component to implement interactive logic, for example `CreateGroupModal`:
```tsx
const CreateGroupModal = () => {
// ... Other logic
const [updateSessionGroup, addCustomGroup] = useSessionStore((s) => [
s.updateSessionGroupId,
s.addSessionGroup,
]);
return (
<Modal
onOk={async () => {
// ... Other logic
const groupId = await addCustomGroup(name);
await updateSessionGroup(sessionId, groupId);
}}
>
{/* ... */}
</Modal>
);
};
```
## 5. Data Migration
In the process of software development, data migration is an inevitable issue, especially when the existing data structure cannot meet the new business requirements. For this iteration of SessionGroup, we need to handle the migration of the `group` field in the `session`, which is a typical data migration case.
### Issues with the Old Data Structure
In the old data structure, the `group` field was used to mark whether the session was "pinned" or belonged to a "default" group. However, when support for multiple session groups is needed, the original data structure becomes inflexible.
For example:
```
before pin: group = abc
after pin: group = pinned
after unpin: group = default
```
From the above example, it can be seen that once a session is unpinned from the "pinned" state, the `group` field cannot be restored to its original `abc` value. This is because we do not have a separate field to maintain the pinned state. Therefore, we have introduced a new field `pinned` to indicate whether the session is pinned, while the `group` field will be used solely to identify the session group.
### Migration Strategy
The core logic of this migration is as follows:
- When the user's `group` field is `pinned`, set their `pinned` field to `true`, and set the group to `default`.
However, data migration in LobeChat typically involves two parts: **configuration file migration** and **database migration**. Therefore, the above logic will need to be implemented separately in these two areas.
#### Configuration File Migration
For configuration file migration, we recommend performing it before database migration, as configuration file migration is usually easier to test and validate. LobeChat's file migration configuration is located in the `src/migrations/index.ts` file, which defines the various versions of configuration file migration and their corresponding migration scripts.
```diff
// Current latest version number
- export const CURRENT_CONFIG_VERSION = 2;
+ export const CURRENT_CONFIG_VERSION = 3;
// Historical version upgrade module
const ConfigMigrations = [
+ /**
+ * 2024.01.22
+ * from `group = pinned` to `pinned:true`
+ */
+ MigrationV2ToV3,
/**
* 2023.11.27
* Migrate from single key database to dexie-based relational structure
*/
MigrationV1ToV2,
/**
* 2023.07.11
* just the first version, Nothing to do
*/
MigrationV0ToV1,
];
```
The logic for this configuration file migration is defined in `src/migrations/FromV2ToV3/index.ts`, simplified as follows:
```ts
export class MigrationV2ToV3 implements Migration {
// Specify the version from which to upgrade
version = 2;
migrate(data: MigrationData<V2ConfigState>): MigrationData<V3ConfigState> {
const { sessions } = data.state;
return {
...data,
state: {
...data.state,
sessions: sessions.map((s) => this.migrateSession(s)),
},
};
}
migrateSession = (session: V2Session): V3Session => {
return {
...session,
group: 'default',
pinned: session.group === 'pinned',
};
};
}
```
It can be seen that the migration implementation is very simple. However, it is important to ensure the correctness of the migration, so corresponding test cases need to be written in `src/migrations/FromV2ToV3/migrations.test.ts`:
```ts
import { MigrationData, VersionController } from '@/migrations/VersionController';
import { MigrationV1ToV2 } from '../FromV1ToV2';
import inputV1Data from '../FromV1ToV2/fixtures/input-v1-session.json';
import inputV2Data from './fixtures/input-v2-session.json';
import outputV3DataFromV1 from './fixtures/output-v3-from-v1.json';
import outputV3Data from './fixtures/output-v3.json';
import { MigrationV2ToV3 } from './index';
describe('MigrationV2ToV3', () => {
let migrations;
let versionController: VersionController<any>;
beforeEach(() => {
migrations = [MigrationV2ToV3];
versionController = new VersionController(migrations, 3);
});
it('should migrate data correctly through multiple versions', () => {
const data: MigrationData = inputV2Data;
const migratedData = versionController.migrate(data);
expect(migratedData.version).toEqual(outputV3Data.version);
expect(migratedData.state.sessions).toEqual(outputV3Data.state.sessions);
expect(migratedData.state.topics).toEqual(outputV3Data.state.topics);
expect(migratedData.state.messages).toEqual(outputV3Data.state.messages);
});
it('should work correct from v1 to v3', () => {
const data: MigrationData = inputV1Data;
versionController = new VersionController([MigrationV2ToV3, MigrationV1ToV2], 3);
const migratedData = versionController.migrate(data);
expect(migratedData.version).toEqual(outputV3DataFromV1.version);
expect(migratedData.state.sessions).toEqual(outputV3DataFromV1.state.sessions);
expect(migratedData.state.topics).toEqual(outputV3DataFromV1.state.topics);
expect(migratedData.state.messages).toEqual(outputV3DataFromV1.state.messages);
});
});
```
```markdown
```
Unit tests require the use of `fixtures` to fix the test data. The test cases include verification logic for two parts: 1) the correctness of a single migration (v2 -> v3) and 2) the correctness of a complete migration (v1 -> v3).
> \[!Important]
>
> The version number in the configuration file may not match the database version number, as database version updates do not always involve changes to the data structure (such as adding tables or fields), while configuration file version updates usually involve data migration.
````
#### Database Migration
Database migration needs to be implemented in the `LocalDB` class, which is defined in the `src/database/core/db.ts` file. The migration process involves adding a new `pinned` field for each record in the `sessions` table and resetting the `group` field:
```diff
export class LocalDB extends Dexie {
public files: LobeDBTable<'files'>;
public sessions: LobeDBTable<'sessions'>;
public messages: LobeDBTable<'messages'>;
public topics: LobeDBTable<'topics'>;
public plugins: LobeDBTable<'plugins'>;
public sessionGroups: LobeDBTable<'sessionGroups'>;
constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
this.version(1).stores(dbSchemaV1);
this.version(2).stores(dbSchemaV2);
this.version(3).stores(dbSchemaV3);
this.version(4)
.stores(dbSchemaV4)
+ .upgrade((trans) => this.upgradeToV4(trans));
this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
this.sessionGroups = this.table('sessionGroups');
}
+ /**
+ * 2024.01.22
+ *
+ * DB V3 to V4
+ * from `group = pinned` to `pinned:true`
+ */
+ upgradeToV4 = async (trans: Transaction) => {
+ const sessions = trans.table('sessions');
+ await sessions.toCollection().modify((session) => {
+ // translate boolean to number
+ session.pinned = session.group === 'pinned' ? 1 : 0;
session.group = 'default';
});
+ };
}
````
This is our data migration strategy. When performing the migration, it is essential to ensure the correctness of the migration script and validate the migration results through thorough testing.
## VI. Data Import and Export
In LobeChat, the data import and export feature is designed to ensure that users can migrate their data between different devices. This includes session, topic, message, and settings data. In the implementation of the Session Group feature, we also need to handle data import and export to ensure that the complete exported data can be restored exactly the same on other devices.
The core implementation of data import and export is in the `ConfigService` in `src/service/config.ts`, with key methods as follows:
| Method Name | Description |
| --------------------- | -------------------------- |
| `importConfigState` | Import configuration data |
| `exportAgents` | Export all agent data |
| `exportSessions` | Export all session data |
| `exportSingleSession` | Export single session data |
| `exportSingleAgent` | Export single agent data |
| `exportSettings` | Export settings data |
| `exportAll` | Export all data |
### Data Export
In LobeChat, when a user chooses to export data, the current session, topic, message, and settings data are packaged into a JSON file and provided for download. The standard structure of this JSON file is as follows:
```json
{
"exportType": "sessions",
"state": {
"sessions": [],
"topics": [],
"messages": []
},
"version": 3
}
```
Where:
- `exportType`: Identifies the type of data being exported, currently including `sessions`, `agent`, `settings`, and `all`.
- `state`: Stores the actual data, with different data types for different `exportType`.
- `version`: Indicates the data version.
In the implementation of the Session Group feature, we need to add `sessionGroups` data to the `state` field. This way, when users export data, their Session Group data will also be included.
For example, when exporting sessions, the relevant implementation code modification is as follows:
```diff
class ConfigService {
// ... Other code omitted
exportSessions = async () => {
const sessions = await sessionService.getSessions();
+ const sessionGroups = await sessionService.getSessionGroups();
const messages = await messageService.getAllMessages();
const topics = await topicService.getAllTopics();
- const config = createConfigFile('sessions', { messages, sessions, topics });
+ const config = createConfigFile('sessions', { messages, sessionGroups, sessions, topics });
exportConfigFile(config, 'sessions');
};
}
```
### Data Import
The data import functionality is implemented through `ConfigService.importConfigState`. When users choose to import data, they need to provide a JSON file that conforms to the above structure specification. The `importConfigState` method accepts the data of the configuration file and imports it into the application.
In the implementation of the Session Group feature, we need to handle the `sessionGroups` data during the data import process. This way, when users import data, their Session Group data will also be imported correctly.
The following is the modified code for the import implementation in `importConfigState`:
```diff
class ConfigService {
// ... Other code omitted
+ importSessionGroups = async (sessionGroups: SessionGroupItem[]) => {
+ return sessionService.batchCreateSessionGroups(sessionGroups);
+ };
importConfigState = async (config: ConfigFile): Promise<ImportResults | undefined> => {
switch (config.exportType) {
case 'settings': {
await this.importSettings(config.state.settings);
break;
}
case 'agents': {
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const data = await this.importSessions(config.state.sessions);
return {
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(data),
};
}
case 'all': {
await this.importSettings(config.state.settings);
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const [sessions, messages, topics] = await Promise.all([
this.importSessions(config.state.sessions),
this.importMessages(config.state.messages),
this.importTopics(config.state.topics),
]);
return {
messages: this.mapImportResult(messages),
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(sessions),
topics: this.mapImportResult(topics),
};
}
case 'sessions': {
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const [sessions, messages, topics] = await Promise.all([
this.importSessions(config.state.sessions),
this.importMessages(config.state.messages),
this.importTopics(config.state.topics),
]);
return {
messages: this.mapImportResult(messages),
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(sessions),
topics: this.mapImportResult(topics),
};
}
}
};
}
```
One key point of the above modification is to import sessionGroup first, because if sessions are imported first and the corresponding SessionGroup Id is not found in the current database, the group of this session will default to be modified to the default value. This will prevent the correct association of the sessionGroup's ID with the session.
This is the implementation of the LobeChat Session Group feature in the data import and export process. This approach ensures that users' Session Group data is correctly handled during the import and export process.
## Summary
The above is the complete implementation process of the LobeChat Session Group feature. Developers can refer to this document for the development and testing of related functionalities.

View File

@ -0,0 +1,707 @@
# LobeChat 功能开发完全指南
本文档旨在指导开发者了解如何在 LobeChat 中开发一块完整的功能需求。
我们将以 sessionGroup 的实现为示例:[✨ feat: add session group manager](https://github.com/lobehub/lobe-chat/pull/1055) 通过以下六个主要部分来阐述完整的实现流程:
1. 数据模型 / 数据库定义
2. Service 实现 / Model 实现
3. 前端数据流 Store 实现
4. UI 实现与 action 绑定
5. 数据迁移
6. 数据导入导出
## 一、数据库部分
为了实现 Session Group 功能,首先需要在数据库层面定义相关的数据模型和索引。
定义一个新的 sessionGroup 表,分 3 步:
### 1. 建立数据模型 schema
`src/database/schema/sessionGroup.ts` 中定义 `DB_SessionGroup` 的数据模型:
```typescript
import { z } from 'zod';
export const DB_SessionGroupSchema = z.object({
name: z.string(),
sort: z.number().optional(),
});
export type DB_SessionGroup = z.infer<typeof DB_SessionGroupSchema>;
```
### 2. 创建数据库索引
由于要新增一个表,所以需要在在数据库 Schema 中,为 `sessionGroup` 表添加索引。
`src/database/core/schema.ts` 中添加 `dbSchemaV4`:
```diff
// ... 前面的一些实现
// ************************************** //
// ******* Version 3 - 2023-12-06 ******* //
// ************************************** //
// - Added `plugin` table
export const dbSchemaV3 = {
...dbSchemaV2,
plugins:
'&identifier, type, manifest.type, manifest.meta.title, manifest.meta.description, manifest.meta.author, createdAt, updatedAt',
};
+ // ************************************** //
+ // ******* Version 4 - 2024-01-21 ******* //
+ // ************************************** //
+ // - Added `sessionGroup` table
+ export const dbSchemaV4 = {
+ ...dbSchemaV3,
+ sessionGroups: '&id, name, sort, createdAt, updatedAt',
+ sessions: '&id, type, group, pinned, meta.title, meta.description, meta.tags, createdAt, updatedAt',
};
```
> \[!Note]
>
> 除了 `sessionGroups` 外,此处也修改了 `sessions` 的定义,原因是存在数据迁移的情况。但由于本节只关注 schema 定义,不展开数据迁移部分实现,详情可见第五节。
> \[!Important]
>
> 如果你不了解为何此处需要创建索引,以及不了解此处的 schema 的定义语法。你可能需要提前了解下 Dexie.js 相关的基础知识,可以查阅 [📘 本地数据库](./Local-Database.zh-CN) 部分了解相关内容。
### 3. 在本地 DB 中加入 sessionGroups 表
扩展本地数据库类以包含新的 `sessionGroups` 表:
```diff
import { dbSchemaV1, dbSchemaV2, dbSchemaV3, dbSchemaV4 } from './schemas';
interface LobeDBSchemaMap {
files: DB_File;
messages: DB_Message;
plugins: DB_Plugin;
+ sessionGroups: DB_SessionGroup;
sessions: DB_Session;
topics: DB_Topic;
}
// Define a local DB
export class LocalDB extends Dexie {
public files: LobeDBTable<'files'>;
public sessions: LobeDBTable<'sessions'>;
public messages: LobeDBTable<'messages'>;
public topics: LobeDBTable<'topics'>;
public plugins: LobeDBTable<'plugins'>;
+ public sessionGroups: LobeDBTable<'sessionGroups'>;
constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
this.version(1).stores(dbSchemaV1);
this.version(2).stores(dbSchemaV2);
this.version(3).stores(dbSchemaV3);
+ this.version(4).stores(dbSchemaV4);
this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
+ this.sessionGroups = this.table('sessionGroups');
}
}
```
如此一来,你就可以通过在 `Application` -> `Storage` -> `IndexedDB` 中查看到 `LOBE_CHAT_DB` 里的 `sessionGroups` 表了。
![](https://github.com/lobehub/lobe-chat/assets/28616219/aea50f66-4060-4a32-88c8-b3c672d05be8)
## 二、Model 与 Service 部分
### 定义 Model
在构建 LobeChat 应用时Model 负责与数据库的交互,它定义了如何读取、插入、更新和删除数据库的数据,定义具体的业务逻辑。
`src/database/model/sessionGroup.ts` 中定义 `SessionGroupModel`
```typescript
import { BaseModel } from '@/database/core';
import { DB_SessionGroup, DB_SessionGroupSchema } from '@/database/schemas/sessionGroup';
import { nanoid } from '@/utils/uuid';
class _SessionGroupModel extends BaseModel {
constructor() {
super('sessions', DB_SessionGroupSchema);
}
async create(name: string, sort?: number, id = nanoid()) {
return this._add({ name, sort }, id);
}
// ... 其他 CRUD 方法的实现
}
export const SessionGroupModel = new _SessionGroupModel();
```
### Service 实现
在 LobeChat 中Service 层主要负责与后端服务进行通信,封装业务逻辑,并提供数据给前端的其他层使用。`SessionService` 是一个专门处理与会话Session相关业务逻辑的服务类它封装了创建会话、查询会话、更新会话等操作。
为了保持代码的可维护性和可扩展性,我们将会话分组相关的服务逻辑放在 `SessionService` 中,这样可以使会话领域的业务逻辑保持内聚。当业务需求增加或变化时,我们可以更容易地在这个领域内进行修改和扩展。
`SessionService` 通过调用 `SessionGroupModel` 的方法来实现对会话分组的管理。 在 `sessionService` 中实现 Session Group 相关的请求逻辑:
```typescript
class SessionService {
// ... 省略 session 业务逻辑
// ************************************** //
// *********** SessionGroup *********** //
// ************************************** //
async createSessionGroup(name: string, sort?: number) {
const item = await SessionGroupModel.create(name, sort);
if (!item) {
throw new Error('session group create Error');
}
return item.id;
}
// ... 其他 SessionGroup 相关的实现
}
```
## 三、Store Action 部分
在 LobeChat 应用中Store 是用于管理应用前端状态的模块。其中的 Action 是触发状态更新的函数,通常会调用服务层的方法来执行实际的数据处理操作,然后更新 Store 中的状态。我们采用了 `zustand` 作为 Store 模块的底层依赖,对于状态管理的详细实践介绍,可以查阅 [📘 状态管理最佳实践](../State-Management/State-Management-Intro.zh-CN.md)
### sessionGroup CRUD
会话组的 CRUD 操作是管理会话组数据的核心行为。在 `src/store/session/slice/sessionGroup` 中,我们将实现与会话组相关的状态逻辑,包括添加、删除、更新会话组及其排序。
以下是 `action.ts` 文件中需要实现的 `SessionGroupAction` 接口方法:
```ts
export interface SessionGroupAction {
// 增加会话组
addSessionGroup: (name: string) => Promise<string>;
// 删除会话组
removeSessionGroup: (id: string) => Promise<void>;
// 更新会话的会话组 ID
updateSessionGroupId: (sessionId: string, groupId: string) => Promise<void>;
// 更新会话组名称
updateSessionGroupName: (id: string, name: string) => Promise<void>;
// 更新会话组排序
updateSessionGroupSort: (items: SessionGroupItem[]) => Promise<void>;
}
```
`addSessionGroup` 方法为例,我们首先调用 `sessionService``createSessionGroup` 方法来创建新的会话组,然后使用 `refreshSessions` 方法来刷新 sessions 状态:
```ts
export const createSessionGroupSlice: StateCreator<
SessionStore,
[['zustand/devtools', never]],
[],
SessionGroupAction
> = (set, get) => ({
// 实现添加会话组的逻辑
addSessionGroup: async (name) => {
// 调用服务层的 createSessionGroup 方法并传入会话组名称
const id = await sessionService.createSessionGroup(name);
// 调用 get 方法获取当前的 Store 状态并执行 refreshSessions 方法刷新会话数据
await get().refreshSessions();
// 返回新创建的会话组 ID
return id;
},
// ... 其他 action 实现
});
```
通过以上的实现,我们可以确保在添加新的会话组后,应用的状态会及时更新,且相关的组件会收到最新的状态并重新渲染。这种方式提高了数据流的可预测性和可维护性,同时也简化了组件之间的通信。
### Sessions 分组逻辑改造
本次需求改造需要对 Sessions 进行升级,从原来的单一列表变成了三个不同的分组:`pinnedSessions`(置顶列表)、`customSessionGroups`(自定义分组)和 `defaultSessions`(默认列表)。
为了处理这些分组,我们需要改造 `useFetchSessions` 的实现逻辑。以下是关键的改动点:
1. 使用 `sessionService.getSessionsWithGroup` 方法负责调用后端接口来获取分组后的会话数据;
2. 将获取后的数据保存为三到不同的状态字段中:`pinnedSessions``customSessionGroups``defaultSessions`
#### `useFetchSessions` 方法
该方法在 `createSessionSlice` 中定义,如下所示:
```typescript
export const createSessionSlice: StateCreator<
SessionStore,
[['zustand/devtools', never]],
[],
SessionAction
> = (set, get) => ({
// ... 其他方法
useFetchSessions: () =>
useSWR<ChatSessionList>(FETCH_SESSIONS_KEY, sessionService.getSessionsWithGroup, {
onSuccess: (data) => {
set(
{
customSessionGroups: data.customGroup,
defaultSessions: data.default,
isSessionsFirstFetchFinished: true,
pinnedSessions: data.pinned,
sessions: data.all,
},
false,
n('useFetchSessions/onSuccess', data),
);
},
}),
});
```
在成功获取数据后,我们使用 `set` 方法来更新 `customSessionGroups``defaultSessions``pinnedSessions``sessions` 状态。这将保证状态与最新的会话数据同步。
#### getSessionsWithGroup
使用 `sessionService.getSessionsWithGroup` 方法负责调用后端接口 `SessionModel.queryWithGroups()`
```typescript
class SessionService {
// ... 其他 SessionGroup 相关的实现
async getSessionsWithGroup(): Promise<ChatSessionList> {
return SessionModel.queryWithGroups();
}
}
```
#### `SessionModel.queryWithGroups` 方法
此方法是 `sessionService.getSessionsWithGroup` 调用的核心方法,它负责查询和组织会话数据,代码如下:
```typescript
class _SessionModel extends BaseModel {
// ... 其他方法
/**
* 查询会话数据,并根据会话组将会话分类。
* @returns {Promise<ChatSessionList>} 返回一个对象,其中包含所有会话以及分为不同组的会话列表。
*/
async queryWithGroups(): Promise<ChatSessionList> {
// 查询会话组数据
const groups = await SessionGroupModel.query();
// 根据会话组ID查询自定义会话组
const customGroups = await this.queryByGroupIds(groups.map((item) => item.id));
// 查询默认会话列表
const defaultItems = await this.querySessionsByGroupId(SessionDefaultGroup.Default);
// 查询置顶的会话
const pinnedItems = await this.getPinnedSessions();
// 查询所有会话
const all = await this.query();
// 组合并返回所有会话及其分组信息
return {
all, // 包含所有会话的数组
customGroup: groups.map((group) => ({ ...group, children: customGroups[group.id] })), // 自定义分组
default: defaultItems, // 默认会话列表
pinned: pinnedItems, // 置顶会话列表
};
}
}
```
方法 `queryWithGroups` 首先查询所有会话组,然后基于这些组的 ID 查询自定义会话组,同时查询默认和固定的会话。最后,它返回一个包含所有会话和按组分类的会话列表对象。
### sessions selectors 调整
由于 sessions 中关于分组的逻辑发生了变化,因此我们需要调整 `sessions` 的 selectors 逻辑,以确保它们能够正确地处理新的数据结构。
原有的 selectors:
```ts
// 默认分组
const defaultSessions = (s: SessionStore): LobeSessions => s.sessions;
// 置顶分组
const pinnedSessionList = (s: SessionStore) =>
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Pinned);
// 未置顶分组
const unpinnedSessionList = (s: SessionStore) =>
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Default);
```
修改后:
```ts
const defaultSessions = (s: SessionStore): LobeSessions => s.defaultSessions;
const pinnedSessions = (s: SessionStore): LobeSessions => s.pinnedSessions;
const customSessionGroups = (s: SessionStore): CustomSessionGroup[] => s.customSessionGroups;
```
由于在 UI 中的取数全部是通过 `useSessionStore(sessionSelectors.defaultSessions)` 这样的写法实现的,因此我们只需要修改 `defaultSessions` 的选择器实现,即可完成数据结构的变更。 UI 层的取数代码完全不用变更,可以大大降低重构的成本和风险。
> !\[Important]
>
> 如果你对 Selectors 的概念和功能不太了解,可以查阅 [📘 数据存储取数模块](../State-Management/State-Management-Selectors.zh-CN.md) 部分了解相关内容。
## 四、UI 部分
在 UI 组件中绑定 Store Action 实现交互逻辑,例如 `CreateGroupModal`
```tsx
const CreateGroupModal = () => {
// ... 其他逻辑
const [updateSessionGroup, addCustomGroup] = useSessionStore((s) => [
s.updateSessionGroupId,
s.addSessionGroup,
]);
return (
<Modal
onOk={async () => {
// ... 其他逻辑
const groupId = await addCustomGroup(name);
await updateSessionGroup(sessionId, groupId);
}}
>
{/* ... */}
</Modal>
);
};
```
## 五、数据迁移
在软件开发过程中,数据迁移是一个不可避免的问题,尤其是当现有的数据结构无法满足新的业务需求时。对于本次 SessionGroup 的迭代,我们需要处理 `session``group` 字段的迁移,这是一个典型的数据迁移案例。
### 旧数据结构的问题
在旧的数据结构中,`group` 字段被用来标记会话是否为 `pinned`(置顶)或属于某个 `default`(默认)分组。但是当需要支持多个会话分组时,原有的数据结构就显得不够灵活了。
例如:
```
before pin: group = abc
after pin: group = pinned
after unpin: group = default
```
从上述示例中可以看出,一旦会话从置顶状态(`pinned`)取消置顶(`unpin``group` 字段将无法恢复为原来的 `abc` 值。这是因为我们没有一个独立的字段来维护置顶状态。因此,我们引入了一个新的字段 `pinned` 来表示会话是否被置顶,而 `group` 字段将仅用于标识会话分组。
### 迁移策略
本次迁移的核心逻辑只有一条:
- 当用户的 `group` 字段为 `pinned` 时,将其 `pinned` 字段置为 `true`,同时将 group 设为 `default`;
但 LobeChat 中的数据迁移通常涉及到 **配置文件迁移****数据库迁移** 两个部分。所以上述逻辑会需要分别在两块实现迁移。
#### 配置文件迁移
对于配置文件迁移我们建议先于数据库迁移进行因为配置文件迁移通常更容易进行测试和验证。LobeChat 的文件迁移配置位于 `src/migrations/index.ts` 文件中,其中定义了配置文件迁移的各个版本及对应的迁移脚本。
```diff
// 当前最新的版本号
- export const CURRENT_CONFIG_VERSION = 2;
+ export const CURRENT_CONFIG_VERSION = 3;
// 历史记录版本升级模块
const ConfigMigrations = [
+ /**
+ * 2024.01.22
+ * from `group = pinned` to `pinned:true`
+ */
+ MigrationV2ToV3,
/**
* 2023.11.27
* 从单 key 数据库转换为基于 dexie 的关系型结构
*/
MigrationV1ToV2,
/**
* 2023.07.11
* just the first version, Nothing to do
*/
MigrationV0ToV1,
];
```
本次的配置文件迁移逻辑定义在 `src/migrations/FromV2ToV3/index.ts` 中,简化如下:
```ts
export class MigrationV2ToV3 implements Migration {
// 指定从该版本开始向上升级
version = 2;
migrate(data: MigrationData<V2ConfigState>): MigrationData<V3ConfigState> {
const { sessions } = data.state;
return {
...data,
state: {
...data.state,
sessions: sessions.map((s) => this.migrateSession(s)),
},
};
}
migrateSession = (session: V2Session): V3Session => {
return {
...session,
group: 'default',
pinned: session.group === 'pinned',
};
};
}
```
可以看到迁移的实现非常简单。但重要的是,我们需要保证迁移的正确性,因此需要编写对应的测试用例 `src/migrations/FromV2ToV3/migrations.test.ts`
```ts
import { MigrationData, VersionController } from '@/migrations/VersionController';
import { MigrationV1ToV2 } from '../FromV1ToV2';
import inputV1Data from '../FromV1ToV2/fixtures/input-v1-session.json';
import inputV2Data from './fixtures/input-v2-session.json';
import outputV3DataFromV1 from './fixtures/output-v3-from-v1.json';
import outputV3Data from './fixtures/output-v3.json';
import { MigrationV2ToV3 } from './index';
describe('MigrationV2ToV3', () => {
let migrations;
let versionController: VersionController<any>;
beforeEach(() => {
migrations = [MigrationV2ToV3];
versionController = new VersionController(migrations, 3);
});
it('should migrate data correctly through multiple versions', () => {
const data: MigrationData = inputV2Data;
const migratedData = versionController.migrate(data);
expect(migratedData.version).toEqual(outputV3Data.version);
expect(migratedData.state.sessions).toEqual(outputV3Data.state.sessions);
expect(migratedData.state.topics).toEqual(outputV3Data.state.topics);
expect(migratedData.state.messages).toEqual(outputV3Data.state.messages);
});
it('should work correct from v1 to v3', () => {
const data: MigrationData = inputV1Data;
versionController = new VersionController([MigrationV2ToV3, MigrationV1ToV2], 3);
const migratedData = versionController.migrate(data);
expect(migratedData.version).toEqual(outputV3DataFromV1.version);
expect(migratedData.state.sessions).toEqual(outputV3DataFromV1.state.sessions);
expect(migratedData.state.topics).toEqual(outputV3DataFromV1.state.topics);
expect(migratedData.state.messages).toEqual(outputV3DataFromV1.state.messages);
});
});
```
单测需要使用 `fixtures` 来固定测试数据,测试用例包含了两个部分的验证逻辑: 1 单次迁移v2 -> v3和 2 完整迁移v1 -> v3的正确性。
> \[!Important]
>
> 配置文件的版本号可能与数据库版本号不一致,因为数据库版本的更新不总是伴随数据结构的变化(如新增表或字段),而配置文件的版本更新则通常涉及到数据迁移。
#### 数据库迁移
数据库迁移则需要在 `LocalDB` 类中实施,该类定义在 `src/database/core/db.ts` 文件中。迁移过程涉及到为 `sessions` 表的每条记录添加新的 `pinned` 字段,并重置 `group` 字段:
```diff
export class LocalDB extends Dexie {
public files: LobeDBTable<'files'>;
public sessions: LobeDBTable<'sessions'>;
public messages: LobeDBTable<'messages'>;
public topics: LobeDBTable<'topics'>;
public plugins: LobeDBTable<'plugins'>;
public sessionGroups: LobeDBTable<'sessionGroups'>;
constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
this.version(1).stores(dbSchemaV1);
this.version(2).stores(dbSchemaV2);
this.version(3).stores(dbSchemaV3);
this.version(4)
.stores(dbSchemaV4)
+ .upgrade((trans) => this.upgradeToV4(trans));
this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
this.sessionGroups = this.table('sessionGroups');
}
+ /**
+ * 2024.01.22
+ *
+ * DB V3 to V4
+ * from `group = pinned` to `pinned:true`
+ */
+ upgradeToV4 = async (trans: Transaction) => {
+ const sessions = trans.table('sessions');
+ await sessions.toCollection().modify((session) => {
+ // translate boolean to number
+ session.pinned = session.group === 'pinned' ? 1 : 0;
+ session.group = 'default';
+ });
+ };
}
```
以上就是我们的数据迁移策略。在进行迁移时,务必确保迁移脚本的正确性,并通过充分的测试验证迁移结果。
## 六、数据导入导出
在 LobeChat 中,数据导入导出功能是为了确保用户可以在不同设备之间迁移他们的数据。这包括会话、话题、消息和设置等数据。在本次的 Session Group 功能实现中,我们也需要对数据导入导出进行处理,以确保当完整导出的数据在其他设备上可以一模一样恢复。
数据导入导出的核心实现在 `src/service/config.ts``ConfigService` 中,其中的关键方法如下:
| 方法名称 | 描述 |
| --------------------- | ---------------- |
| `importConfigState` | 导入配置数据 |
| `exportAgents` | 导出所有助理数据 |
| `exportSessions` | 导出所有会话数据 |
| `exportSingleSession` | 导出单个会话数据 |
| `exportSingleAgent` | 导出单个助理数据 |
| `exportSettings` | 导出设置数据 |
| `exportAll` | 导出所有数据 |
### 数据导出
在 LobeChat 中,当用户选择导出数据时,会将当前的会话、话题、消息和设置等数据打包成一个 JSON 文件并提供给用户下载。这个 JSON 文件的标准结构如下:
```json
{
"exportType": "sessions",
"state": {
"sessions": [],
"topics": [],
"messages": []
},
"version": 3
}
```
其中:
- `exportType` 标识导出数据的类型,目前有 `sessions``agent``settings``all` 四种;
- `state` 存储实际的数据,不同 `exportType` 的数据类型也不同;
- `version` 标识数据的版本。
在 Session Group 功能实现中,我们需要在 `state` 字段中添加 `sessionGroups` 数据。这样,当用户导出数据时,他们的 Session Group 数据也会被包含在内。
以导出 sessions 为例,导出数据的相关实现代码修改如下:
```diff
class ConfigService {
// ... 省略其他
exportSessions = async () => {
const sessions = await sessionService.getSessions();
+ const sessionGroups = await sessionService.getSessionGroups();
const messages = await messageService.getAllMessages();
const topics = await topicService.getAllTopics();
- const config = createConfigFile('sessions', { messages, sessions, topics });
+ const config = createConfigFile('sessions', { messages, sessionGroups, sessions, topics });
exportConfigFile(config, 'sessions');
};
}
```
### 数据导入
数据导入的功能是通过 `ConfigService.importConfigState` 来实现的。当用户选择导入数据时,他们需要提供一个由 符合上述结构规范的 JSON 文件。`importConfigState` 方法接受配置文件的数据,并将其导入到应用中。
在 Session Group 功能实现中,我们需要在导入数据的过程中处理 `sessionGroups` 数据。这样,当用户导入数据时,他们的 Session Group 数据也会被正确地导入。
以下是 `importConfigState` 中导入实现的变更代码:
```diff
class ConfigService {
// ... 省略其他代码
+ importSessionGroups = async (sessionGroups: SessionGroupItem[]) => {
+ return sessionService.batchCreateSessionGroups(sessionGroups);
+ };
importConfigState = async (config: ConfigFile): Promise<ImportResults | undefined> => {
switch (config.exportType) {
case 'settings': {
await this.importSettings(config.state.settings);
break;
}
case 'agents': {
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const data = await this.importSessions(config.state.sessions);
return {
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(data),
};
}
case 'all': {
await this.importSettings(config.state.settings);
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const [sessions, messages, topics] = await Promise.all([
this.importSessions(config.state.sessions),
this.importMessages(config.state.messages),
this.importTopics(config.state.topics),
]);
return {
messages: this.mapImportResult(messages),
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(sessions),
topics: this.mapImportResult(topics),
};
}
case 'sessions': {
+ const sessionGroups = await this.importSessionGroups(config.state.sessionGroups);
const [sessions, messages, topics] = await Promise.all([
this.importSessions(config.state.sessions),
this.importMessages(config.state.messages),
this.importTopics(config.state.topics),
]);
return {
messages: this.mapImportResult(messages),
+ sessionGroups: this.mapImportResult(sessionGroups),
sessions: this.mapImportResult(sessions),
topics: this.mapImportResult(topics),
};
}
}
};
}
```
上述修改的一个要点是先进行 sessionGroup 的导入,因为如果先导入 session 时,如果没有在当前数据库中查到相应的 SessionGroup Id那么这个 session 的 group 会兜底修改为默认值。这样就无法正确地将 sessionGroup 的 ID 与 session 进行关联。
以上就是 LobeChat Session Group 功能在数据导入导出部分的实现。通过这种方式,我们可以确保用户的 Session Group 数据在导入导出过程中能够被正确地处理。
## 总结
以上就是 LobeChat Session Group 功能的完整实现流程。开发者可以参考本文档进行相关功能的开发和测试。

View File

@ -0,0 +1,40 @@
# Directory Structure
The directory structure of LobeChat is as follows:
```bash
src
├── app # Main logic and state management related code for the application
├── components # Reusable UI components
├── config # Application configuration files, including client-side and server-side environment variables
├── const # Used to define constants, such as action types, route names, etc.
├── features # Function modules related to business functions, such as agent settings, plugin development pop-ups, etc.
├── hooks # Custom utility hooks reused throughout the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── locales # Internationalization language files
├── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── types # TypeScript type definition files
└── utils # Common utility functions
```
## app
In the `app` folder, we organize each route page according to the app router's [Route Groups](https://nextjs.org/docs/app/building-your-application/routing/route-groups) to separately handle the implementation of desktop and mobile code. Taking the file structure of the `welcome` page as an example:
```bash
welcome
├── (desktop) # Desktop implementation
│ ├── features # Desktop-specific features
│ ├── index.tsx # Main entry file for desktop
│ └── layout.desktop.tsx # Desktop layout component
├── (mobile) # Mobile implementation
│ ├── features # Mobile-specific features
│ ├── index.tsx # Main entry file for mobile
│ └── layout.mobile.tsx # Mobile layout component
├── features # This folder contains features code shared by both desktop and mobile, such as the Banner component
│ └── Banner
└── page.tsx # This is the main entry file for the page, used to load desktop or mobile code based on the device type
```
In this way, we can clearly distinguish and manage desktop and mobile code, while also easily reusing code required on both devices, thereby improving development efficiency and maintaining code cleanliness and maintainability.

View File

@ -0,0 +1,40 @@
# 目录架构
LobeChat 的文件夹目录架构如下:
```bash
src
├── app # 应用主要逻辑和状态管理相关的代码
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── const # 用于定义常量,如 action 类型、路由名等
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
├── hooks # 全应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏等
├── locales # 国际化的语言文件
├── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── types # TypeScript 的类型定义文件
└── utils # 通用的工具函数
```
## app
`app` 文件夹中,我们将每个路由页面按照 app router 的 [Route Groups](https://nextjs.org/docs/app/building-your-application/routing/route-groups) 进行组织,以此来分别处理桌面端和移动端的代码实现。以 `welcome` 页面的文件结构为例:
```bash
welcome
├── (desktop) # 桌面端实现
│ ├── features # 桌面端特有的功能
│ ├── index.tsx # 桌面端的主入口文件
│ └── layout.desktop.tsx # 桌面端的布局组件
├── (mobile) # 移动端实现
│ ├── features # 移动端特有的功能
│ ├── index.tsx # 移动端的主入口文件
│ └── layout.mobile.tsx # 移动端的布局组件
├── features # 此文件夹包含双端共享的特性代码,如 Banner 组件
│ └── Banner
└── page.tsx # 此为页面的主入口文件,用于根据设备类型选择加载桌面端或移动端的代码
```
通过这种方式,我们可以清晰地区分和管理桌面端和移动端的代码,同时也能方便地复用在两种设备上都需要的代码,从而提高开发效率并保持代码的整洁和可维护性。

View File

@ -0,0 +1,43 @@
# Technical Development Getting Started Guide
Welcome to the LobeChat technical development getting started guide. LobeChat is an AI conversation application built on the Next.js framework, which integrates a series of technology stacks to achieve diverse functions and features. This guide will provide a detailed introduction to the main technical components of LobeChat and how to configure and use these technologies in your development environment.
#### TOC
- [Basic Technology Stack](#basic-technology-stack)
- [Folder Directory Structure](#folder-directory-structure)
## Basic Technology Stack
The core technology stack of LobeChat includes:
- **Framework**: We have chosen [Next.js](https://nextjs.org/), a powerful React framework that provides key features such as server-side rendering, routing framework, and Router Handler for our project.
- **Component Library**: We use [Ant Design (antd)](https://ant.design/) as the basic component library, and also introduce [lobe-ui](https://github.com/lobehub/lobe-ui) as our business component library.
- **State Management**: We have opted for [zustand](https://github.com/pmndrs/zustand), a lightweight and easy-to-use state management library.
- **Network Requests**: We use [swr](https://swr.vercel.app/), a React Hooks library for data fetching.
- **Routing**: For routing management, we directly use the solution provided by [Next.js](https://nextjs.org/) itself.
- **Internationalization**: We use [i18next](https://www.i18next.com/) to implement multi-language support for the application.
- **Styling**: We use [antd-style](https://github.com/ant-design/antd-style), a CSS-in-JS library that complements Ant Design.
- **Unit Testing**: We use [vitest](https://github.com/vitest-dev/vitest) for unit testing.
## Folder Directory Structure
The folder directory structure of LobeChat is as follows:
```bash
src
├── app # Main logic of the application and code related to state management
├── components # Reusable UI components
├── config # Application configuration files, including client-side environment variables and server-side environment variables
├── const # Used to define constants, such as action types, route names, etc.
├── features # Function modules related to business features, such as Agent settings, plugin development pop-ups, etc.
├── hooks # Custom utility hooks reused throughout the application
├── layout # Application layout components, such as navigation bars, sidebars, etc.
├── locales # Language files for internationalization
├── services # Encapsulated backend service interfaces, such as HTTP requests
├── store # Zustand store for state management
├── types # TypeScript type definition files
└── utils # Common utility functions
```
For a detailed introduction to the directory structure, please refer to: [Folder Directory Structure](Folder-Structure.en-US.md)

View File

@ -0,0 +1,108 @@
# 技术开发上手指南
欢迎来到 LobeChat 技术开发上手指南。LobeChat 是一款基于 Next.js 框架构建的 AI 会话应用,它汇集了一系列的技术栈,以实现多样化的功能和特性。本指南将详细介绍 LobeChat 的主要技术组成,以及如何在你的开发环境中配置和使用这些技术。
#### TOC
- [基础技术栈](#基础技术栈)
- [文件夹目录架构](#文件夹目录架构)
- [本地开发环境设置](#本地开发环境设置)
- [代码风格与贡献指南](#代码风格与贡献指南)
- [国际化实现指南](#国际化实现指南)
- [附录:资源与参考](#附录资源与参考)
## 基础技术栈
LobeChat 的核心技术栈如下:
- **框架**:我们选择了 [Next.js](https://nextjs.org/),这是一款强大的 React 框架为我们的项目提供了服务端渲染、路由框架、Router Handler 等关键功能。
- **组件库**:我们使用了 [Ant Design (antd)](https://ant.design/) 作为基础组件库,同时引入了 [lobe-ui](https://github.com/lobehub/lobe-ui) 作为我们的业务组件库。
- **状态管理**:我们选用了 [zustand](https://github.com/pmndrs/zustand),一款轻量级且易于使用的状态管理库。
- **网络请求**:我们采用 [swr](https://swr.vercel.app/),这是一款用于数据获取的 React Hooks 库。
- **路由**:路由管理我们直接使用 [Next.js](https://nextjs.org/) 自身提供的解决方案。
- **国际化**:我们使用 [i18next](https://www.i18next.com/) 来实现应用的多语言支持。
- **样式**:我们使用 [antd-style](https://github.com/ant-design/antd-style),这是一款与 Ant Design 配套的 CSS-in-JS 库。
- **单元测试**:我们使用 [vitest](https://github.com/vitest-dev/vitest) 进行单元测试。
## 文件夹目录架构
LobeChat 的文件夹目录架构如下:
```bash
src
├── app # 应用主要逻辑和状态管理相关的代码
├── components # 可复用的 UI 组件
├── config # 应用的配置文件,包含客户端环境变量与服务端环境变量
├── const # 用于定义常量,如 action 类型、路由名等
├── features # 与业务功能相关的功能模块,如 Agent 设置、插件开发弹窗等
├── hooks # 全应用复用自定义的工具 Hooks
├── layout # 应用的布局组件,如导航栏、侧边栏等
├── locales # 国际化的语言文件
├── services # 封装的后端服务接口,如 HTTP 请求
├── store # 用于状态管理的 zustand store
├── types # TypeScript 的类型定义文件
└── utils # 通用的工具函数
```
有关目录架构的详细介绍,详见: [文件夹目录架构](Folder-Structure.zh-CN.md)
## 本地开发环境设置
本节将概述搭建开发环境并进行本地开发。 在开始之前,请确保你的本地环境中已安装 Node.js、Git 以及你选择的包管理器Bun 或 PNPM
我们推荐使用 WebStorm 作为你的集成开发环境IDE
1. **获取代码**:克隆 LobeChat 的代码库到本地:
```bash
git clone https://github.com/lobehub/lobe-chat.git
```
2. **安装依赖**:进入项目目录,并安装所需依赖:
```bash
cd lobe-chat
# 如果你使用 Bun
bun install
# 如果你使用 PNPM
pnpm install
```
3. **运行与调试**:启动本地开发服务器,开始你的开发之旅:
```bash
# 使用 Bun 启动开发服务器
bun run dev
# 访问 http://localhost:3010 查看应用
```
现在,你应该可以在浏览器中看到 LobeChat 的欢迎页面。详细的环境配置指南,请参考 [开发环境设置指南](Setup-Development.zh-CN.md)。
## 代码风格与贡献指南
在 LobeChat 项目中,我们十分重视代码的质量和一致性。为此,我们制定了一系列的代码风格规范和贡献流程,以确保每位开发者都能顺利地参与到项目中。以下是你作为开发者需要遵守的代码风格和贡献准则。
- **代码风格**:我们使用 `@lobehub/lint` 统一代码风格,包括 ESLint、Prettier、remarklint 和 stylelint 配置。请遵守我们的代码规范,以保持代码的一致性和可读性。
- **贡献流程**:我们采用 gitmoji 和 semantic release 作为代码提交和发布流程。请使用 gitmoji 标注您的提交信息,并确保遵循 semantic release 的规范,以便我们的自动化系统能够正确处理版本控制和发布。
所有的贡献都将经过代码审查。维护者可能会提出修改建议或要求。请积极响应审查意见,并及时做出调整,我们期待你的参与和贡献。
详细的代码风格和贡献指南,请参考 [代码风格与贡献指南](Contributing-Guidelines.zh-CN.md)。
## 国际化实现指南
LobeChat 采用 `i18next``lobe-i18n` 实现多语言支持,确保用户全球化体验。
国际化文件位于 `src/locales`,包含默认语言(中文)。 我们会通过 `lobe-i18n` 自动生成其他的语言 JSON 文件。
如果要添加新语种,需遵循特定步骤,详见 [新语种添加指南](../Internationalization/Add-New-Locale.zh-CN.md)。 我们鼓励你参与我们的国际化努力,共同为全球用户提供更好的服务。
详细的国际化实现指南指南,请参考 [国际化实现指南](../Internationalization/Internationalization-Implementation.zh-CN.md)。
## 附录:资源与参考
为了支持开发者更好地理解和使用 LobeChat 的技术栈,我们提供了一份详尽的资源与参考列表 —— [LobeChat 资源与参考](https://github.com/lobehub/lobe-chat/wiki/Resources.zh-CN) - 访问我们维护的资源列表,包括教程、文章和其他有用的链接。
我们鼓励开发者利用这些资源深入学习和提升技能,通过 [LobeChat GitHub Discussions](https://github.com/lobehub/lobe-chat/discussions) 或者 [Discord](https://discord.com/invite/AYFPHvv2jT) 加入社区讨论,提出问题或分享你的经验。
如果你有任何疑问,或者需要进一步的帮助,请不要犹豫,请通过上述渠道与我们联系。

View File

@ -0,0 +1,19 @@
# Resources and References
The design and development of LobeChat would not have been possible without the excellent projects in the community and ecosystem. We have used or referred to some outstanding resources and guides in the design and development process. Here are some key reference resources for developers to refer to during the development and learning process:
1. **OpenAI API Guide**: We use OpenAI's API to access and process AI conversation data. You can check out the [OpenAI API Guide](https://platform.openai.com/docs/api-reference/introduction) for more details.
2. **OpenAI SDK**: We use OpenAI's Node.js SDK to interact with OpenAI's API. You can view the source code and documentation on the [OpenAI SDK](https://github.com/openai/openai-node) GitHub repository.
3. **AI SDK**: We use Vercel's AI SDK to access and process AI conversation data. You can refer to the documentation of [AI SDK](https://sdk.vercel.ai/docs) for more details.
4. **LangChain**: Our early conversation feature was implemented based on LangChain. You can visit [LangChain](https://langchain.com) to learn more about it.
5. **Chat-Next-Web**: Chat Next Web is an excellent project, and some of LobeChat's features and workflows are referenced from its implementation. You can view the source code and documentation on the [Chat-Next-Web](https://github.com/Yidadaa/ChatGPT-Next-Web) GitHub repository.
6. **Next.js Documentation**: Our project is built on Next.js, and you can refer to the [Next.js Documentation](https://nextjs.org/docs) for more information about Next.js.
7. **FlowGPT**: FlowGPT is currently the world's largest Prompt community, and some of the agents in LobeChat come from active authors in FlowGPT. You can visit [FlowGPT](https://flowgpt.com/) to learn more about it.
We will continue to update and supplement this list to provide developers with more reference resources.

View File

@ -0,0 +1,19 @@
# 资源与参考
LobeChat 的设计和开发离不开社区和生态中的优秀项目。我们在设计和开发过程中使用或参考了一些优秀的资源和指南。以下是一些主要的参考资源,供开发者在开发和学习过程中参考:
1. **OpenAI API 指南**:我们使用 OpenAI 的 API 来获取和处理 AI 的会话数据。你可以查看 [OpenAI API 指南](https://platform.openai.com/docs/api-reference/introduction) 了解更多详情。
2. **OpenAI SDK**:我们使用 OpenAI 的 Node.js SDK 来与 OpenAI 的 API 交互。你可以在 [OpenAI SDK](https://github.com/openai/openai-node) 的 GitHub 仓库中查看源码和文档。
3. **AI SDK**:我们使用 Vercel 的 AI SDK 来获取和处理 AI 的会话数据。你可以查看 [AI SDK](https://sdk.vercel.ai/docs) 的文档来了解更多详情。
4. **LangChain**:我们早期的会话功能是基于 LangChain 实现的。你可以访问 [LangChain](https://langchain.com) 来了解更多关于它的信息。
5. **Chat-Next-Web**Chat Next Web 是一个优秀的项目LobeChat 的部分功能、Workflow 等参考了它的实现。你可以在 [Chat-Next-Web](https://github.com/Yidadaa/ChatGPT-Next-Web) 的 GitHub 仓库中查看源码和文档。
6. **Next.js 文档**:我们的项目是基于 Next.js 构建的,你可以查看 [Next.js 文档](https://nextjs.org/docs) 来了解更多关于 Next.js 的信息。
7. **FlowGPT**FlowGPT 是目前全球最大的 Prompt 社区LobeChat 中的一些 Agent 来自 FlowGPT 的活跃作者。你可以访问 [FlowGPT](https://flowgpt.com/) 来了解更多关于它的信息。
我们会持续更新和补充这个列表,为开发者提供更多的参考资源。

View File

@ -0,0 +1,69 @@
# Environment Setup Guide
Welcome to the LobeChat development environment setup guide.
#### TOC
- [Online Development](#online-development)
- [Local Development](#local-development)
- [Development Environment Requirements](#development-environment-requirements)
- [Project Setup](#project-setup)
## Online Development
If you have access to GitHub Codespaces, you can click the button below to enter the online development environment with just one click:
[![][codespaces-shield]][codespaces-link]
## Local Development
Before starting development on LobeChat, you need to install and configure some necessary software and tools in your local environment. This document will guide you through these steps.
### Development Environment Requirements
First, you need to install the following software:
- Node.js: LobeChat is built on Node.js, so you need to install Node.js. We recommend installing the latest stable version.
- Yarn: We use Yarn as the preferred package manager. You can download and install it from the Yarn official website.
- PNPM: We use PNPM as an auxiliary package manager. You can download and install it from the PNPM official website.
- Git: We use Git for version control. You can download and install it from the Git official website.
- IDE: You can choose your preferred integrated development environment (IDE). We recommend using WebStorm, a powerful IDE particularly suitable for TypeScript development.
### Project Setup
After installing the above software, you can start setting up the LobeChat project.
1. **Get the code**: First, you need to clone the LobeChat codebase from GitHub. Run the following command in the terminal:
```bash
git clone https://github.com/lobehub/lobe-chat.git
```
2. **Install dependencies**: Then, navigate to the project directory and use Yarn to install the project's dependencies:
```bash
cd lobe-chat
yarn install
```
If you are using PNPM, you can execute:
```bash
cd lobe-chat
pnpm install
```
3. **Start the development server**: After installing the dependencies, you can start the development server:
```bash
yarn run dev
```
Now, you can open `http://localhost:3010` in your browser, and you should see the welcome page of LobeChat. This indicates that you have successfully set up the development environment.
![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/274655364-414bc31e-8511-47a3-af17-209b530effc7.png)
During the development process, if you encounter any issues with environment setup or have any questions about LobeChat development, feel free to ask us at any time. We look forward to seeing your contributions!
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg

View File

@ -0,0 +1,69 @@
# 环境设置指南
欢迎阅读 LobeChat 的开发环境设置指南。
#### TOC
- [在线开发](#在线开发)
- [本地开发](#本地开发)
- [开发环境需求](#开发环境需求)
- [项目设置](#项目设置)
## 在线开发
如果你有 GitHub Codespaces 的使用权限,可以点击下方按钮一键进入在线开发环境:
[![][codespaces-shield]][codespaces-link]
## 本地开发
在开始开发 LobeChat 之前,你需要在本地环境中安装和配置一些必要的软件和工具。本文档将指导你完成这些步骤。
### 开发环境需求
首先,你需要安装以下软件:
- Node.jsLobeChat 是基于 Node.js 构建的,因此你需要安装 Node.js。我们建议安装最新的稳定版。
- Bun我们使用 Bun 作为首选包管理器。你可以从 Bun 的官方网站上下载并安装。
- PNPM我们使用 PNPM 作为辅助包管理器。你可以从 pnpm 的官方网站上下载并安装。
- Git我们使用 Git 进行版本控制。你可以从 Git 的官方网站上下载并安装。
- IDE你可以选择你喜欢的集成开发环境IDE。我们推荐使用 WebStorm它是一款功能强大的 IDE特别适合 TypeScript 开发。
### 项目设置
完成上述软件的安装后,你可以开始设置 LobeChat 项目了。
1. **获取代码**:首先,你需要从 GitHub 上克隆 LobeChat 的代码库。在终端中运行以下命令:
```bash
git clone https://github.com/lobehub/lobe-chat.git
```
2. **安装依赖**:然后,进入项目目录,并使用 bun 安装项目的依赖包:
```bash
cd lobe-chat
bun i
```
如果你使用 pnpm ,可以执行:
```bash
cd lobe-chat
pnpm i
```
3. **启动开发服务器**:安装完依赖后,你可以启动开发服务器:
```bash
bun run dev
```
现在,你可以在浏览器中打开 `http://localhost:3010`,你应该能看到 LobeChat 的欢迎页面。这表明你已经成功地设置了开发环境。
![](https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/274655364-414bc31e-8511-47a3-af17-209b530effc7.png)
在开发过程中,如果你在环境设置上遇到任何问题,或者有任何关于 LobeChat 开发的问题,欢迎随时向我们提问。我们期待看到你的贡献!
[codespaces-link]: https://codespaces.new/lobehub/lobe-chat
[codespaces-shield]: https://github.com/codespaces/badge.svg

View File

@ -0,0 +1,87 @@
# Testing Guide
LobeChat's testing strategy includes unit testing and end-to-end (E2E) testing. Below are detailed explanations of each type of testing:
#### TOC
- [Unit Testing](#unit-testing)
- [🚧 End-to-End Testing](#-end-to-end-testing)
- [Development Testing](#development-testing)
- [1. Unit Testing](#1-unit-testing)
- [Testing Strategy](#testing-strategy)
## Unit Testing
Unit testing is used to test the functionality of independent units in the application, such as components, functions, utility functions, etc. We use [vitest][vitest-url] for unit testing.
To run unit tests, you can use the following command:
```
npm run test
```
This will run all unit tests and generate a test report.
We encourage developers to write corresponding unit tests while writing code to ensure the quality and stability of the code.
## 🚧 End-to-End Testing
End-to-end testing is used to test the functionality and performance of the application in a real environment. It simulates real user operations and verifies the application's performance in different scenarios.
Currently, there is no integrated end-to-end testing in LobeChat. We will gradually introduce end-to-end testing in subsequent iterations.
## Development Testing
### 1. Unit Testing
Unit testing is conducted on the smallest testable units in the application, usually functions, components, or modules. In LobeChat, we use [vitest][vitest-url] for unit testing.
#### Writing Test Cases
Before writing unit tests, you need to create a directory with the same name as the file to be tested and name the test file `<filename>.test.ts`. For example, if you want to test the `src/utils/formatDate.ts` file, the test file should be named `src/utils/formatDate.test.ts`.
In the test file, you can use the `describe` and `it` functions to organize and write test cases. The `describe` function is used to create a test suite, and the `it` function is used to write specific test cases.
```typescript
import { formatNumber } from './formatNumber';
describe('formatNumber', () => {
it('should format number with comma separator', () => {
const result = formatNumber(1000);
expect(result).toBe('1,000');
});
it('should return the same number if it is less than 1000', () => {
const result = formatNumber(500);
expect(result).toBe('500');
});
});
```
In test cases, you can use the `expect` function to assert whether the test results meet expectations. The `expect` function can be used with various matchers, such as `toBe`, `toEqual`, `toBeTruthy`, etc.
#### Running Unit Tests
Execute unit tests by running the following command:
```
npm run test
```
This will run all unit tests and output the test results.
## Testing Strategy
To write effective test cases, you can consider the following testing strategies:
- **Boundary Testing**: Test the boundary conditions of inputs, such as minimum value, maximum value, empty value, etc.
- **Exception Testing**: Test the code handling exceptional cases, such as error handling, fallback in exceptional situations, etc.
- **Functional Testing**: Test whether various functional modules of the application work properly, including user interaction, data processing, etc.
- **Compatibility Testing**: Test the compatibility of the application on different browsers and devices.
- **Performance Testing**: Test the performance of the application under different loads, such as response time, resource utilization, etc.
Also, ensure that your test cases have good coverage, covering critical code and functionality in the application.
By properly writing and executing unit tests, integration tests, and end-to-end tests, you can improve the quality and stability of the application and promptly identify and fix potential issues.
[vitest-url]: https://vitest.dev/

View File

@ -0,0 +1,87 @@
# 测试指南
LobeChat 的测试策略包括单元测试和端到端 (E2E) 测试。下面是每种测试的详细说明:
#### TOC
- [单元测试](#单元测试)
- [🚧 端到端测试](#-端到端测试)
- [开发测试](#开发测试)
- [1. 单元测试](#1-单元测试)
- [测试策略](#测试策略)
## 单元测试
单元测试用于测试应用中的独立单元(如组件、函数、工具函数等)的功能。我们使用 [vitest][vitest-url] 进行单元测试。
要运行单元测试,可以使用以下命令:
```
npm run test
```
这将运行所有的单元测试,并生成测试报告。
我们鼓励开发者在编写代码时,同时编写对应的单元测试,以确保代码的质量和稳定性。
## 🚧 端到端测试
端到端测试用于测试应用在真实环境中的功能和性能。它模拟用户的真实操作,并验证应用在不同场景下的表现。
在 LobeChat 中,目前暂时没有集成端到端测试,我们会在后续迭代中逐步引入端到端测试。
## 开发测试
### 1. 单元测试
单元测试是针对应用中的最小可测试单元进行的测试,通常是针对函数、组件或模块进行的测试。在 LobeChat 中,我们使用 [vitest][vitest-url] 进行单元测试。
#### 编写测试用例
在编写单元测试之前,您需要创建一个与被测试文件相同的目录,并将测试文件命名为 `<filename>.test.ts`。例如,如果要测试 `src/utils/formatDate.ts` 文件,测试文件应命名为 `src/utils/formatDate.test.ts`
在测试文件中,您可以使用 `describe``it` 函数来组织和编写测试用例。`describe` 函数用于创建测试套件,`it` 函数用于编写具体的测试用例。
```typescript
import { formatNumber } from './formatNumber';
describe('formatNumber', () => {
it('should format number with comma separator', () => {
const result = formatNumber(1000);
expect(result).toBe('1,000');
});
it('should return the same number if it is less than 1000', () => {
const result = formatNumber(500);
expect(result).toBe('500');
});
});
```
在测试用例中,您可以使用 `expect` 函数来断言测试结果是否符合预期。`expect` 函数可以与各种匹配器matchers一起使用例如 `toBe``toEqual``toBeTruthy` 等。
#### 运行单元测试
通过运行以下命令来执行单元测试:
```
npm run test
```
这将运行所有的单元测试,并输出测试结果。
## 测试策略
为了编写有效的测试用例,您可以考虑以下测试策略:
- **边界条件测试**:测试输入的边界条件,例如最小值、最大值、空值等。
- **异常情况测试**:测试处理异常情况的代码,例如错误处理、异常情况下的回退等。
- **功能测试**:测试应用的各个功能模块是否正常工作,包括用户交互、数据处理等。
- **兼容性测试**:测试应用在不同浏览器和设备上的兼容性。
- **性能测试**:测试应用在不同负载下的性能表现,例如响应时间、资源占用等。
同时,请确保您的测试用例具有良好的覆盖率,覆盖到应用中的关键代码和功能。
通过合理编写和执行单元测试、集成测试和端到端测试,您可以提高应用的质量和稳定性,并及时发现和修复潜在的问题。
[vitest-url]: https://vitest.dev/

View File

@ -0,0 +1,95 @@
<div align="center">
<img height="120" src="https://registry.npmmirror.com/@lobehub/assets-logo/1.0.0/files/assets/logo-3d.webp">
<img height="120" src="https://gw.alipayobjects.com/zos/kitchen/qJ3l3EPsdW/split.svg">
<img height="120" src="https://registry.npmmirror.com/@lobehub/assets-emoji/1.3.0/files/assets/robot.webp">
<h1>Lobe Chat Contributing Wiki</h1>
LobeChat is an open-source, extensible ([Function Calling][fc-url]), high-performance chatbot framework. <br/> It supports one-click free deployment of your private ChatGPT/LLM web application.
[Usage Documents](https://chat-docs.lobehub.com/en) | [使用指南](https://chat-docs.lobehub.com/zh)
</div>
![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)
<!-- DOCS LIST -->
### 🤯 Basic
- [Architecture Design](https://github.com/lobehub/lobe-chat/wiki/Architecture) | [架构设计](https://github.com/lobehub/lobe-chat/wiki/Architecture.zh-CN)
- [Code Style and Contribution Guidelines](https://github.com/lobehub/lobe-chat/wiki/Contributing-Guidelines) | [代码风格与贡献指南](https://github.com/lobehub/lobe-chat/wiki/Contributing-Guidelines.zh-CN)
- [Complete Guide to LobeChat Feature Development](https://github.com/lobehub/lobe-chat/wiki/Feature-Development) | [LobeChat 功能开发完全指南](https://github.com/lobehub/lobe-chat/wiki/Feature-Development.zh-CN)
- [Conversation API Implementation Logic](https://github.com/lobehub/lobe-chat/wiki/Chat-API) | [会话 API 实现逻辑](https://github.com/lobehub/lobe-chat/wiki/Chat-API.zh-CN)
- [Directory Structure](https://github.com/lobehub/lobe-chat/wiki/Folder-Structure) | [目录架构](https://github.com/lobehub/lobe-chat/wiki/Folder-Structure.zh-CN)
- [Environment Setup Guide](https://github.com/lobehub/lobe-chat/wiki/Setup-Development) | [环境设置指南](https://github.com/lobehub/lobe-chat/wiki/Setup-Development.zh-CN)
- [How to Develop a New Feature](https://github.com/lobehub/lobe-chat/wiki/Feature-Development-Frontend) | [如何开发一个新功能:前端实现](https://github.com/lobehub/lobe-chat/wiki/Feature-Development-Frontend.zh-CN)
- [New Authentication Provider Guide](https://github.com/lobehub/lobe-chat/wiki/Add-New-Authentication-Providers) | [新身份验证方式开发指南](https://github.com/lobehub/lobe-chat/wiki/Add-New-Authentication-Providers.zh-CN)
- [Resources and References](https://github.com/lobehub/lobe-chat/wiki/Resources) | [资源与参考](https://github.com/lobehub/lobe-chat/wiki/Resources.zh-CN)
- [Technical Development Getting Started Guide](https://github.com/lobehub/lobe-chat/wiki/Intro) | [技术开发上手指南](https://github.com/lobehub/lobe-chat/wiki/Intro.zh-CN)
- [Testing Guide](https://github.com/lobehub/lobe-chat/wiki/Test) | [测试指南](https://github.com/lobehub/lobe-chat/wiki/Test.zh-CN)
<br/>
### 🌎 Internationalization
- [Internationalization Implementation Guide](https://github.com/lobehub/lobe-chat/wiki/Internationalization-Implementation) | [国际化实现指南](https://github.com/lobehub/lobe-chat/wiki/Internationalization-Implementation.zh-CN)
- [New Locale Guide](https://github.com/lobehub/lobe-chat/wiki/Add-New-Locale) | [新语种添加指南](https://github.com/lobehub/lobe-chat/wiki/Add-New-Locale.zh-CN)
<br/>
### ⌨️ State Management
- [Best Practices for State Management](https://github.com/lobehub/lobe-chat/wiki/State-Management-Intro) | [状态管理最佳实践](https://github.com/lobehub/lobe-chat/wiki/State-Management-Intro.zh-CN)
- [Data Store Selector](https://github.com/lobehub/lobe-chat/wiki/State-Management-Selectors) | [数据存储取数模块](https://github.com/lobehub/lobe-chat/wiki/State-Management-Selectors.zh-CN)
<br/>
### 🤖 Agents
- [Agent Index and Submit](https://github.com/lobehub/lobe-chat-agents) | [助手索引与提交](https://github.com/lobehub/lobe-chat-agents/blob/main/README.zh-CN.md)
<br/>
### 🧩 Plugins
- [Plugin Index and Submit](https://github.com/lobehub/lobe-chat-plugins) | [插件索引与提交](https://github.com/lobehub/lobe-chat-plugins/blob/main/README.zh-CN.md)
- [Plugin SDK Docs](https://chat-plugin-sdk.lobehub.com) | [插件 SDK 文档](https://chat-plugin-sdk.lobehub.com)
<br/>
### 📊 Others
- [Lighthouse Reports](https://github.com/lobehub/lobe-chat/wiki/Lighthouse) | [Lighthouse 测试报告](https://github.com/lobehub/lobe-chat/wiki/Lighthouse.zh-CN)
<br/>
<!-- DOCS LIST -->
---
<details><summary><h4>📝 License</h4></summary>
[![][fossa-license-shield]][fossa-license-url]
</details>
Copyright © 2023 [LobeHub][profile-url]. <br />
This project is [MIT][license-url] licensed.
<!-- LINK GROUP -->
[fc-url]: https://sspai.com/post/81986
[fossa-license-shield]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat.svg?type=large
[fossa-license-url]: https://app.fossa.com/projects/git%2Bgithub.com%2Flobehub%2Flobe-chat
[license-url]: https://github.com/lobehub/lobe-chat/blob/main/LICENSE
[profile-url]: https://github.com/lobehub

View File

@ -0,0 +1,62 @@
# New Locale Guide
LobeChat uses [lobe-i18n](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n) as the i18n solution, which allows for quick addition of new language support in the application.
## TOC
- [Adding New Language Support](#adding-new-language-support)
- [Step 1: Update the Internationalization Configuration File](#step-1-update-the-internationalization-configuration-file)
- [Step 2: Automatically Translate Language Files](#step-2-automatically-translate-language-files)
- [Step 3: Submit and Review Your Changes](#step-3-submit-and-review-your-changes)
- [Additional Information](#additional-information)
## Adding New Language Support
To add new language internationalization support in LobeChat (for example, adding Vietnamese `vi-VN`), please follow the steps below:
### Step 1: Update the Internationalization Configuration File
1. Open the `.i18nrc.js` file. You can find this file in the project's root directory.
2. Add the new language code to the configuration file. For example, to add Vietnamese, you need to add `'vi-VN'` to the configuration file.
```js
module.exports = {
// ... Other configurations
outputLocales: [
'zh-TW',
'en-US',
'ru-RU',
'ja-JP',
// ...Other languages
'vi-VN', // Add 'vi-VN' to the array
],
};
```
### Step 2: Automatically Translate Language Files
LobeChat uses the `lobe-i18n` tool to automatically translate language files, so manual updating of i18n files is not required.
Run the following command to automatically translate and generate the Vietnamese language files:
```bash
npm run i18n
```
This will utilize the `lobe-i18n` tool to process the language files.
### Step 3: Submit and Review Your Changes
Once you have completed the above steps, you need to submit your changes and create a Pull Request.
Ensure that you follow LobeChat's contribution guidelines and provide a necessary description to explain your changes. For example, refer to a similar previous Pull Request [#759](https://github.com/lobehub/lobe-chat/pull/759).
### Additional Information
- After submitting your Pull Request, please patiently wait for the project maintainers to review it.
- If you encounter any issues, you can reach out to the LobeChat community for assistance.
- For more accurate results, ensure that your Pull Request is based on the latest main branch and stays in sync with the main branch.
By following the above steps, you can successfully add new language support to LobeChat and ensure that the application provides a localized experience for more users.

View File

@ -0,0 +1,62 @@
# 新语种添加指南
LobeChat 使用 [lobe-i18n](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n) 作为 i18n 解决方案,可以在应用中快速添加新的语言支持。
## TOC
- [添加新的语言支持](#添加新的语言支持)
- [步骤 1: 更新国际化配置文件](#步骤-1-更新国际化配置文件)
- [步骤 2: 自动翻译语言文件](#步骤-2-自动翻译语言文件)
- [步骤 3: 提交和审查你的更改](#步骤-3-提交和审查你的更改)
- [附加信息](#附加信息)
## 添加新的语言支持
为了在 LobeChat 中添加新的语言国际化支持,(例如添加越南语 `vi-VN`),请按照以下步骤操作:
### 步骤 1: 更新国际化配置文件
1. 打开 `.i18nrc.js` 文件。你可以在项目的根目录中找到此文件。
2. 将新的语言代码添加到配置文件中。例如,为了添加越南语,你需要在配置文件中添加 `'vi-VN'`
```js
module.exports = {
// ... 其他配置
outputLocales: [
'zh-TW',
'en-US',
'ru-RU',
'ja-JP',
// ...其他语言
'vi-VN', // 在数组中添加 'vi-VN'
],
};
```
### 步骤 2: 自动翻译语言文件
LobeChat 使用 `lobe-i18n` 工具来自动翻译语言文件,因此不需要手动更新 i18n 文件。
运行以下命令来自动翻译并生成越南语的语言文件:
```bash
npm run i18n
```
这将会利用 `lobe-i18n` 工具来处理语言文件。
### 步骤 3: 提交和审查你的更改
一旦你完成了上述步骤,你需要提交你的更改并创建一个 Pull Request。
请确保你遵循了 LobeChat 的贡献指南,并提供必要的描述来说明你的更改。例如,参考之前的类似 Pull Request [#759](https://github.com/lobehub/lobe-chat/pull/759)。
### 附加信息
- 提交你的 Pull Request 后,请耐心等待项目维护人员的审查。
- 如果遇到任何问题,可以联系 LobeChat 社区寻求帮助。
- 为了更精确的结果,确保你的 Pull Request 是基于最新的主分支,并且与主分支保持同步。
通过遵循上述步骤,你可以成功为 LobeChat 添加新的语言支持,并且确保应用能够为更多用户提供本地化的体验。

View File

@ -0,0 +1,125 @@
# Internationalization Implementation Guide
Welcome to the LobeChat Internationalization Implementation Guide. This document will guide you through understanding the internationalization mechanism of LobeChat, including file structure and how to add new languages. LobeChat uses `i18next` and `lobe-i18n` as the internationalization solution, aiming to provide users with seamless multilingual support.
## TOC
- [Internationalization Overview](#internationalization-overview)
- [File Structure](#file-structure)
- [Core Implementation Logic](#core-implementation-logic)
- [Adding Support for New Languages](#adding-support-for-new-languages)
- [Resources and Further Reading](#resources-and-further-reading)
## Internationalization Overview
Internationalization (i18n for short) is the process of enabling an application to adapt to different languages and regions. In LobeChat, we support multiple languages and achieve dynamic language switching and content localization through the `i18next` library. Our goal is to provide a localized experience for global users.
## File Structure
In the LobeChat project, internationalization-related files are organized as follows:
- `src/locales/default`: Contains translation files for the default development language (Chinese), which we use as Chinese.
- `locales`: Contains folders for all supported languages, with each language folder containing the respective translation files generated by lobe-i18n.
In the directory structure of `src/locales`, the `default` folder contains the original translation files (Chinese), while each other language folder contains JSON translation files for the respective language. The files in each language folder correspond to the TypeScript files in the `default` folder, ensuring consistency in the structure of translation files across languages.
```
src/locales
├── create.ts
├── default
│ ├── chat.ts
│ ├── common.ts
│ ├── error.ts
│ ├── index.ts
│ ├── market.ts
│ ├── migration.ts
│ ├── plugin.ts
│ ├── setting.ts
│ ├── tool.ts
│ └── welcome.ts
└── resources.ts
```
The file structure generated by lobe-i18n is as follows:
```
locales
├── ar
│ ├── chat.json
│ ├── common.json
│ ├── error.json
│ └── ... (other translation files)
├── de-DE
│ ├── chat.json
│ ├── common.json
│ ├── error.json
│ └── ... (other translation files)
├── en-US
├── ... (other language directories)
├── zh-CN
└── zh-TW
```
## Core Implementation Logic
The internationalization core implementation logic of LobeChat is as follows:
- Initialize and configure using the `i18next` library.
- Automatically detect the user's language preference using `i18next-browser-languagedetector`.
- Dynamically load translation resources using `i18next-resources-to-backend`.
- Set the direction of the HTML document (LTR or RTL) based on the user's language preference.
Here is a simplified pseudo code example to illustrate the core implementation logic of internationalization in LobeChat:
```ts
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import resourcesToBackend from 'i18next-resources-to-backend';
import { isRtlLang } from 'rtl-detect';
// Create i18n instance and configure
const createI18nInstance = (lang) => {
const i18nInstance = i18n
.use(LanguageDetector) // Use language detection
.use(
resourcesToBackend((language, namespace) => {
// Dynamically load translation resources for the corresponding language
return import(`path/to/locales/${language}/${namespace}.json`);
}),
);
// Listen for language change events and dynamically set document direction
i18nInstance.on('languageChanged', (language) => {
const direction = isRtlLang(language) ? 'rtl' : 'ltr';
document.documentElement.dir = direction; // Set HTML document direction
});
// Initialize i18n instance
i18nInstance.init({
// Relevant configurations
});
return i18nInstance;
};
```
In this example, we demonstrate how to use `i18next` and related plugins to initialize internationalization settings. We dynamically import translation resources and respond to language change events to adjust the text direction of the page. This process provides LobeChat with flexible multilingual support capabilities.
## Adding Support for New Languages
We have already supported a variety of languages globally through the following efforts:
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobe-chat/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobe-chat/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobe-chat/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobe-chat/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobe-chat/pull/137)
To add support for new languages, please refer to the detailed steps in the [New Locale Addition Guide](Add-New-Locale.en-US).
## Resources and Further Reading
- [i18next Official Documentation](https://www.i18next.com/)
- [lobe-i18n Tool Description](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n)
By following this guide, you can better understand and participate in the internationalization work of LobeChat, providing a seamless multilingual experience for global users.

View File

@ -0,0 +1,125 @@
# 国际化实现指南
欢迎阅读 LobeChat 国际化实现指南。本文档将指导你了解 LobeChat 的国际化机制包括文件结构、如何添加新语种。LobeChat 采用 `i18next``lobe-i18n` 作为国际化解决方案,旨在为用户提供流畅的多语言支持。
## TOC
- [国际化概述](#国际化概述)
- [文件结构](#文件结构)
- [核心实现逻辑](#核心实现逻辑)
- [添加新的语言支持](#添加新的语言支持)
- [资源和进一步阅读](#资源和进一步阅读)
## 国际化概述
国际化Internationalization简称为 i18n是一个让应用能够适应不同语言和地区的过程。在 LobeChat 中,我们支持多种语言,并通过 `i18next` 库来实现语言的动态切换和内容的本地化。我们的目标是让 LobeChat 能够为全球用户提供本地化的体验。
## 文件结构
在 LobeChat 的项目中,国际化相关的文件被组织如下:
- `src/locales/default`: 包含默认开发语言(中文)的翻译文件,我们作为中文。
- `locales`: 包含所有支持的语言文件夹,每个语言文件夹中包含相应语言的翻译文件,这些翻译文件通过 lobe-i18n 自动生成。
`src/locales` 这个目录结构中,`default` 文件夹包含了原始的翻译文件(中文),其他每个语言文件夹则包含了相应语言的 JSON 翻译文件。每个语言文件夹中的文件对应 `default` 文件夹中的 TypeScript 文件,确保了各语种之间的翻译文件结构一致性。
```
src/locales
├── create.ts
├── default
│ ├── chat.ts
│ ├── common.ts
│ ├── error.ts
│ ├── index.ts
│ ├── market.ts
│ ├── migration.ts
│ ├── plugin.ts
│ ├── setting.ts
│ ├── tool.ts
│ └── welcome.ts
└── resources.ts
```
通过 lobe-i18n 自动生成的文件结构如下:
```
locales
├── ar
│ ├── chat.json
│ ├── common.json
│ ├── error.json
│ └── ... (其他翻译文件)
├── de-DE
│ ├── chat.json
│ ├── common.json
│ ├── error.json
│ └── ... (其他翻译文件)
├── en-US
├── ... (其他语种目录)
├── zh-CN
└── zh-TW
```
## 核心实现逻辑
LobeChat 的国际化核心实现逻辑如下:
- 使用 `i18next` 库进行初始化和配置。
- 使用 `i18next-browser-languagedetector` 自动检测用户的语言偏好。
- 使用 `i18next-resources-to-backend` 动态加载翻译资源。
- 根据用户的语言偏好,设置 HTML 文档的方向LTR 或 RTL
以下是一个简化的伪代码示例,用以说明 LobeChat 国际化的核心实现逻辑:
```ts
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import resourcesToBackend from 'i18next-resources-to-backend';
import { isRtlLang } from 'rtl-detect';
// 创建 i18n 实例并配置
const createI18nInstance = (lang) => {
const i18nInstance = i18n
.use(LanguageDetector) // 使用语言检测
.use(
resourcesToBackend((language, namespace) => {
// 动态加载对应语言的翻译资源
return import(`path/to/locales/${language}/${namespace}.json`);
}),
);
// 监听语言变化事件,动态设置文档方向
i18nInstance.on('languageChanged', (language) => {
const direction = isRtlLang(language) ? 'rtl' : 'ltr';
document.documentElement.dir = direction; // 设置 HTML 文档方向
});
// 初始化 i18n 实例
i18nInstance.init({
// 相关配置
});
return i18nInstance;
};
```
在这个示例中,我们展示了如何使用 `i18next` 和相关插件来初始化国际化设置。我们动态导入了翻译资源,并响应语言变化事件来调整页面的文本方向。这个过程为 LobeChat 提供了灵活的多语言支持能力。
## 添加新的语言支持
我们通过以下工作,已经支持了全球多种语言:
- [✨ feat: adding Arabic Language Support #1049](https://github.com/lobehub/lobe-chat/pull/1049)
- [🌐 style: Add Vietnamese files and add the vi-VN option in the General Settings #860](https://github.com/lobehub/lobe-chat/pull/860)
- [🌐 style: support it-IT nl-NL and pl-PL locales #759](https://github.com/lobehub/lobe-chat/pull/759)
- [🌐 feat(locale): Add fr-FR (#637) #645](https://github.com/lobehub/lobe-chat/pull/645)
- [🌐 Add russian localy #137](https://github.com/lobehub/lobe-chat/pull/137)
要添加新的语种支持, 详细步骤请参考:[新语种添加指南](Add-New-Locale.zh-CN.md)。
## 资源和进一步阅读
- [i18next 官方文档](https://www.i18next.com/)
- [lobe-i18n 工具说明](https://github.com/lobehub/lobe-cli-toolbox/tree/master/packages/lobe-i18n)
通过遵循本指南,你可以更好地理解和参与到 LobeChat 的国际化工作中,为全球用户提供无缝的多语言体验。

View File

@ -0,0 +1,65 @@
# Lighthouse Reports
#### TOC
- [Welcome Page](#welcome-page)
- [Chat Page](#chat-page)
- [Market Page](#market-page)
- [Settings Page](#settings-page)
## Welcome Page
> **Info**\
> <https://chat-preview.lobehub.com/welcome>
| Desktop | Mobile |
| :---------------------------------------------: | :--------------------------------------------: |
| ![][welcome-desktop] | ![][welcome-mobile] |
| [⚡️ Lighthouse Report][welcome-desktop-report] | [⚡️ Lighthouse Report][welcome-mobile-report] |
## Chat Page
> **Info**\
> <https://chat-preview.lobehub.com/chat>
| Desktop | Mobile |
| :------------------------------------------: | :-----------------------------------------: |
| ![][chat-desktop] | ![][chat-mobile] |
| [⚡️ Lighthouse Report][chat-desktop-report] | [⚡️ Lighthouse Report][chat-mobile-report] |
## Market Page
> **Info**\
> <https://chat-preview.lobehub.com/market>
| Desktop | Mobile |
| :--------------------------------------------: | :-------------------------------------------: |
| ![][market-desktop] | ![][market-mobile] |
| [⚡️ Lighthouse Report][market-desktop-report] | [⚡️ Lighthouse Report][market-mobile-report] |
## Settings Page
> **Info**\
> <https://chat-preview.lobehub.com/settings>
| Desktop | Mobile |
| :----------------------------------------------: | :---------------------------------------------: |
| ![][settings-desktop] | ![][settings-mobile] |
| [⚡️ Lighthouse Report][settings-desktop-report] | [⚡️ Lighthouse Report][settings-mobile-report] |
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/chat_preview_lobehub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/chat_preview_lobehub_com_chat.html
[market-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/market/desktop/pagespeed.svg
[market-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/market/desktop/chat_preview_lobehub_com_market.html
[market-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/market/mobile/pagespeed.svg
[market-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/market/mobile/chat_preview_lobehub_com_market.html
[settings-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/settings/desktop/pagespeed.svg
[settings-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/settings/desktop/chat_preview_lobehub_com_settings.html
[settings-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/settings/mobile/pagespeed.svg
[settings-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/settings/mobile/chat_preview_lobehub_com_settings.html
[welcome-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/welcome/desktop/pagespeed.svg
[welcome-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/welcome/desktop/chat_preview_lobehub_com_welcome.html
[welcome-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/welcome/mobile/pagespeed.svg
[welcome-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/welcome/mobile/chat_preview_lobehub_com_welcome.html

View File

@ -0,0 +1,65 @@
# Lighthouse 测试报告
#### TOC
- [Welcome 欢迎页面](#welcome-欢迎页面)
- [Chat 聊天页面](#chat-聊天页面)
- [Market 市场页面](#market-市场页面)
- [Settings 设置页面](#settings-设置页面)
## Welcome 欢迎页面
> **Info**\
> <https://chat-preview.lobehub.com/welcome>
| Desktop | Mobile |
| :---------------------------------------------: | :--------------------------------------------: |
| ![][welcome-desktop] | ![][welcome-mobile] |
| [⚡️ Lighthouse Report][welcome-desktop-report] | [⚡️ Lighthouse Report][welcome-mobile-report] |
## Chat 聊天页面
> **Info**\
> <https://chat-preview.lobehub.com/chat>
| Desktop | Mobile |
| :------------------------------------------: | :-----------------------------------------: |
| ![][chat-desktop] | ![][chat-mobile] |
| [⚡️ Lighthouse Report][chat-desktop-report] | [⚡️ Lighthouse Report][chat-mobile-report] |
## Market 市场页面
> **Info**\
> <https://chat-preview.lobehub.com/market>
| Desktop | Mobile |
| :--------------------------------------------: | :-------------------------------------------: |
| ![][market-desktop] | ![][market-mobile] |
| [⚡️ Lighthouse Report][market-desktop-report] | [⚡️ Lighthouse Report][market-mobile-report] |
## Settings 设置页面
> **Info**\
> <https://chat-preview.lobehub.com/settings>
| Desktop | Mobile |
| :----------------------------------------------: | :---------------------------------------------: |
| ![][settings-desktop] | ![][settings-mobile] |
| [⚡️ Lighthouse Report][settings-desktop-report] | [⚡️ Lighthouse Report][settings-mobile-report] |
[chat-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/desktop/pagespeed.svg
[chat-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/desktop/chat_preview_lobehub_com_chat.html
[chat-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/chat/mobile/pagespeed.svg
[chat-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/chat/mobile/chat_preview_lobehub_com_chat.html
[market-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/market/desktop/pagespeed.svg
[market-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/market/desktop/chat_preview_lobehub_com_market.html
[market-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/market/mobile/pagespeed.svg
[market-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/market/mobile/chat_preview_lobehub_com_market.html
[settings-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/settings/desktop/pagespeed.svg
[settings-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/settings/desktop/chat_preview_lobehub_com_settings.html
[settings-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/settings/mobile/pagespeed.svg
[settings-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/settings/mobile/chat_preview_lobehub_com_settings.html
[welcome-desktop]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/welcome/desktop/pagespeed.svg
[welcome-desktop-report]: https://lobehub.github.io/lobe-chat/lighthouse/welcome/desktop/chat_preview_lobehub_com_welcome.html
[welcome-mobile]: https://raw.githubusercontent.com/lobehub/lobe-chat/lighthouse/lighthouse/welcome/mobile/pagespeed.svg
[welcome-mobile-report]: https://lobehub.github.io/lobe-chat/lighthouse/welcome/mobile/chat_preview_lobehub_com_welcome.html

Some files were not shown because too many files have changed in this diff Show More