mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-29 16:05:35 +08:00
Docs: Update version references to v0.23.0 in READMEs and docs (#12253)
### What problem does this PR solve? - Update version tags in README files (including translations) from v0.22.1 to v0.23.0 - Modify Docker image references and documentation to reflect new version - Update version badges and image descriptions - Maintain consistency across all language variants of README files ### Type of change - [x] Documentation Update Co-authored-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@ -22,7 +22,7 @@
|
|||||||
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
||||||
@ -85,6 +85,7 @@ Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
|
|||||||
|
|
||||||
## 🔥 Latest Updates
|
## 🔥 Latest Updates
|
||||||
|
|
||||||
|
- 2025-12-26 Supports 'Memory' for AI agent.
|
||||||
- 2025-11-19 Supports Gemini 3 Pro.
|
- 2025-11-19 Supports Gemini 3 Pro.
|
||||||
- 2025-11-12 Supports data synchronization from Confluence, S3, Notion, Discord, Google Drive.
|
- 2025-11-12 Supports data synchronization from Confluence, S3, Notion, Discord, Google Drive.
|
||||||
- 2025-10-23 Supports MinerU & Docling as document parsing methods.
|
- 2025-10-23 Supports MinerU & Docling as document parsing methods.
|
||||||
@ -187,12 +188,12 @@ releases! 🌟
|
|||||||
> All Docker images are built for x86 platforms. We don't currently offer Docker images for ARM64.
|
> All Docker images are built for x86 platforms. We don't currently offer Docker images for ARM64.
|
||||||
> If you are on an ARM64 platform, follow [this guide](https://ragflow.io/docs/dev/build_docker_image) to build a Docker image compatible with your system.
|
> If you are on an ARM64 platform, follow [this guide](https://ragflow.io/docs/dev/build_docker_image) to build a Docker image compatible with your system.
|
||||||
|
|
||||||
> The command below downloads the `v0.22.1` edition of the RAGFlow Docker image. See the following table for descriptions of different RAGFlow editions. To download a RAGFlow edition different from `v0.22.1`, update the `RAGFLOW_IMAGE` variable accordingly in **docker/.env** before using `docker compose` to start the server.
|
> The command below downloads the `v0.23.0` edition of the RAGFlow Docker image. See the following table for descriptions of different RAGFlow editions. To download a RAGFlow edition different from `v0.23.0`, update the `RAGFLOW_IMAGE` variable accordingly in **docker/.env** before using `docker compose` to start the server.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# Optional: use a stable tag (see releases: https://github.com/infiniflow/ragflow/releases)
|
# Optional: use a stable tag (see releases: https://github.com/infiniflow/ragflow/releases)
|
||||||
# This step ensures the **entrypoint.sh** file in the code matches the Docker image version.
|
# This step ensures the **entrypoint.sh** file in the code matches the Docker image version.
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<img alt="Lencana Daring" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Lencana Daring" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Rilis%20Terbaru" alt="Rilis Terbaru">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Rilis%20Terbaru" alt="Rilis Terbaru">
|
||||||
@ -85,6 +85,7 @@ Coba demo kami di [https://demo.ragflow.io](https://demo.ragflow.io).
|
|||||||
|
|
||||||
## 🔥 Pembaruan Terbaru
|
## 🔥 Pembaruan Terbaru
|
||||||
|
|
||||||
|
- 2025-12-26 Mendukung 'Memori' untuk agen AI.
|
||||||
- 2025-11-19 Mendukung Gemini 3 Pro.
|
- 2025-11-19 Mendukung Gemini 3 Pro.
|
||||||
- 2025-11-12 Mendukung sinkronisasi data dari Confluence, S3, Notion, Discord, Google Drive.
|
- 2025-11-12 Mendukung sinkronisasi data dari Confluence, S3, Notion, Discord, Google Drive.
|
||||||
- 2025-10-23 Mendukung MinerU & Docling sebagai metode penguraian dokumen.
|
- 2025-10-23 Mendukung MinerU & Docling sebagai metode penguraian dokumen.
|
||||||
@ -187,12 +188,12 @@ Coba demo kami di [https://demo.ragflow.io](https://demo.ragflow.io).
|
|||||||
> Semua gambar Docker dibangun untuk platform x86. Saat ini, kami tidak menawarkan gambar Docker untuk ARM64.
|
> Semua gambar Docker dibangun untuk platform x86. Saat ini, kami tidak menawarkan gambar Docker untuk ARM64.
|
||||||
> Jika Anda menggunakan platform ARM64, [silakan gunakan panduan ini untuk membangun gambar Docker yang kompatibel dengan sistem Anda](https://ragflow.io/docs/dev/build_docker_image).
|
> Jika Anda menggunakan platform ARM64, [silakan gunakan panduan ini untuk membangun gambar Docker yang kompatibel dengan sistem Anda](https://ragflow.io/docs/dev/build_docker_image).
|
||||||
|
|
||||||
> Perintah di bawah ini mengunduh edisi v0.22.1 dari gambar Docker RAGFlow. Silakan merujuk ke tabel berikut untuk deskripsi berbagai edisi RAGFlow. Untuk mengunduh edisi RAGFlow yang berbeda dari v0.22.1, perbarui variabel RAGFLOW_IMAGE di docker/.env sebelum menggunakan docker compose untuk memulai server.
|
> Perintah di bawah ini mengunduh edisi v0.23.0 dari gambar Docker RAGFlow. Silakan merujuk ke tabel berikut untuk deskripsi berbagai edisi RAGFlow. Untuk mengunduh edisi RAGFlow yang berbeda dari v0.23.0, perbarui variabel RAGFLOW_IMAGE di docker/.env sebelum menggunakan docker compose untuk memulai server.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# Opsional: gunakan tag stabil (lihat releases: https://github.com/infiniflow/ragflow/releases)
|
# Opsional: gunakan tag stabil (lihat releases: https://github.com/infiniflow/ragflow/releases)
|
||||||
# This steps ensures the **entrypoint.sh** file in the code matches the Docker image version.
|
# This steps ensures the **entrypoint.sh** file in the code matches the Docker image version.
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
||||||
@ -66,7 +66,8 @@
|
|||||||
|
|
||||||
## 🔥 最新情報
|
## 🔥 最新情報
|
||||||
|
|
||||||
- 2025-11-19 Gemini 3 Proをサポートしています
|
- 2025-12-26 AIエージェントの「メモリ」機能をサポート。
|
||||||
|
- 2025-11-19 Gemini 3 Proをサポートしています。
|
||||||
- 2025-11-12 Confluence、S3、Notion、Discord、Google Drive からのデータ同期をサポートします。
|
- 2025-11-12 Confluence、S3、Notion、Discord、Google Drive からのデータ同期をサポートします。
|
||||||
- 2025-10-23 ドキュメント解析方法として MinerU と Docling をサポートします。
|
- 2025-10-23 ドキュメント解析方法として MinerU と Docling をサポートします。
|
||||||
- 2025-10-15 オーケストレーションされたデータパイプラインのサポート。
|
- 2025-10-15 オーケストレーションされたデータパイプラインのサポート。
|
||||||
@ -167,12 +168,12 @@
|
|||||||
> 現在、公式に提供されているすべての Docker イメージは x86 アーキテクチャ向けにビルドされており、ARM64 用の Docker イメージは提供されていません。
|
> 現在、公式に提供されているすべての Docker イメージは x86 アーキテクチャ向けにビルドされており、ARM64 用の Docker イメージは提供されていません。
|
||||||
> ARM64 アーキテクチャのオペレーティングシステムを使用している場合は、[このドキュメント](https://ragflow.io/docs/dev/build_docker_image)を参照して Docker イメージを自分でビルドしてください。
|
> ARM64 アーキテクチャのオペレーティングシステムを使用している場合は、[このドキュメント](https://ragflow.io/docs/dev/build_docker_image)を参照して Docker イメージを自分でビルドしてください。
|
||||||
|
|
||||||
> 以下のコマンドは、RAGFlow Docker イメージの v0.22.1 エディションをダウンロードします。異なる RAGFlow エディションの説明については、以下の表を参照してください。v0.22.1 とは異なるエディションをダウンロードするには、docker/.env ファイルの RAGFLOW_IMAGE 変数を適宜更新し、docker compose を使用してサーバーを起動してください。
|
> 以下のコマンドは、RAGFlow Docker イメージの v0.23.0 エディションをダウンロードします。異なる RAGFlow エディションの説明については、以下の表を参照してください。v0.23.0 とは異なるエディションをダウンロードするには、docker/.env ファイルの RAGFLOW_IMAGE 変数を適宜更新し、docker compose を使用してサーバーを起動してください。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# 任意: 安定版タグを利用 (一覧: https://github.com/infiniflow/ragflow/releases)
|
# 任意: 安定版タグを利用 (一覧: https://github.com/infiniflow/ragflow/releases)
|
||||||
# この手順は、コード内の entrypoint.sh ファイルが Docker イメージのバージョンと一致していることを確認します。
|
# この手順は、コード内の entrypoint.sh ファイルが Docker イメージのバージョンと一致していることを確認します。
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
||||||
@ -67,6 +67,7 @@
|
|||||||
|
|
||||||
## 🔥 업데이트
|
## 🔥 업데이트
|
||||||
|
|
||||||
|
- 2025-12-26 AI 에이전트의 '메모리' 기능 지원.
|
||||||
- 2025-11-19 Gemini 3 Pro를 지원합니다.
|
- 2025-11-19 Gemini 3 Pro를 지원합니다.
|
||||||
- 2025-11-12 Confluence, S3, Notion, Discord, Google Drive에서 데이터 동기화를 지원합니다.
|
- 2025-11-12 Confluence, S3, Notion, Discord, Google Drive에서 데이터 동기화를 지원합니다.
|
||||||
- 2025-10-23 문서 파싱 방법으로 MinerU 및 Docling을 지원합니다.
|
- 2025-10-23 문서 파싱 방법으로 MinerU 및 Docling을 지원합니다.
|
||||||
@ -169,12 +170,12 @@
|
|||||||
> 모든 Docker 이미지는 x86 플랫폼을 위해 빌드되었습니다. 우리는 현재 ARM64 플랫폼을 위한 Docker 이미지를 제공하지 않습니다.
|
> 모든 Docker 이미지는 x86 플랫폼을 위해 빌드되었습니다. 우리는 현재 ARM64 플랫폼을 위한 Docker 이미지를 제공하지 않습니다.
|
||||||
> ARM64 플랫폼을 사용 중이라면, [시스템과 호환되는 Docker 이미지를 빌드하려면 이 가이드를 사용해 주세요](https://ragflow.io/docs/dev/build_docker_image).
|
> ARM64 플랫폼을 사용 중이라면, [시스템과 호환되는 Docker 이미지를 빌드하려면 이 가이드를 사용해 주세요](https://ragflow.io/docs/dev/build_docker_image).
|
||||||
|
|
||||||
> 아래 명령어는 RAGFlow Docker 이미지의 v0.22.1 버전을 다운로드합니다. 다양한 RAGFlow 버전에 대한 설명은 다음 표를 참조하십시오. v0.22.1과 다른 RAGFlow 버전을 다운로드하려면, docker/.env 파일에서 RAGFLOW_IMAGE 변수를 적절히 업데이트한 후 docker compose를 사용하여 서버를 시작하십시오.
|
> 아래 명령어는 RAGFlow Docker 이미지의 v0.23.0 버전을 다운로드합니다. 다양한 RAGFlow 버전에 대한 설명은 다음 표를 참조하십시오. v0.23.0과 다른 RAGFlow 버전을 다운로드하려면, docker/.env 파일에서 RAGFLOW_IMAGE 변수를 적절히 업데이트한 후 docker compose를 사용하여 서버를 시작하십시오.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# Optional: use a stable tag (see releases: https://github.com/infiniflow/ragflow/releases)
|
# Optional: use a stable tag (see releases: https://github.com/infiniflow/ragflow/releases)
|
||||||
# 이 단계는 코드의 entrypoint.sh 파일이 Docker 이미지 버전과 일치하도록 보장합니다.
|
# 이 단계는 코드의 entrypoint.sh 파일이 Docker 이미지 버전과 일치하도록 보장합니다.
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<img alt="Badge Estático" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Badge Estático" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Última%20Relese" alt="Última Versão">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Última%20Relese" alt="Última Versão">
|
||||||
@ -86,6 +86,7 @@ Experimente nossa demo em [https://demo.ragflow.io](https://demo.ragflow.io).
|
|||||||
|
|
||||||
## 🔥 Últimas Atualizações
|
## 🔥 Últimas Atualizações
|
||||||
|
|
||||||
|
- 26-12-2025 Suporte à função 'Memória' para agentes de IA.
|
||||||
- 19-11-2025 Suporta Gemini 3 Pro.
|
- 19-11-2025 Suporta Gemini 3 Pro.
|
||||||
- 12-11-2025 Suporta a sincronização de dados do Confluence, S3, Notion, Discord e Google Drive.
|
- 12-11-2025 Suporta a sincronização de dados do Confluence, S3, Notion, Discord e Google Drive.
|
||||||
- 23-10-2025 Suporta MinerU e Docling como métodos de análise de documentos.
|
- 23-10-2025 Suporta MinerU e Docling como métodos de análise de documentos.
|
||||||
@ -187,12 +188,12 @@ Experimente nossa demo em [https://demo.ragflow.io](https://demo.ragflow.io).
|
|||||||
> Todas as imagens Docker são construídas para plataformas x86. Atualmente, não oferecemos imagens Docker para ARM64.
|
> Todas as imagens Docker são construídas para plataformas x86. Atualmente, não oferecemos imagens Docker para ARM64.
|
||||||
> Se você estiver usando uma plataforma ARM64, por favor, utilize [este guia](https://ragflow.io/docs/dev/build_docker_image) para construir uma imagem Docker compatível com o seu sistema.
|
> Se você estiver usando uma plataforma ARM64, por favor, utilize [este guia](https://ragflow.io/docs/dev/build_docker_image) para construir uma imagem Docker compatível com o seu sistema.
|
||||||
|
|
||||||
> O comando abaixo baixa a edição`v0.22.1` da imagem Docker do RAGFlow. Consulte a tabela a seguir para descrições de diferentes edições do RAGFlow. Para baixar uma edição do RAGFlow diferente da `v0.22.1`, atualize a variável `RAGFLOW_IMAGE` conforme necessário no **docker/.env** antes de usar `docker compose` para iniciar o servidor.
|
> O comando abaixo baixa a edição`v0.23.0` da imagem Docker do RAGFlow. Consulte a tabela a seguir para descrições de diferentes edições do RAGFlow. Para baixar uma edição do RAGFlow diferente da `v0.23.0`, atualize a variável `RAGFLOW_IMAGE` conforme necessário no **docker/.env** antes de usar `docker compose` para iniciar o servidor.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# Opcional: use uma tag estável (veja releases: https://github.com/infiniflow/ragflow/releases)
|
# Opcional: use uma tag estável (veja releases: https://github.com/infiniflow/ragflow/releases)
|
||||||
# Esta etapa garante que o arquivo entrypoint.sh no código corresponda à versão da imagem do Docker.
|
# Esta etapa garante que o arquivo entrypoint.sh no código corresponda à versão da imagem do Docker.
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
||||||
@ -85,15 +85,16 @@
|
|||||||
|
|
||||||
## 🔥 近期更新
|
## 🔥 近期更新
|
||||||
|
|
||||||
- 2025-11-19 支援 Gemini 3 Pro.
|
- 2025-12-26 支援AI代理的「記憶」功能。
|
||||||
|
- 2025-11-19 支援 Gemini 3 Pro。
|
||||||
- 2025-11-12 支援從 Confluence、S3、Notion、Discord、Google Drive 進行資料同步。
|
- 2025-11-12 支援從 Confluence、S3、Notion、Discord、Google Drive 進行資料同步。
|
||||||
- 2025-10-23 支援 MinerU 和 Docling 作為文件解析方法。
|
- 2025-10-23 支援 MinerU 和 Docling 作為文件解析方法。
|
||||||
- 2025-10-15 支援可編排的資料管道。
|
- 2025-10-15 支援可編排的資料管道。
|
||||||
- 2025-08-08 支援 OpenAI 最新的 GPT-5 系列模型。
|
- 2025-08-08 支援 OpenAI 最新的 GPT-5 系列模型。
|
||||||
- 2025-08-01 支援 agentic workflow 和 MCP
|
- 2025-08-01 支援 agentic workflow 和 MCP。
|
||||||
- 2025-05-23 為 Agent 新增 Python/JS 程式碼執行器元件。
|
- 2025-05-23 為 Agent 新增 Python/JS 程式碼執行器元件。
|
||||||
- 2025-05-05 支援跨語言查詢。
|
- 2025-05-05 支援跨語言查詢。
|
||||||
- 2025-03-19 PDF和DOCX中的圖支持用多模態大模型去解析得到描述.
|
- 2025-03-19 PDF和DOCX中的圖支持用多模態大模型去解析得到描述。
|
||||||
- 2024-12-18 升級了 DeepDoc 的文檔佈局分析模型。
|
- 2024-12-18 升級了 DeepDoc 的文檔佈局分析模型。
|
||||||
- 2024-08-22 支援用 RAG 技術實現從自然語言到 SQL 語句的轉換。
|
- 2024-08-22 支援用 RAG 技術實現從自然語言到 SQL 語句的轉換。
|
||||||
|
|
||||||
@ -186,12 +187,12 @@
|
|||||||
> 所有 Docker 映像檔都是為 x86 平台建置的。目前,我們不提供 ARM64 平台的 Docker 映像檔。
|
> 所有 Docker 映像檔都是為 x86 平台建置的。目前,我們不提供 ARM64 平台的 Docker 映像檔。
|
||||||
> 如果您使用的是 ARM64 平台,請使用 [這份指南](https://ragflow.io/docs/dev/build_docker_image) 來建置適合您系統的 Docker 映像檔。
|
> 如果您使用的是 ARM64 平台,請使用 [這份指南](https://ragflow.io/docs/dev/build_docker_image) 來建置適合您系統的 Docker 映像檔。
|
||||||
|
|
||||||
> 執行以下指令會自動下載 RAGFlow Docker 映像 `v0.22.1`。請參考下表查看不同 Docker 發行版的說明。如需下載不同於 `v0.22.1` 的 Docker 映像,請在執行 `docker compose` 啟動服務之前先更新 **docker/.env** 檔案內的 `RAGFLOW_IMAGE` 變數。
|
> 執行以下指令會自動下載 RAGFlow Docker 映像 `v0.23.0`。請參考下表查看不同 Docker 發行版的說明。如需下載不同於 `v0.23.0` 的 Docker 映像,請在執行 `docker compose` 啟動服務之前先更新 **docker/.env** 檔案內的 `RAGFLOW_IMAGE` 變數。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# 可選:使用穩定版標籤(查看發佈:https://github.com/infiniflow/ragflow/releases)
|
# 可選:使用穩定版標籤(查看發佈:https://github.com/infiniflow/ragflow/releases)
|
||||||
# 此步驟確保程式碼中的 entrypoint.sh 檔案與 Docker 映像版本一致。
|
# 此步驟確保程式碼中的 entrypoint.sh 檔案與 Docker 映像版本一致。
|
||||||
|
|
||||||
|
|||||||
11
README_zh.md
11
README_zh.md
@ -22,7 +22,7 @@
|
|||||||
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
|
||||||
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.22.1">
|
<img src="https://img.shields.io/docker/pulls/infiniflow/ragflow?label=Docker%20Pulls&color=0db7ed&logo=docker&logoColor=white&style=flat-square" alt="docker pull infiniflow/ragflow:v0.23.0">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
<a href="https://github.com/infiniflow/ragflow/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
<img src="https://img.shields.io/github/v/release/infiniflow/ragflow?color=blue&label=Latest%20Release" alt="Latest Release">
|
||||||
@ -85,7 +85,8 @@
|
|||||||
|
|
||||||
## 🔥 近期更新
|
## 🔥 近期更新
|
||||||
|
|
||||||
- 2025-11-19 支持 Gemini 3 Pro.
|
- 2025-12-26 支持AI代理的“记忆”功能。
|
||||||
|
- 2025-11-19 支持 Gemini 3 Pro。
|
||||||
- 2025-11-12 支持从 Confluence、S3、Notion、Discord、Google Drive 进行数据同步。
|
- 2025-11-12 支持从 Confluence、S3、Notion、Discord、Google Drive 进行数据同步。
|
||||||
- 2025-10-23 支持 MinerU 和 Docling 作为文档解析方法。
|
- 2025-10-23 支持 MinerU 和 Docling 作为文档解析方法。
|
||||||
- 2025-10-15 支持可编排的数据管道。
|
- 2025-10-15 支持可编排的数据管道。
|
||||||
@ -93,7 +94,7 @@
|
|||||||
- 2025-08-01 支持 agentic workflow 和 MCP。
|
- 2025-08-01 支持 agentic workflow 和 MCP。
|
||||||
- 2025-05-23 Agent 新增 Python/JS 代码执行器组件。
|
- 2025-05-23 Agent 新增 Python/JS 代码执行器组件。
|
||||||
- 2025-05-05 支持跨语言查询。
|
- 2025-05-05 支持跨语言查询。
|
||||||
- 2025-03-19 PDF 和 DOCX 中的图支持用多模态大模型去解析得到描述.
|
- 2025-03-19 PDF 和 DOCX 中的图支持用多模态大模型去解析得到描述。
|
||||||
- 2024-12-18 升级了 DeepDoc 的文档布局分析模型。
|
- 2024-12-18 升级了 DeepDoc 的文档布局分析模型。
|
||||||
- 2024-08-22 支持用 RAG 技术实现从自然语言到 SQL 语句的转换。
|
- 2024-08-22 支持用 RAG 技术实现从自然语言到 SQL 语句的转换。
|
||||||
|
|
||||||
@ -187,12 +188,12 @@
|
|||||||
> 请注意,目前官方提供的所有 Docker 镜像均基于 x86 架构构建,并不提供基于 ARM64 的 Docker 镜像。
|
> 请注意,目前官方提供的所有 Docker 镜像均基于 x86 架构构建,并不提供基于 ARM64 的 Docker 镜像。
|
||||||
> 如果你的操作系统是 ARM64 架构,请参考[这篇文档](https://ragflow.io/docs/dev/build_docker_image)自行构建 Docker 镜像。
|
> 如果你的操作系统是 ARM64 架构,请参考[这篇文档](https://ragflow.io/docs/dev/build_docker_image)自行构建 Docker 镜像。
|
||||||
|
|
||||||
> 运行以下命令会自动下载 RAGFlow Docker 镜像 `v0.22.1`。请参考下表查看不同 Docker 发行版的描述。如需下载不同于 `v0.22.1` 的 Docker 镜像,请在运行 `docker compose` 启动服务之前先更新 **docker/.env** 文件内的 `RAGFLOW_IMAGE` 变量。
|
> 运行以下命令会自动下载 RAGFlow Docker 镜像 `v0.23.0`。请参考下表查看不同 Docker 发行版的描述。如需下载不同于 `v0.23.0` 的 Docker 镜像,请在运行 `docker compose` 启动服务之前先更新 **docker/.env** 文件内的 `RAGFLOW_IMAGE` 变量。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
|
|
||||||
# git checkout v0.22.1
|
# git checkout v0.23.0
|
||||||
# 可选:使用稳定版本标签(查看发布:https://github.com/infiniflow/ragflow/releases)
|
# 可选:使用稳定版本标签(查看发布:https://github.com/infiniflow/ragflow/releases)
|
||||||
# 这一步确保代码中的 entrypoint.sh 文件与 Docker 镜像的版本保持一致。
|
# 这一步确保代码中的 entrypoint.sh 文件与 Docker 镜像的版本保持一致。
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,7 @@ It consists of a server-side Service and a command-line client (CLI), both imple
|
|||||||
1. Ensure the Admin Service is running.
|
1. Ensure the Admin Service is running.
|
||||||
2. Install ragflow-cli.
|
2. Install ragflow-cli.
|
||||||
```bash
|
```bash
|
||||||
pip install ragflow-cli==0.22.1
|
pip install ragflow-cli==0.23.0
|
||||||
```
|
```
|
||||||
3. Launch the CLI client:
|
3. Launch the CLI client:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@ -16,14 +16,14 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import base64
|
import base64
|
||||||
from cmd import Cmd
|
|
||||||
|
|
||||||
from Cryptodome.PublicKey import RSA
|
|
||||||
from Cryptodome.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
|
|
||||||
from typing import Dict, List, Any
|
|
||||||
from lark import Lark, Transformer, Tree
|
|
||||||
import requests
|
|
||||||
import getpass
|
import getpass
|
||||||
|
from cmd import Cmd
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from Cryptodome.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
|
||||||
|
from Cryptodome.PublicKey import RSA
|
||||||
|
from lark import Lark, Transformer, Tree
|
||||||
|
|
||||||
GRAMMAR = r"""
|
GRAMMAR = r"""
|
||||||
start: command
|
start: command
|
||||||
@ -141,7 +141,6 @@ NUMBER: /[0-9]+/
|
|||||||
|
|
||||||
|
|
||||||
class AdminTransformer(Transformer):
|
class AdminTransformer(Transformer):
|
||||||
|
|
||||||
def start(self, items):
|
def start(self, items):
|
||||||
return items[0]
|
return items[0]
|
||||||
|
|
||||||
@ -149,7 +148,7 @@ class AdminTransformer(Transformer):
|
|||||||
return items[0]
|
return items[0]
|
||||||
|
|
||||||
def list_services(self, items):
|
def list_services(self, items):
|
||||||
result = {'type': 'list_services'}
|
result = {"type": "list_services"}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def show_service(self, items):
|
def show_service(self, items):
|
||||||
@ -236,11 +235,7 @@ class AdminTransformer(Transformer):
|
|||||||
action_list = items[1]
|
action_list = items[1]
|
||||||
resource = items[3]
|
resource = items[3]
|
||||||
role_name = items[6]
|
role_name = items[6]
|
||||||
return {
|
return {"type": "revoke_permission", "role_name": role_name, "resource": resource, "actions": action_list}
|
||||||
"type": "revoke_permission",
|
|
||||||
"role_name": role_name,
|
|
||||||
"resource": resource, "actions": action_list
|
|
||||||
}
|
|
||||||
|
|
||||||
def alter_user_role(self, items):
|
def alter_user_role(self, items):
|
||||||
user_name = items[2]
|
user_name = items[2]
|
||||||
@ -264,12 +259,12 @@ class AdminTransformer(Transformer):
|
|||||||
# handle quoted parameter
|
# handle quoted parameter
|
||||||
parsed_args = []
|
parsed_args = []
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if hasattr(arg, 'value'):
|
if hasattr(arg, "value"):
|
||||||
parsed_args.append(arg.value)
|
parsed_args.append(arg.value)
|
||||||
else:
|
else:
|
||||||
parsed_args.append(str(arg))
|
parsed_args.append(str(arg))
|
||||||
|
|
||||||
return {'type': 'meta', 'command': command_name, 'args': parsed_args}
|
return {"type": "meta", "command": command_name, "args": parsed_args}
|
||||||
|
|
||||||
def meta_command_name(self, items):
|
def meta_command_name(self, items):
|
||||||
return items[0]
|
return items[0]
|
||||||
@ -279,22 +274,22 @@ class AdminTransformer(Transformer):
|
|||||||
|
|
||||||
|
|
||||||
def encrypt(input_string):
|
def encrypt(input_string):
|
||||||
pub = '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB\n-----END PUBLIC KEY-----'
|
pub = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB\n-----END PUBLIC KEY-----"
|
||||||
pub_key = RSA.importKey(pub)
|
pub_key = RSA.importKey(pub)
|
||||||
cipher = Cipher_pkcs1_v1_5.new(pub_key)
|
cipher = Cipher_pkcs1_v1_5.new(pub_key)
|
||||||
cipher_text = cipher.encrypt(base64.b64encode(input_string.encode('utf-8')))
|
cipher_text = cipher.encrypt(base64.b64encode(input_string.encode("utf-8")))
|
||||||
return base64.b64encode(cipher_text).decode("utf-8")
|
return base64.b64encode(cipher_text).decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def encode_to_base64(input_string):
|
def encode_to_base64(input_string):
|
||||||
base64_encoded = base64.b64encode(input_string.encode('utf-8'))
|
base64_encoded = base64.b64encode(input_string.encode("utf-8"))
|
||||||
return base64_encoded.decode('utf-8')
|
return base64_encoded.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
class AdminCLI(Cmd):
|
class AdminCLI(Cmd):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.parser = Lark(GRAMMAR, start='start', parser='lalr', transformer=AdminTransformer())
|
self.parser = Lark(GRAMMAR, start="start", parser="lalr", transformer=AdminTransformer())
|
||||||
self.command_history = []
|
self.command_history = []
|
||||||
self.is_interactive = False
|
self.is_interactive = False
|
||||||
self.admin_account = "admin@ragflow.io"
|
self.admin_account = "admin@ragflow.io"
|
||||||
@ -312,7 +307,7 @@ class AdminCLI(Cmd):
|
|||||||
result = self.parse_command(command)
|
result = self.parse_command(command)
|
||||||
|
|
||||||
if isinstance(result, dict):
|
if isinstance(result, dict):
|
||||||
if 'type' in result and result.get('type') == 'empty':
|
if "type" in result and result.get("type") == "empty":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.execute_command(result)
|
self.execute_command(result)
|
||||||
@ -320,7 +315,7 @@ class AdminCLI(Cmd):
|
|||||||
if isinstance(result, Tree):
|
if isinstance(result, Tree):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if result.get('type') == 'meta' and result.get('command') in ['q', 'quit', 'exit']:
|
if result.get("type") == "meta" and result.get("command") in ["q", "quit", "exit"]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@ -338,7 +333,7 @@ class AdminCLI(Cmd):
|
|||||||
|
|
||||||
def parse_command(self, command_str: str) -> dict[str, str]:
|
def parse_command(self, command_str: str) -> dict[str, str]:
|
||||||
if not command_str.strip():
|
if not command_str.strip():
|
||||||
return {'type': 'empty'}
|
return {"type": "empty"}
|
||||||
|
|
||||||
self.command_history.append(command_str)
|
self.command_history.append(command_str)
|
||||||
|
|
||||||
@ -346,11 +341,11 @@ class AdminCLI(Cmd):
|
|||||||
result = self.parser.parse(command_str)
|
result = self.parser.parse(command_str)
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {'type': 'error', 'message': f'Parse error: {str(e)}'}
|
return {"type": "error", "message": f"Parse error: {str(e)}"}
|
||||||
|
|
||||||
def verify_admin(self, arguments: dict, single_command: bool):
|
def verify_admin(self, arguments: dict, single_command: bool):
|
||||||
self.host = arguments['host']
|
self.host = arguments["host"]
|
||||||
self.port = arguments['port']
|
self.port = arguments["port"]
|
||||||
print("Attempt to access server for admin login")
|
print("Attempt to access server for admin login")
|
||||||
url = f"http://{self.host}:{self.port}/api/v1/admin/login"
|
url = f"http://{self.host}:{self.port}/api/v1/admin/login"
|
||||||
|
|
||||||
@ -365,25 +360,21 @@ class AdminCLI(Cmd):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if single_command:
|
if single_command:
|
||||||
admin_passwd = arguments['password']
|
admin_passwd = arguments["password"]
|
||||||
else:
|
else:
|
||||||
admin_passwd = getpass.getpass(f"password for {self.admin_account}: ").strip()
|
admin_passwd = getpass.getpass(f"password for {self.admin_account}: ").strip()
|
||||||
try:
|
try:
|
||||||
self.admin_password = encrypt(admin_passwd)
|
self.admin_password = encrypt(admin_passwd)
|
||||||
response = self.session.post(url, json={'email': self.admin_account, 'password': self.admin_password})
|
response = self.session.post(url, json={"email": self.admin_account, "password": self.admin_password})
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
error_code = res_json.get('code', -1)
|
error_code = res_json.get("code", -1)
|
||||||
if error_code == 0:
|
if error_code == 0:
|
||||||
self.session.headers.update({
|
self.session.headers.update({"Content-Type": "application/json", "Authorization": response.headers["Authorization"], "User-Agent": "RAGFlow-CLI/0.23.0"})
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': response.headers['Authorization'],
|
|
||||||
'User-Agent': 'RAGFlow-CLI/0.22.1'
|
|
||||||
})
|
|
||||||
print("Authentication successful.")
|
print("Authentication successful.")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
error_message = res_json.get('message', 'Unknown error')
|
error_message = res_json.get("message", "Unknown error")
|
||||||
print(f"Authentication failed: {error_message}, try again")
|
print(f"Authentication failed: {error_message}, try again")
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
@ -403,10 +394,14 @@ class AdminCLI(Cmd):
|
|||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
# display latest status
|
# display latest status
|
||||||
heartbeats = sorted(v, key=lambda x: x["now"], reverse=True)
|
heartbeats = sorted(v, key=lambda x: x["now"], reverse=True)
|
||||||
task_executor_list.append({
|
task_executor_list.append(
|
||||||
"task_executor_name": k,
|
{
|
||||||
**heartbeats[0],
|
"task_executor_name": k,
|
||||||
} if heartbeats else {"task_executor_name": k})
|
**heartbeats[0],
|
||||||
|
}
|
||||||
|
if heartbeats
|
||||||
|
else {"task_executor_name": k}
|
||||||
|
)
|
||||||
return task_executor_list
|
return task_executor_list
|
||||||
|
|
||||||
def _print_table_simple(self, data):
|
def _print_table_simple(self, data):
|
||||||
@ -422,12 +417,7 @@ class AdminCLI(Cmd):
|
|||||||
col_widths = {}
|
col_widths = {}
|
||||||
|
|
||||||
def get_string_width(text):
|
def get_string_width(text):
|
||||||
half_width_chars = (
|
half_width_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\t\n\r"
|
||||||
" !\"#$%&'()*+,-./0123456789:;<=>?@"
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz{|}~"
|
|
||||||
"\t\n\r"
|
|
||||||
)
|
|
||||||
width = 0
|
width = 0
|
||||||
for char in text:
|
for char in text:
|
||||||
if char in half_width_chars:
|
if char in half_width_chars:
|
||||||
@ -439,7 +429,7 @@ class AdminCLI(Cmd):
|
|||||||
for col in columns:
|
for col in columns:
|
||||||
max_width = get_string_width(str(col))
|
max_width = get_string_width(str(col))
|
||||||
for item in data:
|
for item in data:
|
||||||
value_len = get_string_width(str(item.get(col, '')))
|
value_len = get_string_width(str(item.get(col, "")))
|
||||||
if value_len > max_width:
|
if value_len > max_width:
|
||||||
max_width = value_len
|
max_width = value_len
|
||||||
col_widths[col] = max(2, max_width)
|
col_widths[col] = max(2, max_width)
|
||||||
@ -457,16 +447,15 @@ class AdminCLI(Cmd):
|
|||||||
for item in data:
|
for item in data:
|
||||||
row = "|"
|
row = "|"
|
||||||
for col in columns:
|
for col in columns:
|
||||||
value = str(item.get(col, ''))
|
value = str(item.get(col, ""))
|
||||||
if get_string_width(value) > col_widths[col]:
|
if get_string_width(value) > col_widths[col]:
|
||||||
value = value[:col_widths[col] - 3] + "..."
|
value = value[: col_widths[col] - 3] + "..."
|
||||||
row += f" {value:<{col_widths[col] - (get_string_width(value) - len(value))}} |"
|
row += f" {value:<{col_widths[col] - (get_string_width(value) - len(value))}} |"
|
||||||
print(row)
|
print(row)
|
||||||
|
|
||||||
print(separator)
|
print(separator)
|
||||||
|
|
||||||
def run_interactive(self):
|
def run_interactive(self):
|
||||||
|
|
||||||
self.is_interactive = True
|
self.is_interactive = True
|
||||||
print("RAGFlow Admin command line interface - Type '\\?' for help, '\\q' to quit")
|
print("RAGFlow Admin command line interface - Type '\\?' for help, '\\q' to quit")
|
||||||
|
|
||||||
@ -483,7 +472,7 @@ class AdminCLI(Cmd):
|
|||||||
if isinstance(result, Tree):
|
if isinstance(result, Tree):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if result.get('type') == 'meta' and result.get('command') in ['q', 'quit', 'exit']:
|
if result.get("type") == "meta" and result.get("command") in ["q", "quit", "exit"]:
|
||||||
break
|
break
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@ -497,36 +486,30 @@ class AdminCLI(Cmd):
|
|||||||
self.execute_command(result)
|
self.execute_command(result)
|
||||||
|
|
||||||
def parse_connection_args(self, args: List[str]) -> Dict[str, Any]:
|
def parse_connection_args(self, args: List[str]) -> Dict[str, Any]:
|
||||||
parser = argparse.ArgumentParser(description='Admin CLI Client', add_help=False)
|
parser = argparse.ArgumentParser(description="Admin CLI Client", add_help=False)
|
||||||
parser.add_argument('-h', '--host', default='localhost', help='Admin service host')
|
parser.add_argument("-h", "--host", default="localhost", help="Admin service host")
|
||||||
parser.add_argument('-p', '--port', type=int, default=9381, help='Admin service port')
|
parser.add_argument("-p", "--port", type=int, default=9381, help="Admin service port")
|
||||||
parser.add_argument('-w', '--password', default='admin', type=str, help='Superuser password')
|
parser.add_argument("-w", "--password", default="admin", type=str, help="Superuser password")
|
||||||
parser.add_argument('command', nargs='?', help='Single command')
|
parser.add_argument("command", nargs="?", help="Single command")
|
||||||
try:
|
try:
|
||||||
parsed_args, remaining_args = parser.parse_known_args(args)
|
parsed_args, remaining_args = parser.parse_known_args(args)
|
||||||
if remaining_args:
|
if remaining_args:
|
||||||
command = remaining_args[0]
|
command = remaining_args[0]
|
||||||
return {
|
return {"host": parsed_args.host, "port": parsed_args.port, "password": parsed_args.password, "command": command}
|
||||||
'host': parsed_args.host,
|
|
||||||
'port': parsed_args.port,
|
|
||||||
'password': parsed_args.password,
|
|
||||||
'command': command
|
|
||||||
}
|
|
||||||
else:
|
else:
|
||||||
return {
|
return {
|
||||||
'host': parsed_args.host,
|
"host": parsed_args.host,
|
||||||
'port': parsed_args.port,
|
"port": parsed_args.port,
|
||||||
}
|
}
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
return {'error': 'Invalid connection arguments'}
|
return {"error": "Invalid connection arguments"}
|
||||||
|
|
||||||
def execute_command(self, parsed_command: Dict[str, Any]):
|
def execute_command(self, parsed_command: Dict[str, Any]):
|
||||||
|
|
||||||
command_dict: dict
|
command_dict: dict
|
||||||
if isinstance(parsed_command, Tree):
|
if isinstance(parsed_command, Tree):
|
||||||
command_dict = parsed_command.children[0]
|
command_dict = parsed_command.children[0]
|
||||||
else:
|
else:
|
||||||
if parsed_command['type'] == 'error':
|
if parsed_command["type"] == "error":
|
||||||
print(f"Error: {parsed_command['message']}")
|
print(f"Error: {parsed_command['message']}")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@ -534,56 +517,56 @@ class AdminCLI(Cmd):
|
|||||||
|
|
||||||
# print(f"Parsed command: {command_dict}")
|
# print(f"Parsed command: {command_dict}")
|
||||||
|
|
||||||
command_type = command_dict['type']
|
command_type = command_dict["type"]
|
||||||
|
|
||||||
match command_type:
|
match command_type:
|
||||||
case 'list_services':
|
case "list_services":
|
||||||
self._handle_list_services(command_dict)
|
self._handle_list_services(command_dict)
|
||||||
case 'show_service':
|
case "show_service":
|
||||||
self._handle_show_service(command_dict)
|
self._handle_show_service(command_dict)
|
||||||
case 'restart_service':
|
case "restart_service":
|
||||||
self._handle_restart_service(command_dict)
|
self._handle_restart_service(command_dict)
|
||||||
case 'shutdown_service':
|
case "shutdown_service":
|
||||||
self._handle_shutdown_service(command_dict)
|
self._handle_shutdown_service(command_dict)
|
||||||
case 'startup_service':
|
case "startup_service":
|
||||||
self._handle_startup_service(command_dict)
|
self._handle_startup_service(command_dict)
|
||||||
case 'list_users':
|
case "list_users":
|
||||||
self._handle_list_users(command_dict)
|
self._handle_list_users(command_dict)
|
||||||
case 'show_user':
|
case "show_user":
|
||||||
self._handle_show_user(command_dict)
|
self._handle_show_user(command_dict)
|
||||||
case 'drop_user':
|
case "drop_user":
|
||||||
self._handle_drop_user(command_dict)
|
self._handle_drop_user(command_dict)
|
||||||
case 'alter_user':
|
case "alter_user":
|
||||||
self._handle_alter_user(command_dict)
|
self._handle_alter_user(command_dict)
|
||||||
case 'create_user':
|
case "create_user":
|
||||||
self._handle_create_user(command_dict)
|
self._handle_create_user(command_dict)
|
||||||
case 'activate_user':
|
case "activate_user":
|
||||||
self._handle_activate_user(command_dict)
|
self._handle_activate_user(command_dict)
|
||||||
case 'list_datasets':
|
case "list_datasets":
|
||||||
self._handle_list_datasets(command_dict)
|
self._handle_list_datasets(command_dict)
|
||||||
case 'list_agents':
|
case "list_agents":
|
||||||
self._handle_list_agents(command_dict)
|
self._handle_list_agents(command_dict)
|
||||||
case 'create_role':
|
case "create_role":
|
||||||
self._create_role(command_dict)
|
self._create_role(command_dict)
|
||||||
case 'drop_role':
|
case "drop_role":
|
||||||
self._drop_role(command_dict)
|
self._drop_role(command_dict)
|
||||||
case 'alter_role':
|
case "alter_role":
|
||||||
self._alter_role(command_dict)
|
self._alter_role(command_dict)
|
||||||
case 'list_roles':
|
case "list_roles":
|
||||||
self._list_roles(command_dict)
|
self._list_roles(command_dict)
|
||||||
case 'show_role':
|
case "show_role":
|
||||||
self._show_role(command_dict)
|
self._show_role(command_dict)
|
||||||
case 'grant_permission':
|
case "grant_permission":
|
||||||
self._grant_permission(command_dict)
|
self._grant_permission(command_dict)
|
||||||
case 'revoke_permission':
|
case "revoke_permission":
|
||||||
self._revoke_permission(command_dict)
|
self._revoke_permission(command_dict)
|
||||||
case 'alter_user_role':
|
case "alter_user_role":
|
||||||
self._alter_user_role(command_dict)
|
self._alter_user_role(command_dict)
|
||||||
case 'show_user_permission':
|
case "show_user_permission":
|
||||||
self._show_user_permission(command_dict)
|
self._show_user_permission(command_dict)
|
||||||
case 'show_version':
|
case "show_version":
|
||||||
self._show_version(command_dict)
|
self._show_version(command_dict)
|
||||||
case 'meta':
|
case "meta":
|
||||||
self._handle_meta_command(command_dict)
|
self._handle_meta_command(command_dict)
|
||||||
case _:
|
case _:
|
||||||
print(f"Command '{command_type}' would be executed with API")
|
print(f"Command '{command_type}' would be executed with API")
|
||||||
@ -591,29 +574,29 @@ class AdminCLI(Cmd):
|
|||||||
def _handle_list_services(self, command):
|
def _handle_list_services(self, command):
|
||||||
print("Listing all services")
|
print("Listing all services")
|
||||||
|
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/services'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/services"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to get all services, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to get all services, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_show_service(self, command):
|
def _handle_show_service(self, command):
|
||||||
service_id: int = command['number']
|
service_id: int = command["number"]
|
||||||
print(f"Showing service: {service_id}")
|
print(f"Showing service: {service_id}")
|
||||||
|
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/services/{service_id}'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/services/{service_id}"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
res_data = res_json['data']
|
res_data = res_json["data"]
|
||||||
if 'status' in res_data and res_data['status'] == 'alive':
|
if "status" in res_data and res_data["status"] == "alive":
|
||||||
print(f"Service {res_data['service_name']} is alive, ")
|
print(f"Service {res_data['service_name']} is alive, ")
|
||||||
if isinstance(res_data['message'], str):
|
if isinstance(res_data["message"], str):
|
||||||
print(res_data['message'])
|
print(res_data["message"])
|
||||||
else:
|
else:
|
||||||
data = self._format_service_detail_table(res_data['message'])
|
data = self._format_service_detail_table(res_data["message"])
|
||||||
self._print_table_simple(data)
|
self._print_table_simple(data)
|
||||||
else:
|
else:
|
||||||
print(f"Service {res_data['service_name']} is down, {res_data['message']}")
|
print(f"Service {res_data['service_name']} is down, {res_data['message']}")
|
||||||
@ -621,47 +604,47 @@ class AdminCLI(Cmd):
|
|||||||
print(f"Fail to show service, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to show service, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_restart_service(self, command):
|
def _handle_restart_service(self, command):
|
||||||
service_id: int = command['number']
|
service_id: int = command["number"]
|
||||||
print(f"Restart service {service_id}")
|
print(f"Restart service {service_id}")
|
||||||
|
|
||||||
def _handle_shutdown_service(self, command):
|
def _handle_shutdown_service(self, command):
|
||||||
service_id: int = command['number']
|
service_id: int = command["number"]
|
||||||
print(f"Shutdown service {service_id}")
|
print(f"Shutdown service {service_id}")
|
||||||
|
|
||||||
def _handle_startup_service(self, command):
|
def _handle_startup_service(self, command):
|
||||||
service_id: int = command['number']
|
service_id: int = command["number"]
|
||||||
print(f"Startup service {service_id}")
|
print(f"Startup service {service_id}")
|
||||||
|
|
||||||
def _handle_list_users(self, command):
|
def _handle_list_users(self, command):
|
||||||
print("Listing all users")
|
print("Listing all users")
|
||||||
|
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to get all users, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to get all users, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_show_user(self, command):
|
def _handle_show_user(self, command):
|
||||||
username_tree: Tree = command['user_name']
|
username_tree: Tree = command["user_name"]
|
||||||
user_name: str = username_tree.children[0].strip("'\"")
|
user_name: str = username_tree.children[0].strip("'\"")
|
||||||
print(f"Showing user: {user_name}")
|
print(f"Showing user: {user_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
table_data = res_json['data']
|
table_data = res_json["data"]
|
||||||
table_data.pop('avatar')
|
table_data.pop("avatar")
|
||||||
self._print_table_simple(table_data)
|
self._print_table_simple(table_data)
|
||||||
else:
|
else:
|
||||||
print(f"Fail to get user {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to get user {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_drop_user(self, command):
|
def _handle_drop_user(self, command):
|
||||||
username_tree: Tree = command['user_name']
|
username_tree: Tree = command["user_name"]
|
||||||
user_name: str = username_tree.children[0].strip("'\"")
|
user_name: str = username_tree.children[0].strip("'\"")
|
||||||
print(f"Drop user: {user_name}")
|
print(f"Drop user: {user_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}"
|
||||||
response = self.session.delete(url)
|
response = self.session.delete(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
@ -670,13 +653,13 @@ class AdminCLI(Cmd):
|
|||||||
print(f"Fail to drop user, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to drop user, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_alter_user(self, command):
|
def _handle_alter_user(self, command):
|
||||||
user_name_tree: Tree = command['user_name']
|
user_name_tree: Tree = command["user_name"]
|
||||||
user_name: str = user_name_tree.children[0].strip("'\"")
|
user_name: str = user_name_tree.children[0].strip("'\"")
|
||||||
password_tree: Tree = command['password']
|
password_tree: Tree = command["password"]
|
||||||
password: str = password_tree.children[0].strip("'\"")
|
password: str = password_tree.children[0].strip("'\"")
|
||||||
print(f"Alter user: {user_name}, password: ******")
|
print(f"Alter user: {user_name}, password: ******")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/password'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/password"
|
||||||
response = self.session.put(url, json={'new_password': encrypt(password)})
|
response = self.session.put(url, json={"new_password": encrypt(password)})
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print(res_json["message"])
|
print(res_json["message"])
|
||||||
@ -684,32 +667,29 @@ class AdminCLI(Cmd):
|
|||||||
print(f"Fail to alter password, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to alter password, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_create_user(self, command):
|
def _handle_create_user(self, command):
|
||||||
user_name_tree: Tree = command['user_name']
|
user_name_tree: Tree = command["user_name"]
|
||||||
user_name: str = user_name_tree.children[0].strip("'\"")
|
user_name: str = user_name_tree.children[0].strip("'\"")
|
||||||
password_tree: Tree = command['password']
|
password_tree: Tree = command["password"]
|
||||||
password: str = password_tree.children[0].strip("'\"")
|
password: str = password_tree.children[0].strip("'\"")
|
||||||
role: str = command['role']
|
role: str = command["role"]
|
||||||
print(f"Create user: {user_name}, password: ******, role: {role}")
|
print(f"Create user: {user_name}, password: ******, role: {role}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users"
|
||||||
response = self.session.post(
|
response = self.session.post(url, json={"user_name": user_name, "password": encrypt(password), "role": role})
|
||||||
url,
|
|
||||||
json={'user_name': user_name, 'password': encrypt(password), 'role': role}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to create user {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to create user {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_activate_user(self, command):
|
def _handle_activate_user(self, command):
|
||||||
user_name_tree: Tree = command['user_name']
|
user_name_tree: Tree = command["user_name"]
|
||||||
user_name: str = user_name_tree.children[0].strip("'\"")
|
user_name: str = user_name_tree.children[0].strip("'\"")
|
||||||
activate_tree: Tree = command['activate_status']
|
activate_tree: Tree = command["activate_status"]
|
||||||
activate_status: str = activate_tree.children[0].strip("'\"")
|
activate_status: str = activate_tree.children[0].strip("'\"")
|
||||||
if activate_status.lower() in ['on', 'off']:
|
if activate_status.lower() in ["on", "off"]:
|
||||||
print(f"Alter user {user_name} activate status, turn {activate_status.lower()}.")
|
print(f"Alter user {user_name} activate status, turn {activate_status.lower()}.")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/activate'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/activate"
|
||||||
response = self.session.put(url, json={'activate_status': activate_status})
|
response = self.session.put(url, json={"activate_status": activate_status})
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print(res_json["message"])
|
print(res_json["message"])
|
||||||
@ -719,202 +699,182 @@ class AdminCLI(Cmd):
|
|||||||
print(f"Unknown activate status: {activate_status}.")
|
print(f"Unknown activate status: {activate_status}.")
|
||||||
|
|
||||||
def _handle_list_datasets(self, command):
|
def _handle_list_datasets(self, command):
|
||||||
username_tree: Tree = command['user_name']
|
username_tree: Tree = command["user_name"]
|
||||||
user_name: str = username_tree.children[0].strip("'\"")
|
user_name: str = username_tree.children[0].strip("'\"")
|
||||||
print(f"Listing all datasets of user: {user_name}")
|
print(f"Listing all datasets of user: {user_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/datasets'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/datasets"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
table_data = res_json['data']
|
table_data = res_json["data"]
|
||||||
for t in table_data:
|
for t in table_data:
|
||||||
t.pop('avatar')
|
t.pop("avatar")
|
||||||
self._print_table_simple(table_data)
|
self._print_table_simple(table_data)
|
||||||
else:
|
else:
|
||||||
print(f"Fail to get all datasets of {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to get all datasets of {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_list_agents(self, command):
|
def _handle_list_agents(self, command):
|
||||||
username_tree: Tree = command['user_name']
|
username_tree: Tree = command["user_name"]
|
||||||
user_name: str = username_tree.children[0].strip("'\"")
|
user_name: str = username_tree.children[0].strip("'\"")
|
||||||
print(f"Listing all agents of user: {user_name}")
|
print(f"Listing all agents of user: {user_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/agents'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name}/agents"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
table_data = res_json['data']
|
table_data = res_json["data"]
|
||||||
for t in table_data:
|
for t in table_data:
|
||||||
t.pop('avatar')
|
t.pop("avatar")
|
||||||
self._print_table_simple(table_data)
|
self._print_table_simple(table_data)
|
||||||
else:
|
else:
|
||||||
print(f"Fail to get all agents of {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to get all agents of {user_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _create_role(self, command):
|
def _create_role(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name: str = role_name_tree.children[0].strip("'\"")
|
role_name: str = role_name_tree.children[0].strip("'\"")
|
||||||
desc_str: str = ''
|
desc_str: str = ""
|
||||||
if 'description' in command:
|
if "description" in command:
|
||||||
desc_tree: Tree = command['description']
|
desc_tree: Tree = command["description"]
|
||||||
desc_str = desc_tree.children[0].strip("'\"")
|
desc_str = desc_tree.children[0].strip("'\"")
|
||||||
|
|
||||||
print(f"create role name: {role_name}, description: {desc_str}")
|
print(f"create role name: {role_name}, description: {desc_str}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles"
|
||||||
response = self.session.post(
|
response = self.session.post(url, json={"role_name": role_name, "description": desc_str})
|
||||||
url,
|
|
||||||
json={'role_name': role_name, 'description': desc_str}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to create role {role_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to create role {role_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _drop_role(self, command):
|
def _drop_role(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name: str = role_name_tree.children[0].strip("'\"")
|
role_name: str = role_name_tree.children[0].strip("'\"")
|
||||||
print(f"drop role name: {role_name}")
|
print(f"drop role name: {role_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}"
|
||||||
response = self.session.delete(url)
|
response = self.session.delete(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to drop role {role_name}, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to drop role {role_name}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _alter_role(self, command):
|
def _alter_role(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name: str = role_name_tree.children[0].strip("'\"")
|
role_name: str = role_name_tree.children[0].strip("'\"")
|
||||||
desc_tree: Tree = command['description']
|
desc_tree: Tree = command["description"]
|
||||||
desc_str: str = desc_tree.children[0].strip("'\"")
|
desc_str: str = desc_tree.children[0].strip("'\"")
|
||||||
|
|
||||||
print(f"alter role name: {role_name}, description: {desc_str}")
|
print(f"alter role name: {role_name}, description: {desc_str}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}"
|
||||||
response = self.session.put(
|
response = self.session.put(url, json={"description": desc_str})
|
||||||
url,
|
|
||||||
json={'description': desc_str}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"Fail to update role {role_name} with description: {desc_str}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
f"Fail to update role {role_name} with description: {desc_str}, code: {res_json['code']}, message: {res_json['message']}")
|
|
||||||
|
|
||||||
def _list_roles(self, command):
|
def _list_roles(self, command):
|
||||||
print("Listing all roles")
|
print("Listing all roles")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to list roles, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to list roles, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _show_role(self, command):
|
def _show_role(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name: str = role_name_tree.children[0].strip("'\"")
|
role_name: str = role_name_tree.children[0].strip("'\"")
|
||||||
print(f"show role: {role_name}")
|
print(f"show role: {role_name}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}/permission'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles/{role_name}/permission"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to list roles, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to list roles, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _grant_permission(self, command):
|
def _grant_permission(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
||||||
resource_tree: Tree = command['resource']
|
resource_tree: Tree = command["resource"]
|
||||||
resource_str: str = resource_tree.children[0].strip("'\"")
|
resource_str: str = resource_tree.children[0].strip("'\"")
|
||||||
action_tree_list: list = command['actions']
|
action_tree_list: list = command["actions"]
|
||||||
actions: list = []
|
actions: list = []
|
||||||
for action_tree in action_tree_list:
|
for action_tree in action_tree_list:
|
||||||
action_str: str = action_tree.children[0].strip("'\"")
|
action_str: str = action_tree.children[0].strip("'\"")
|
||||||
actions.append(action_str)
|
actions.append(action_str)
|
||||||
print(f"grant role_name: {role_name_str}, resource: {resource_str}, actions: {actions}")
|
print(f"grant role_name: {role_name_str}, resource: {resource_str}, actions: {actions}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles/{role_name_str}/permission'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles/{role_name_str}/permission"
|
||||||
response = self.session.post(
|
response = self.session.post(url, json={"actions": actions, "resource": resource_str})
|
||||||
url,
|
|
||||||
json={'actions': actions, 'resource': resource_str}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"Fail to grant role {role_name_str} with {actions} on {resource_str}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
f"Fail to grant role {role_name_str} with {actions} on {resource_str}, code: {res_json['code']}, message: {res_json['message']}")
|
|
||||||
|
|
||||||
def _revoke_permission(self, command):
|
def _revoke_permission(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
||||||
resource_tree: Tree = command['resource']
|
resource_tree: Tree = command["resource"]
|
||||||
resource_str: str = resource_tree.children[0].strip("'\"")
|
resource_str: str = resource_tree.children[0].strip("'\"")
|
||||||
action_tree_list: list = command['actions']
|
action_tree_list: list = command["actions"]
|
||||||
actions: list = []
|
actions: list = []
|
||||||
for action_tree in action_tree_list:
|
for action_tree in action_tree_list:
|
||||||
action_str: str = action_tree.children[0].strip("'\"")
|
action_str: str = action_tree.children[0].strip("'\"")
|
||||||
actions.append(action_str)
|
actions.append(action_str)
|
||||||
print(f"revoke role_name: {role_name_str}, resource: {resource_str}, actions: {actions}")
|
print(f"revoke role_name: {role_name_str}, resource: {resource_str}, actions: {actions}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/roles/{role_name_str}/permission'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/roles/{role_name_str}/permission"
|
||||||
response = self.session.delete(
|
response = self.session.delete(url, json={"actions": actions, "resource": resource_str})
|
||||||
url,
|
|
||||||
json={'actions': actions, 'resource': resource_str}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"Fail to revoke role {role_name_str} with {actions} on {resource_str}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
f"Fail to revoke role {role_name_str} with {actions} on {resource_str}, code: {res_json['code']}, message: {res_json['message']}")
|
|
||||||
|
|
||||||
def _alter_user_role(self, command):
|
def _alter_user_role(self, command):
|
||||||
role_name_tree: Tree = command['role_name']
|
role_name_tree: Tree = command["role_name"]
|
||||||
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
role_name_str: str = role_name_tree.children[0].strip("'\"")
|
||||||
user_name_tree: Tree = command['user_name']
|
user_name_tree: Tree = command["user_name"]
|
||||||
user_name_str: str = user_name_tree.children[0].strip("'\"")
|
user_name_str: str = user_name_tree.children[0].strip("'\"")
|
||||||
print(f"alter_user_role user_name: {user_name_str}, role_name: {role_name_str}")
|
print(f"alter_user_role user_name: {user_name_str}, role_name: {role_name_str}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name_str}/role'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name_str}/role"
|
||||||
response = self.session.put(
|
response = self.session.put(url, json={"role_name": role_name_str})
|
||||||
url,
|
|
||||||
json={'role_name': role_name_str}
|
|
||||||
)
|
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"Fail to alter user: {user_name_str} to role {role_name_str}, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
f"Fail to alter user: {user_name_str} to role {role_name_str}, code: {res_json['code']}, message: {res_json['message']}")
|
|
||||||
|
|
||||||
def _show_user_permission(self, command):
|
def _show_user_permission(self, command):
|
||||||
user_name_tree: Tree = command['user_name']
|
user_name_tree: Tree = command["user_name"]
|
||||||
user_name_str: str = user_name_tree.children[0].strip("'\"")
|
user_name_str: str = user_name_tree.children[0].strip("'\"")
|
||||||
print(f"show_user_permission user_name: {user_name_str}")
|
print(f"show_user_permission user_name: {user_name_str}")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/users/{user_name_str}/permission'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/users/{user_name_str}/permission"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"Fail to show user: {user_name_str} permission, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
f"Fail to show user: {user_name_str} permission, code: {res_json['code']}, message: {res_json['message']}")
|
|
||||||
|
|
||||||
def _show_version(self, command):
|
def _show_version(self, command):
|
||||||
print("show_version")
|
print("show_version")
|
||||||
url = f'http://{self.host}:{self.port}/api/v1/admin/version'
|
url = f"http://{self.host}:{self.port}/api/v1/admin/version"
|
||||||
response = self.session.get(url)
|
response = self.session.get(url)
|
||||||
res_json = response.json()
|
res_json = response.json()
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._print_table_simple(res_json['data'])
|
self._print_table_simple(res_json["data"])
|
||||||
else:
|
else:
|
||||||
print(f"Fail to show version, code: {res_json['code']}, message: {res_json['message']}")
|
print(f"Fail to show version, code: {res_json['code']}, message: {res_json['message']}")
|
||||||
|
|
||||||
def _handle_meta_command(self, command):
|
def _handle_meta_command(self, command):
|
||||||
meta_command = command['command']
|
meta_command = command["command"]
|
||||||
args = command.get('args', [])
|
args = command.get("args", [])
|
||||||
|
|
||||||
if meta_command in ['?', 'h', 'help']:
|
if meta_command in ["?", "h", "help"]:
|
||||||
self.show_help()
|
self.show_help()
|
||||||
elif meta_command in ['q', 'quit', 'exit']:
|
elif meta_command in ["q", "quit", "exit"]:
|
||||||
print("Goodbye!")
|
print("Goodbye!")
|
||||||
else:
|
else:
|
||||||
print(f"Meta command '{meta_command}' with args {args}")
|
print(f"Meta command '{meta_command}' with args {args}")
|
||||||
@ -950,16 +910,16 @@ def main():
|
|||||||
cli = AdminCLI()
|
cli = AdminCLI()
|
||||||
|
|
||||||
args = cli.parse_connection_args(sys.argv)
|
args = cli.parse_connection_args(sys.argv)
|
||||||
if 'error' in args:
|
if "error" in args:
|
||||||
print("Error: Invalid connection arguments")
|
print("Error: Invalid connection arguments")
|
||||||
return
|
return
|
||||||
|
|
||||||
if 'command' in args:
|
if "command" in args:
|
||||||
if 'password' not in args:
|
if "password" not in args:
|
||||||
print("Error: password is missing")
|
print("Error: password is missing")
|
||||||
return
|
return
|
||||||
if cli.verify_admin(args, single_command=True):
|
if cli.verify_admin(args, single_command=True):
|
||||||
command: str = args['command']
|
command: str = args["command"]
|
||||||
# print(f"Run single command: {command}")
|
# print(f"Run single command: {command}")
|
||||||
cli.run_single_command(command)
|
cli.run_single_command(command)
|
||||||
else:
|
else:
|
||||||
@ -974,5 +934,5 @@ def main():
|
|||||||
cli.cmdloop()
|
cli.cmdloop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ragflow-cli"
|
name = "ragflow-cli"
|
||||||
version = "0.22.1"
|
version = "0.23.0"
|
||||||
description = "Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring. "
|
description = "Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring. "
|
||||||
authors = [{ name = "Lynn", email = "lynn_inf@hotmail.com" }]
|
authors = [{ name = "Lynn", email = "lynn_inf@hotmail.com" }]
|
||||||
license = { text = "Apache License, Version 2.0" }
|
license = { text = "Apache License, Version 2.0" }
|
||||||
|
|||||||
2
admin/client/uv.lock
generated
2
admin/client/uv.lock
generated
@ -196,7 +196,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ragflow-cli"
|
name = "ragflow-cli"
|
||||||
version = "0.22.1"
|
version = "0.23.0"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "beartype" },
|
{ name = "beartype" },
|
||||||
|
|||||||
@ -128,11 +128,11 @@ ADMIN_SVR_HTTP_PORT=9381
|
|||||||
SVR_MCP_PORT=9382
|
SVR_MCP_PORT=9382
|
||||||
|
|
||||||
# The RAGFlow Docker image to download. v0.22+ doesn't include embedding models.
|
# The RAGFlow Docker image to download. v0.22+ doesn't include embedding models.
|
||||||
RAGFLOW_IMAGE=infiniflow/ragflow:v0.22.1
|
RAGFLOW_IMAGE=infiniflow/ragflow:v0.23.0
|
||||||
|
|
||||||
# If you cannot download the RAGFlow Docker image:
|
# If you cannot download the RAGFlow Docker image:
|
||||||
# RAGFLOW_IMAGE=swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:v0.22.1
|
# RAGFLOW_IMAGE=swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:v0.23.0
|
||||||
# RAGFLOW_IMAGE=registry.cn-hangzhou.aliyuncs.com/infiniflow/ragflow:v0.22.1
|
# RAGFLOW_IMAGE=registry.cn-hangzhou.aliyuncs.com/infiniflow/ragflow:v0.23.0
|
||||||
#
|
#
|
||||||
# - For the `nightly` edition, uncomment either of the following:
|
# - For the `nightly` edition, uncomment either of the following:
|
||||||
# RAGFLOW_IMAGE=swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:nightly
|
# RAGFLOW_IMAGE=swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:nightly
|
||||||
|
|||||||
@ -77,7 +77,7 @@ The [.env](./.env) file contains important environment variables for Docker.
|
|||||||
- `SVR_HTTP_PORT`
|
- `SVR_HTTP_PORT`
|
||||||
The port used to expose RAGFlow's HTTP API service to the host machine, allowing **external** access to the service running inside the Docker container. Defaults to `9380`.
|
The port used to expose RAGFlow's HTTP API service to the host machine, allowing **external** access to the service running inside the Docker container. Defaults to `9380`.
|
||||||
- `RAGFLOW-IMAGE`
|
- `RAGFLOW-IMAGE`
|
||||||
The Docker image edition. Defaults to `infiniflow/ragflow:v0.22.1`. The RAGFlow Docker image does not include embedding models.
|
The Docker image edition. Defaults to `infiniflow/ragflow:v0.23.0`. The RAGFlow Docker image does not include embedding models.
|
||||||
|
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
|
|||||||
@ -99,7 +99,7 @@ RAGFlow utilizes MinIO as its object storage solution, leveraging its scalabilit
|
|||||||
- `SVR_HTTP_PORT`
|
- `SVR_HTTP_PORT`
|
||||||
The port used to expose RAGFlow's HTTP API service to the host machine, allowing **external** access to the service running inside the Docker container. Defaults to `9380`.
|
The port used to expose RAGFlow's HTTP API service to the host machine, allowing **external** access to the service running inside the Docker container. Defaults to `9380`.
|
||||||
- `RAGFLOW-IMAGE`
|
- `RAGFLOW-IMAGE`
|
||||||
The Docker image edition. Defaults to `infiniflow/ragflow:v0.22.1` (the RAGFlow Docker image without embedding models).
|
The Docker image edition. Defaults to `infiniflow/ragflow:v0.23.0` (the RAGFlow Docker image without embedding models).
|
||||||
|
|
||||||
:::tip NOTE
|
:::tip NOTE
|
||||||
If you cannot download the RAGFlow Docker image, try the following mirrors.
|
If you cannot download the RAGFlow Docker image, try the following mirrors.
|
||||||
|
|||||||
@ -47,7 +47,7 @@ After building the infiniflow/ragflow:nightly image, you are ready to launch a f
|
|||||||
|
|
||||||
1. Edit Docker Compose Configuration
|
1. Edit Docker Compose Configuration
|
||||||
|
|
||||||
Open the `docker/.env` file. Find the `RAGFLOW_IMAGE` setting and change the image reference from `infiniflow/ragflow:v0.22.1` to `infiniflow/ragflow:nightly` to use the pre-built image.
|
Open the `docker/.env` file. Find the `RAGFLOW_IMAGE` setting and change the image reference from `infiniflow/ragflow:v0.23.0` to `infiniflow/ragflow:nightly` to use the pre-built image.
|
||||||
|
|
||||||
|
|
||||||
2. Launch the Service
|
2. Launch the Service
|
||||||
|
|||||||
@ -133,7 +133,7 @@ See [Run retrieval test](./run_retrieval_test.md) for details.
|
|||||||
|
|
||||||
## Search for dataset
|
## Search for dataset
|
||||||
|
|
||||||
As of RAGFlow v0.22.1, the search feature is still in a rudimentary form, supporting only dataset search by name.
|
As of RAGFlow v0.23.0, the search feature is still in a rudimentary form, supporting only dataset search by name.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@ -87,4 +87,4 @@ RAGFlow's file management allows you to download an uploaded file:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
> As of RAGFlow v0.22.1, bulk download is not supported, nor can you download an entire folder.
|
> As of RAGFlow v0.23.0, bulk download is not supported, nor can you download an entire folder.
|
||||||
|
|||||||
@ -46,7 +46,7 @@ The Admin CLI and Admin Service form a client-server architectural suite for RAG
|
|||||||
2. Install ragflow-cli.
|
2. Install ragflow-cli.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install ragflow-cli==0.22.1
|
pip install ragflow-cli==0.23.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Launch the CLI client:
|
3. Launch the CLI client:
|
||||||
|
|||||||
@ -60,16 +60,16 @@ To upgrade RAGFlow, you must upgrade **both** your code **and** your Docker imag
|
|||||||
git pull
|
git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Switch to the latest, officially published release, e.g., `v0.22.1`:
|
3. Switch to the latest, officially published release, e.g., `v0.23.0`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git checkout -f v0.22.1
|
git checkout -f v0.23.0
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Update **ragflow/docker/.env**:
|
4. Update **ragflow/docker/.env**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
RAGFLOW_IMAGE=infiniflow/ragflow:v0.22.1
|
RAGFLOW_IMAGE=infiniflow/ragflow:v0.23.0
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Update the RAGFlow image and restart RAGFlow:
|
5. Update the RAGFlow image and restart RAGFlow:
|
||||||
@ -90,10 +90,10 @@ No, you do not need to. Upgrading RAGFlow in itself will *not* remove your uploa
|
|||||||
1. From an environment with Internet access, pull the required Docker image.
|
1. From an environment with Internet access, pull the required Docker image.
|
||||||
2. Save the Docker image to a **.tar** file.
|
2. Save the Docker image to a **.tar** file.
|
||||||
```bash
|
```bash
|
||||||
docker save -o ragflow.v0.22.1.tar infiniflow/ragflow:v0.22.1
|
docker save -o ragflow.v0.23.0.tar infiniflow/ragflow:v0.23.0
|
||||||
```
|
```
|
||||||
3. Copy the **.tar** file to the target server.
|
3. Copy the **.tar** file to the target server.
|
||||||
4. Load the **.tar** file into Docker:
|
4. Load the **.tar** file into Docker:
|
||||||
```bash
|
```bash
|
||||||
docker load -i ragflow.v0.22.1.tar
|
docker load -i ragflow.v0.23.0.tar
|
||||||
```
|
```
|
||||||
|
|||||||
@ -46,7 +46,7 @@ This section provides instructions on setting up the RAGFlow server on Linux. If
|
|||||||
|
|
||||||
`vm.max_map_count`. This value sets the maximum number of memory map areas a process may have. Its default value is 65530. While most applications require fewer than a thousand maps, reducing this value can result in abnormal behaviors, and the system will throw out-of-memory errors when a process reaches the limitation.
|
`vm.max_map_count`. This value sets the maximum number of memory map areas a process may have. Its default value is 65530. While most applications require fewer than a thousand maps, reducing this value can result in abnormal behaviors, and the system will throw out-of-memory errors when a process reaches the limitation.
|
||||||
|
|
||||||
RAGFlow v0.22.1 uses Elasticsearch or [Infinity](https://github.com/infiniflow/infinity) for multiple recall. Setting the value of `vm.max_map_count` correctly is crucial to the proper functioning of the Elasticsearch component.
|
RAGFlow v0.23.0 uses Elasticsearch or [Infinity](https://github.com/infiniflow/infinity) for multiple recall. Setting the value of `vm.max_map_count` correctly is crucial to the proper functioning of the Elasticsearch component.
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="linux"
|
defaultValue="linux"
|
||||||
@ -186,7 +186,7 @@ This section provides instructions on setting up the RAGFlow server on Linux. If
|
|||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/infiniflow/ragflow.git
|
$ git clone https://github.com/infiniflow/ragflow.git
|
||||||
$ cd ragflow/docker
|
$ cd ragflow/docker
|
||||||
$ git checkout -f v0.22.1
|
$ git checkout -f v0.23.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Use the pre-built Docker images and start up the server:
|
3. Use the pre-built Docker images and start up the server:
|
||||||
@ -202,7 +202,7 @@ This section provides instructions on setting up the RAGFlow server on Linux. If
|
|||||||
|
|
||||||
| RAGFlow image tag | Image size (GB) | Stable? |
|
| RAGFlow image tag | Image size (GB) | Stable? |
|
||||||
| ------------------- | --------------- | ------------------------ |
|
| ------------------- | --------------- | ------------------------ |
|
||||||
| v0.22.1 | ≈2 | Stable release |
|
| v0.23.0 | ≈2 | Stable release |
|
||||||
| nightly | ≈2 | _Unstable_ nightly build |
|
| nightly | ≈2 | _Unstable_ nightly build |
|
||||||
|
|
||||||
```mdx-code-block
|
```mdx-code-block
|
||||||
|
|||||||
@ -56,7 +56,7 @@ env:
|
|||||||
ragflow:
|
ragflow:
|
||||||
image:
|
image:
|
||||||
repository: infiniflow/ragflow
|
repository: infiniflow/ragflow
|
||||||
tag: v0.22.1
|
tag: v0.23.0
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
pullSecrets: []
|
pullSecrets: []
|
||||||
# Optional service configuration overrides
|
# Optional service configuration overrides
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ragflow"
|
name = "ragflow"
|
||||||
version = "0.22.1"
|
version = "0.23.0"
|
||||||
description = "[RAGFlow](https://ragflow.io/) is an open-source RAG (Retrieval-Augmented Generation) engine based on deep document understanding. It offers a streamlined RAG workflow for businesses of any scale, combining LLM (Large Language Models) to provide truthful question-answering capabilities, backed by well-founded citations from various complex formatted data."
|
description = "[RAGFlow](https://ragflow.io/) is an open-source RAG (Retrieval-Augmented Generation) engine based on deep document understanding. It offers a streamlined RAG workflow for businesses of any scale, combining LLM (Large Language Models) to provide truthful question-answering capabilities, backed by well-founded citations from various complex formatted data."
|
||||||
authors = [{ name = "Zhichang Yu", email = "yuzhichang@gmail.com" }]
|
authors = [{ name = "Zhichang Yu", email = "yuzhichang@gmail.com" }]
|
||||||
license-files = ["LICENSE"]
|
license-files = ["LICENSE"]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ragflow-sdk"
|
name = "ragflow-sdk"
|
||||||
version = "0.22.1"
|
version = "0.23.0"
|
||||||
description = "Python client sdk of [RAGFlow](https://github.com/infiniflow/ragflow). RAGFlow is an open-source RAG (Retrieval-Augmented Generation) engine based on deep document understanding."
|
description = "Python client sdk of [RAGFlow](https://github.com/infiniflow/ragflow). RAGFlow is an open-source RAG (Retrieval-Augmented Generation) engine based on deep document understanding."
|
||||||
authors = [{ name = "Zhichang Yu", email = "yuzhichang@gmail.com" }]
|
authors = [{ name = "Zhichang Yu", email = "yuzhichang@gmail.com" }]
|
||||||
license = { text = "Apache License, Version 2.0" }
|
license = { text = "Apache License, Version 2.0" }
|
||||||
|
|||||||
2
sdk/python/uv.lock
generated
2
sdk/python/uv.lock
generated
@ -353,7 +353,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ragflow-sdk"
|
name = "ragflow-sdk"
|
||||||
version = "0.22.1"
|
version = "0.23.0"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "beartype" },
|
{ name = "beartype" },
|
||||||
|
|||||||
Reference in New Issue
Block a user