Compare commits

..

1801 Commits

Author SHA1 Message Date
94181a990b Refa: knowledge_graph chunk method is deprecated (#7220)
### What problem does this PR solve?

The knowledge_graph chunk method is deprecated and should no longer be
used. #7184.

### Type of change

- [x] Refactoring
2025-04-23 13:01:46 +08:00
03672df691 Docs: update for v0.18.0 (#7223)
### What problem does this PR solve?

update for v0.18.0

### Type of change

- [x] Documentation Update
2025-04-23 12:02:50 +08:00
e9669e7fb1 Updated v0.18.0 release notes (#7221)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-04-23 11:12:14 +08:00
9a1ac8020d v0.18.0 release notes (#7185)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update
2025-04-23 10:41:58 +08:00
b44bbd11b8 Feat: Upload document #3221 (#7209)
### What problem does this PR solve?

Feat: Upload document #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-23 10:39:09 +08:00
1e91318445 Added a RAPTOR guide (#7211)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2025-04-22 20:56:30 +08:00
f35ff65c36 [BREAKING CHANGE] GET to POST: enhance kb list capability (#7205)
### What problem does this PR solve?

Enhance capability of `list_kbs`.

Breaking change: change method from `GET` to `POST`.

### Type of change

- [x] Refactoring
- [x] Enhancement with breaking change
2025-04-22 17:54:12 +08:00
ba0e363d5a Feat: Show the owner of this knowledge base on the list card. #3221 (#7204)
### What problem does this PR solve?

Feat: Show the owner of this knowledge base on the list card. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 16:46:13 +08:00
dde8c26feb Feat: Even if the knowledge base has slices, the chunk method can be changed #7115 (#7201)
### What problem does this PR solve?

Feat: Even if the knowledge base has slices, the chunk method can be
changed #7115

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 16:04:49 +08:00
64dd187498 Fix: Knowledge Graph Extraction Conflict Between Dataset-Level and File-Specific Configurations #7198 (#7199)
### What problem does this PR solve?

Fix: Knowledge Graph Extraction Conflict Between Dataset-Level and
File-Specific Configurations #7198

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-22 16:00:55 +08:00
67dee2d74e Fix: fix retrieval tesing wrong pagination (#7174)
### What problem does this PR solve?

Fix retrieval testing wrong pagination. #7171 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-04-22 15:16:04 +08:00
bcac195a0c Put the knowledge base list related hooks into use-knowledge-request.ts #3221 (#7197)
### What problem does this PR solve?

Put the knowledge base list related hooks into use-knowledge-request.ts
#3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 15:01:35 +08:00
8fca8faa7d Feat: Move langfuse configuration to api page #6155 (#7196)
### What problem does this PR solve?

Feat: Move langfuse configuration to api page #6155

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 14:08:20 +08:00
1cc17eb611 Feat: Filter the knowledge base list using owner #3221 (#7191)
### What problem does this PR solve?

Feat: Filter the knowledge base list using owner #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 13:44:41 +08:00
c8194f5fd0 refactor: Update Redis configuration to use StatefulSet instead of deployment with pvc (#7187)
### What problem does this PR solve?

This PR changes Redis to be a statefulset. In some situation when we
Redis pod gets rescheduled to another Node, it gets stuck in pending
state due to the PVC attached to another Kubernetes node.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [X] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-22 12:53:30 +08:00
f2c9ffc056 Fix: KG search issue. (#7186)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-22 12:10:30 +08:00
10432a1be7 Refa: Optimize pptx shape extraction to reduce content loss (#6703)
### What problem does this PR solve?

When parsing pptx files, some shapes do not contain the `shape_type`
attribute, which causes the original code to throw an exception during
extraction, leading to failure in content extraction. This optimization
introduces handling logic for such anomalous shapes, providing a safer
and more robust processing mechanism.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [x] Performance Improvement
- [ ] Other (please describe):
2025-04-22 10:16:24 +08:00
e7f83b13ca Feat: Rename a dataset #3221 (#7162)
### What problem does this PR solve?

Feat: Rename a dataset #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 10:09:41 +08:00
ad220a0a3c Feat: add mcp self-host mode (#7157)
### What problem does this PR solve?

Add mcp self-host mode, a complement of #7084.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-04-22 10:04:21 +08:00
91c5a5c08f Docs: add mcp self-host mode (#7163)
### What problem does this PR solve?

Add mcp self-host mode documentation, a complement of #7141.

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-04-22 10:03:38 +08:00
8362ab405c Fix: don't modify S3 file name when not using prefix_path (#7152)
### What problem does this PR solve?

Hello, I encountered a problem when trying to use a S3 backend
(seaweedfs) for storage in RAGFlow: when calling
`STORAGE_IMPL.get("bucket", "key")`, the actual request sent to S3 is
`bucket/bucket/key`, causing a `NoSuchKey` error.

I compared the code in `s3_conn.py` to `minio_conn.py` and
`oss_conn.py`, then decided to remove the `else` branch in
`use_prefix_path` method, and it works. I didn't configure `prefix_path`
or `bucket` in `s3` section of the `service_conf.yaml`.

I think this is a bug, but not sure.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-21 11:55:50 +08:00
68b9dae6c0 Feat: mcp server (#7084)
### What problem does this PR solve?

Add MCP support with a client example.

Issue link: #4344

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-04-21 09:43:20 +08:00
9b956ac1a9 Docs: MCP server (#7141)
### What problem does this PR solve?

Documentation for MCP server

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-04-21 09:42:32 +08:00
d4dbdfb61d feat: Recover pending tasks while pod restart. (#7073)
### What problem does this PR solve?

If you deploy Ragflow using Kubernetes, the hostname will change during
a rolling update. This causes the consumer name of the task executor to
change, making it impossible to schedule tasks that were previously in a
pending state.
To address this, I introduced a recovery task that scans these pending
messages and re-publishes them, allowing the tasks to continue being
processed.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: liuzhenghua-jk <liuzhenghua-jk@360shuke.com>
2025-04-19 16:18:51 +08:00
487aed419e Fix: cite disfunction for G component. (#7117)
### What problem does this PR solve?

#7097

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-18 18:05:26 +08:00
8b8a2f2949 fix(nursery): Fix Closure Trap Issues in Trio Concurrent Tasks (#7106)
## Problem Description
Multiple files in the RAGFlow project contain closure trap issues when
using lambda functions with `trio.open_nursery()`. This problem causes
concurrent tasks created in loops to reference the same variable,
resulting in all tasks processing the same data (the data from the last
iteration) rather than each task processing its corresponding data from
the loop.

## Issue Details
When using a `lambda` to create a closure function and passing it to
`nursery.start_soon()` within a loop, the lambda function captures a
reference to the loop variable rather than its value. For example:

```python
# Problematic code
async with trio.open_nursery() as nursery:
    for d in docs:
        nursery.start_soon(lambda: doc_keyword_extraction(chat_mdl, d, topn))
```

In this pattern, when concurrent tasks begin execution, `d` has already
become the value after the loop ends (typically the last element),
causing all tasks to use the same data.

## Fix Solution
Changed the way concurrent tasks are created with `nursery.start_soon()`
by leveraging Trio's API design to directly pass the function and its
arguments separately:

```python
# Fixed code
async with trio.open_nursery() as nursery:
    for d in docs:
        nursery.start_soon(doc_keyword_extraction, chat_mdl, d, topn)
```

This way, each task uses the parameter values at the time of the
function call, rather than references captured through closures.

## Fixed Files
Fixed closure traps in the following files:

1. `rag/svr/task_executor.py`: 3 fixes, involving document keyword
extraction, question generation, and tag processing
2. `rag/raptor.py`: 1 fix, involving document summarization
3. `graphrag/utils.py`: 2 fixes, involving graph node and edge
processing
4. `graphrag/entity_resolution.py`: 2 fixes, involving entity resolution
and graph node merging
5. `graphrag/general/mind_map_extractor.py`: 2 fixes, involving document
processing
6. `graphrag/general/extractor.py`: 3 fixes, involving content
processing and graph node/edge merging
7. `graphrag/general/community_reports_extractor.py`: 1 fix, involving
community report extraction

## Potential Impact
This fix resolves a serious concurrency issue that could have caused:
- Data processing errors (processing duplicate data)
- Performance degradation (all tasks working on the same data)
- Inconsistent results (some data not being processed)

After the fix, all concurrent tasks should correctly process their
respective data, improving system correctness and reliability.
2025-04-18 18:00:20 +08:00
42e236f464 Feat: Rendering a search test list with real data #3221 (#7138)
### What problem does this PR solve?

Feat: Rendering a search test list with real data #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-18 16:29:41 +08:00
1b4016317e fix bug chunking:expected string or bytes-like object (#7116)
… bytes-like object

### What problem does this PR solve?
fix bug #6990 internal server error ehile chunking:expected string or
bytes-like object
_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: unknown <taoshi.ln@chinatelecom.cn>
2025-04-18 14:42:36 +08:00
b1798bafb0 Fix: handle sometimes graph index will miss explanation (#7127)
### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/7053

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-18 14:24:36 +08:00
86f76df586 Feat: Retrieval test #3221 (#7121)
### What problem does this PR solve?

Feat: Retrieval test #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-17 19:03:55 +08:00
db82c15de4 Fix: wrong “available” property when list chunk (#7093)
### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/7083

Internal due to when returning from ES, fields changed to str, so the
bool conversion does not work as expected.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-17 17:17:35 +08:00
627fd002ae Update utils.py (#7091)
### What problem does this PR solve?

when there are multiple entities, the variable `v` may be a list, which
will lead to this error:
```
| File "/mnt/d/wrf/ragflow/ragflow/graphrag/utils.py", line 59, in replace_all
| result = result.replace(f"{{{k}}}", v)
| TypeError: replace() argument 2 must be str, not list
```
this pr assign this `v` to be a str

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-17 17:17:09 +08:00
9e7d052c8d Fix: knowledge graph resolution with infinity raise error tokenizing in specific situations (#7048)
### What problem does this PR solve?

When running graph resolution with infinity, if single quotation marks
appeared in the entities name that to be delete, an error tokenizing of
sqlglot might occur after calling infinity.

For example:
```
INFINITY delete table ragflow_xxx, filter knowledge_graph_kwd IN ('entity') AND entity_kwd IN ('86 IMAGES FROM PREVIOUS CONTESTS', 'ADAM OPTIMIZATION', 'BACKGROUND'ESTIMATION')
```
may raise error
```
Error tokenizing 'TS', 'ADAM OPTIMIZATION', 'BACKGROUND'ESTIMATION''
```
and make the document parsing failed。

Replace one single quotation mark with double single quotation marks can
let sqlglot tokenize the entity name correctly.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-17 16:15:21 +08:00
d9927f5185 Fix: Error in sending placeholder words in Chinese and Chinese-Traditional (#7094)
### What problem does this PR solve?

The assistant message placeholder is incorrect, I have finished
modifying both Chinese and traditional Chinese characters

### Type of change


- [x] Bug Fix
2025-04-17 15:52:03 +08:00
5d253e0a34 Fix: pymysql.err.InterfaceError: (0, '') during long time streaming chat responses (#6548) (#7057)
### Related Issue:
https://github.com/infiniflow/ragflow/issues/6548

### Related PR:
https://github.com/infiniflow/ragflow/pull/6861


### Environment:
Commit version:
[[48730e0](48730e00a8)]

### Bug Description:
Unexpected `pymysql.err.InterfaceError: (0, '') `when using Peewee +
PyMySQL + PooledMySQLDatabase after a long-running `chat streamly`
operation.

This is a common issue with Peewee + PyMySQL + connection pooling: you
end up using a connection that was silently closed by the server, but
Peewee doesn't realize it's dead.

**I found that the error only occurs during longer streaming outputs**
and is unrelated to the database connection context, so it's likely
because:

- The prolonged streaming response caused the database connection to
time out

- The original database connection might have been disconnected by the
server during the streaming process

### Why This Happens
This error happens even when using `@DB.connection_context() `after the
stream is done. After investigation, I found this is caused by MySQL
connection pools that appear to be open but are actually dead (expired
due to` wait_timeout`).

1. `@DB.connection_context()` (as a decorator or context manager) pulls
a connection from the pool.

2. If this connection was idle and expired on the MySQL server (e.g.,
due to `wait_timeout`), but not closed in Python, it will still be
considered “open” (`DB.is_closed() == False`).

3. The real error will occur only when I execute a SQL command (such as
.`get_or_none()`), and PyMySQL tries to send it to the server via a
broken socket.


### Changes Made:

1. I implemented manual connection checks before executing SQL:
```
    try:
        DB.execute_sql("SELECT 1")
    except Exception:
        print("Connection dead, reconnecting...")
        DB.close()
        DB.connect()
```
2. Delayed the token count update until after the streaming response is
completed to ensure the streaming output isn't interrupted by database
operations.
```
        total_tokens = 0 
        for txt in chat_streamly(system, history, gen_conf):
            if isinstance(txt, int):
                total_tokens = txt
......
                break
......
        if total_tokens > 0:
            if not TenantLLMService.increase_usage(self.tenant_id, self.llm_type, txt, self.llm_name):
                logging.error("LLMBundle.chat_streamly can't update token usage for {}/CHAT llm_name: {}, content: {}".format(self.tenant_id, self.llm_name, txt))
```
2025-04-16 19:15:35 +08:00
de5727f90a Fix: Files being parsed are not allowed to be deleted in batches #7065 (#7066)
### What problem does this PR solve?

Fix: Files being parsed are not allowed to be deleted in batches #7065

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-16 16:46:24 +08:00
9c2dd70839 Miscellaneous editorial updates. (#7047)
### What problem does this PR solve?

#6910 

### Type of change

- [x] Documentation Update
2025-04-16 10:31:10 +08:00
e0e78112a2 Docs: Change DELETE to POST in Related Questions curl example (#7054)
### What problem does this PR solve?

docs(api): Fix request method in Related Questions example (DELETE→POST)

### Type of change

- [x] Documentation Update
2025-04-16 10:29:59 +08:00
48730e00a8 Docs: updates. (#7042)
### What problem does this PR solve?

#7019

### Type of change

- [x] Documentation Update
2025-04-15 17:45:52 +08:00
e5f9d148e7 Test: Added test cases for Delete Sessions With Chat Assistant HTTP API (#7025)
### What problem does this PR solve?

cover [Delete chat assistant's
sessions](https://ragflow.io/docs/dev/http_api_reference#delete-chat-assistants-sessions)
endpoints

### Type of change

- [x] Add test cases
2025-04-15 14:54:26 +08:00
f6b280e372 Fix: when remove document do not delete the file in storage if the source is not knowledge base (#7005)
### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/6905

When deleting a document will check before removing it from storage

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-15 12:11:41 +08:00
5af2d57086 Refa. (#7022)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2025-04-15 10:20:33 +08:00
7a34159737 Fix: add fallback for bad citation output (#7014)
### What problem does this PR solve?

Add fallback for bad citation output. #6948

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-15 09:33:53 +08:00
b1fa5a0754 Fix Helm Ingress template (#7018)
### What problem does this PR solve?

Fix Helm Ingress template; Trying to access a global variable within a
loop
Fix #6191

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-15 09:19:37 +08:00
018ff4dd0a Refa: update llms (#7007)
### What problem does this PR solve?

Update LLM models

### Type of change

- [x] Refactoring
2025-04-15 09:19:07 +08:00
ed352710ec Feat: Remove the rotation state of the button that parses the document #7008 (#7009)
### What problem does this PR solve?

Feat: Remove the rotation state of the button that parses the document
#7008
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-14 18:50:11 +08:00
0a0c1edce3 Docs: readme updating. (#7002)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-04-14 14:45:37 +08:00
18eb76f6b8 Fix: The selected state of the TreeView node cannot be seen on Mac #7000 (#7001)
### What problem does this PR solve?

Fix: The selected state of the TreeView node cannot be seen on Mac #7000

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-14 14:23:26 +08:00
ed5f81b02e Fix: abnormal cell mergeing. (#6991)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-14 11:00:11 +08:00
23c5ce48d1 Fix update_progress issue (#6992)
### What problem does this PR solve?

Fix update_progress issue introduced by #6975 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-14 10:23:13 +08:00
de766ba628 Fix: Fix api page translation issue. #3221 (#6993)
### What problem does this PR solve?

Fix: Fix api page translation issue. #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-14 10:23:00 +08:00
5aae73c230 Make error messages during PPT processing clearer. (#6980)
### What problem does this PR solve?

Sometimes a slide may trigger a Proxy error (ArgumentException:
Parameter is not valid) due to issues in the original file, and this
error message can be confusing for users.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe):
2025-04-14 10:10:20 +08:00
b578451e6a docs: update Docker build commands to specify platform as linux/amd64 (#6977)
### What problem does this PR solve?

Considering the ragflow_deps image is only available for `linux/amd64`
platform, if we try to run the docker build commands in ,macOS for
instance, without the platform flag, we get an error due to the
different platform. Specifying the platform in the docker build command
fixes this issue.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [X] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-14 10:07:39 +08:00
53c653b099 fix RAGFlowPdfParser AttributeError: 'PdfReader' object has no attribute 'close' err (#6859)
i use PdfParser in local(refer to this case:
https://github.com/infiniflow/ragflow/blob/main/rag/app/paper.py) like
this:
```
import re
import openpyxl

from ragflow.api.db import ParserType
from ragflow.rag.nlp import rag_tokenizer, tokenize, tokenize_table, add_positions, bullets_category, \
    title_frequency, \
    tokenize_chunks
from ragflow.rag.utils import num_tokens_from_string
from ragflow.deepdoc.parser import PdfParser, ExcelParser, DocxParser,PlainParser


def logger(prog=None, msg=""):
    print(msg)


class Pdf(PdfParser):
    def __init__(self):
        self.model_speciess = ParserType.MANUAL.value
        super().__init__()

    def __call__(self, filename, binary=None, from_page=0,
                 to_page=100000, zoomin=3, callback=None):
        from timeit import default_timer as timer
        start = timer()
        callback(msg="OCR is running...")

        self.__images__(
            filename if not binary else binary,
            zoomin,
            from_page,
            to_page,
            callback
        )
        callback(msg="OCR finished.")
        print("OCR:", timer() - start)
   
        self._layouts_rec(zoomin)
        callback(0.65, "Layout analysis finished.")
        print("layouts:", timer() - start)

        self._table_transformer_job(zoomin)
        callback(0.67, "Table analysis finished.")


        self._text_merge()
        tbls = self._extract_table_figure(True, zoomin, True, True)
        self._concat_downward()  
        self._filter_forpages()   
        callback(0.68, "Text merging finished")

        # clean mess
        for b in self.boxes:
            b["text"] = re.sub(r"([\t  ]|\u3000){2,}", " ", b["text"].strip())

        return [(b["text"], b.get("layout_no", ""), self.get_position(b, zoomin))
                for i, b in enumerate(self.boxes)], tbls


```

show err like this:
```
  File "xxxxx/third_party/ragflow/deepdoc/parser/pdf_parser.py", line 1039, in __images__
    self.pdf.close()
AttributeError: 'PdfReader' object has no attribute 'close'
```

i found ragflow source code use
`pdfplumber.open`(https://github.com/infiniflow/ragflow/blob/main/deepdoc/parser/pdf_parser.py#L1007C28-L1007C43)

and replace` self.pdf `with ` pdf2_read` (from pypdf import PdfReader as
pdf2_read)in line 1024
(https://github.com/infiniflow/ragflow/blob/main/deepdoc/parser/pdf_parser.py#L1024)
```
self.pdf = pdf2_read
```


---
and I found that `pdfplumber` can be used in this way:
```
file_path="xxx.pdf"
res = pdfplumber.open(file_path)
res.close()
```

but `pypdf.PdfReader` source code do not has `close` func, source code
use like this

```
 with open(stream, "rb") as fh:
         stream = BytesIO(fh.read())
          self._stream_opened = True
```
> https://github.com/py-pdf/pypdf/blob/main/pypdf/_reader.py#L156

so I moved the `self.pdf.close` function call and fixed this problem
hoping to help the project😊
2025-04-14 09:40:13 +08:00
b70abe52b2 Fix: Ensure lock is released in update_progress using context manager (#6975)
ragflow: v0.17 also encountered this problem. #1453 The task table shows
that the actual task has been completed. Since the process_msg of the
task is not synchronized to the document table, there is no progress
update on the page.
This may be caused by the lock not being released when the exception
occurs.

ragflow:v0.17同样碰到这个问题, 看task表实际任务已经完成,由于没有把task的process_msg同步给document表,
所以在页面看没有进度更新。
可能是这里异常时没有释放锁导致的。

```/api/ragflow_server.py
def update_progress():
    lock_value = str(uuid.uuid4())
    redis_lock = RedisDistributedLock("update_progress", lock_value=lock_value, timeout=60)
    logging.info(f"update_progress lock_value: {lock_value}")
    while not stop_event.is_set():
        try:
            if redis_lock.acquire():
                DocumentService.update_progress()
                redis_lock.release()
            stop_event.wait(6)
        except Exception:
            logging.exception("update_progress exception")
++       if redis_lock.acquired:
++               redis_lock.release()
```
2025-04-11 20:46:19 +08:00
98670c3755 Fix: KB update_time changed whenever system relaunched (#6959)
### What problem does this PR solve?

Fix KB update_time changed whenever system relaunched. #6953 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-11 20:10:49 +08:00
9b789c2ae9 Test: Added test cases for Update Session With Chat Assistant HTTP API (#6968)
### What problem does this PR solve?

cover [Update chat assistant's
sessions](https://ragflow.io/docs/dev/http_api_reference#update-chat-assistants-session)
endpoints

### Type of change

- [x] Update test cases
2025-04-11 20:10:24 +08:00
ffb9f01bea Test: Update test cases for PR 6906 ISSUE 6875 (#6971)
### What problem does this PR solve?

PR #6906 ISSUE #6875

### Type of change

- [ ] Update test cases
2025-04-11 20:09:44 +08:00
ed7244f5f5 Fix: Delete unused pages (#6973)
### What problem does this PR solve?

Fix: Delete unused pages

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-11 20:06:58 +08:00
e54c0e39b5 fix bug [ERROR][Exception]: 8 vs. 9 (#6955)
### What problem does this PR solve?

Sometimes, the **s** in **chunks (s, a)** is an empty string. This
causes the condition **if s and len(a) > 0** in the line **chunks = [(s,
a) for s, a in chunks if s and len(a) > 0]** to fail, which changes the
length of the new chunks. As a result, the final assertion **assert
len(chunks) - end == n_clusters, "{} vs. {}".format(len(chunks) - end,
n_clusters)** fails and raises a confusing error like 7 vs. 8

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-11 17:01:49 +08:00
056ea68e52 Fix: In the dark night theme, the message input box is not displayed correctly. #6950 (#6951)
### What problem does this PR solve?

Fix: In the dark night theme, the message input box is not displayed
correctly. #6950

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-11 12:37:16 +08:00
d9266ed65a Fix: incorrect total chunks count in retrieval function after similarity filtering (#6741) (#6932)
### Related Issue:
https://github.com/infiniflow/ragflow/issues/6741

### Environment:
Using nightly version
Commit version:
[[6051abb](6051abb4a3)]

### Bug Description:
The retrieval function in rag/nlp/search.py returns the original total
chunks number
even after chunks are filtered by similarity_threshold. This creates
inconsistency
between the actual returned chunks and the reported total.

### Changes Made:
Added code to count how many search results actually meet or exceed the
configured similarity threshold
Positioned the calculation after the doc_ids conditional logic to ensure
special cases are handled correctly
Updated the ranks["total"] value to store this filtered count instead of
using the raw search result count
Using NumPy leverages optimized C-level batch operations to optimize
speed
2025-04-11 12:31:36 +08:00
6051abb4a3 Miscellaneous UI updates (#6947)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-04-10 20:09:46 +08:00
4b125f0ffe Feat: Add translation text to the prompt word of the generate operator to distinguish it from the prompt word of the knowledge base #6934 (#6935)
### What problem does this PR solve?

Feat: Add translation text to the prompt word of the generate operator
to distinguish it from the prompt word of the knowledge base #6934

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-10 19:24:04 +08:00
43cf321942 Added similarity scores in reference chunks (#6918)
- Returning 3 similarity scores to the chat completion's `reference`
field. It gives the user more transparency and added flexibility to
display/rerank the reference when needed

Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
2025-04-10 19:17:45 +08:00
9283e91aa0 Fix: remove deprecated permission field (#6912)
### What problem does this PR solve?

Fix: remove deprecated KB updating `permission` field. #6911 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-10 18:56:41 +08:00
dc59aba132 Test: Added test cases for List Sessions With Chat Assistant HTTP API (#6938)
### What problem does this PR solve?

cover [List chat assistant's
sessions](https://ragflow.io/docs/dev/http_api_reference#list-chat-assistants-sessions)
endpoints

### Type of change

- [x] Update test cases
2025-04-10 17:31:01 +08:00
8fb5edd927 Test: Update test cases for PR 6906 (#6929)
### What problem does this PR solve?

PR #6906

### Type of change

- [x] Update test cases
2025-04-10 12:28:56 +08:00
3bb1e012e6 Fix: assistant deleteion issue. (#6906)
### What problem does this PR solve?

#6875

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-09 20:29:40 +08:00
22758a2763 Test: Update test cases for PR 6888 ISSUE 6876 (#6907)
### What problem does this PR solve?

PR #6888 ISSUE #6876

### Type of change

- [x] Update test case
2025-04-09 20:29:29 +08:00
a008b38cf5 Fix: local variable referenced before assignment (#6909)
### What problem does this PR solve?

Fix: local variable referenced before assignment. #6803 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-09 20:29:12 +08:00
d0897312ac Added a guide on setting chat variables (#6904)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2025-04-09 19:32:25 +08:00
aa99c6b896 Fix delete duplicate assistant (#6888)
### What problem does this PR solve?

resolve this issue:https://github.com/infiniflow/ragflow/issues/6876

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-04-09 19:10:08 +08:00
ae107f31d9 Test: Added test cases for Create Session With Chat Assistant HTTP API (#6902)
### What problem does this PR solve?

cover [create session with chat
assistant](https://ragflow.io/docs/dev/http_api_reference#create-session-with-chat-assistant)
endpoints

### Type of change

- [x] add test cases
2025-04-09 17:21:48 +08:00
9d9f2dacd2 fix Conversation roles must alternate user/assistant/user/assistant/... bug (#6880)
### What problem does this PR solve?

The old logic filters out all assistant messages from messages, which,
in multi-turn conversations, results in only user messages being
retained. This leads to an error in locally deployed models:
Conversation roles must alternate user/assistant/user/assistant/...

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-09 17:21:27 +08:00
08bc5d3521 Feat: Install sonner library #3221 (#6898)
### What problem does this PR solve?

Feat: Install sonner library #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-09 17:21:01 +08:00
6e7fb75618 Fix: handle waiting tasks when upstream is switch/categorize/relevant and normal path fails (#6874)
### What problem does this PR solve?

Fix the issue where waiting tasks couldn't be processed when upstream
components were "switch", "categorize", or "relevant" and the normal
processing path couldn't continue.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-04-09 12:37:21 +08:00
c26c38ee12 Test: Added test cases for Delete Chat Assistants HTTP API (#6879)
### What problem does this PR solve?

cover [delete chat
assistants](https://ragflow.io/docs/dev/http_api_reference#delete-chat-assistants)
endpoints

### Type of change

- [x] add test cases
2025-04-08 18:53:02 +08:00
dc2c74b249 Feat: add primitive support for function calls (#6840)
### What problem does this PR solve?

This PR introduces ​**​primitive support for function calls​**​,
enabling the system to handle basic function call capabilities.
However, this feature is currently experimental and ​**​not yet enabled
for general use​**​, as it is only supported by a subset of models,
namely, Qwen and OpenAI models.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-04-08 16:09:03 +08:00
a20439bf81 fix: add exception handling for get_by_id method (#6861)
### What problem does this PR solve?

Fixes #6548 

Add exception handling to prevent exceptions from propagating back to
the web, which may lead to failure in displaying conversation content.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: cm <caiming@sict.ac.cn>
2025-04-08 16:06:57 +08:00
a1fb32908d Fix: Error message is incorrect when updating chat name #6850 (#6851)
### What problem does this PR solve?

#6850 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-07 17:13:17 +08:00
0b89458eb8 Test: Added test cases for Update Chat Assistant HTTP API (#6843)
### What problem does this PR solve?

cover [update chat
assistant](https://ragflow.io/docs/v0.17.2/http_api_reference#update-chat-assistant)
endpoints

### Type of change

- [x] add test cases
2025-04-07 15:04:23 +08:00
14a3efd756 Fix: docx image exceptions. (#6839)
### What problem does this PR solve?

Close #6784

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-07 12:33:34 +08:00
d64c6870bb Fix:When parsing documents with graph, an error occurred:[ERROR][Exception]: 'method' (#6836)
[When parsing documents with graph, an error
occurred:[ERROR][Exception]: 'method']
(https://github.com/infiniflow/ragflow/issues/6835)
### What problem does this PR solve?

Close #6786

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: cm <caiming@sict.ac.cn>
2025-04-07 12:29:25 +08:00
dc87c91f9d Update broken discord link (#6841)
### Type of change

- [x] Documentation Update
2025-04-07 12:18:43 +08:00
d4574ffb49 Fix: improve Dockerfile build for China (#6812)
### What problem does this PR solve?
This PR addresses the build and dependency issues faced by developers in
regions with poor connectivity to official Ubuntu repositories and
standard dependency sources. Currently, developers in these regions
experience slow or failed Docker builds and dependency downloads,
significantly impacting development efficiency.

### Type of change
- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

The changes include:
1. Modified Dockerfile to use alternative Ubuntu mirrors with better
connectivity in affected regions
2. Added a new script (download_deps_CN.py) that provides
region-specific alternative download links for dependencies
2025-04-07 11:58:46 +08:00
5a8c479ff3 Miscellaneous editorial updates (#6805)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2025-04-07 09:33:55 +08:00
c6b26a3159 update some setting to README_zh.md (#6737)
### What problem does this PR solve?
#6731 #6722 
_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Documentation Update

---------

Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2025-04-03 22:12:49 +08:00
2a5ad74ac6 Test: Update test cases for #6800 (#6804)
### What problem does this PR solve?

update test case for PR #6800 issue #6539

### Type of change

- [x] update test cases
2025-04-03 21:22:41 +08:00
2caf15b24c Refa: trival. (#6802)
### What problem does this PR solve?


### Type of change


- [x] Refactoring
2025-04-03 19:01:24 +08:00
f49588756e Feat: Load the dialog page, prohibit calling the dialog/get interface #6798 (#6799)
### What problem does this PR solve?

Feat: Load the dialog page, prohibit calling the dialog/get interface
#6798

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-03 18:04:40 +08:00
57e760883e Fix: update chunk, empty question issue. (#6800)
### What problem does this PR solve?

fix issue #6539, refer to pr #6405

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-03 18:04:19 +08:00
b213e88cca Test: Added test cases for List Chat Assistants HTTP API (#6792)
### What problem does this PR solve?

cover [list chat
assistant](https://ragflow.io/docs/v0.17.2/http_api_reference#list-chat-assistants)
endpoints

### Type of change

- [x] add test cases
2025-04-03 17:22:23 +08:00
e8f46c9207 Fix: missing redis pvc storageclass in helm (#6788)
fix redis pvc in helm deployment

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-03 16:55:47 +08:00
cded812b97 Feat: add OpenAI compatible API for agent (#6329)
### What problem does this PR solve?
add openai agent
_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-04-03 16:51:37 +08:00
2acb02366e Feat: Clarify the use of OpenAI-API-compatible #6782 (#6783)
### What problem does this PR solve?

Feat: Clarify the use of OpenAI-API-compatible #6782

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-03 11:38:21 +08:00
9ecc78feeb Refa: copywriting refinement. (#6779)
### What problem does this PR solve?

Close #6762

### Type of change

- [x] Refactoring
2025-04-03 11:38:02 +08:00
fdc410e743 Fix set_graph on non-existing edge (#6777)
### What problem does this PR solve?

Fix set_graph on non-existing edge

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-03 11:09:04 +08:00
5b5558300a Feat: add gemini-2.5-pro-exp-03-25 (#6774)
### What problem does this PR solve?

#6733

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-04-03 10:48:58 +08:00
b5918e7158 Docs: Fix for issue #6713 (#6775)
### What problem does this PR solve?

update fo issue #6713

### Type of change

- [x] Documentation Update
2025-04-03 10:19:58 +08:00
58f8026632 Test: Update test cases for PR #6643 (#6766)
### What problem does this PR solve?

Update test cases for PR #6643 issue #6607

### Type of change

- [x] update test cases
2025-04-03 10:10:40 +08:00
a73fbc61ff Fix: Handle the case of deleting empty blocks. Update the relevant message (#6643)
…gic to return the correct deletion message. Add handling for empty
arrays to ensure no errors occur during the deletion operation. Update
the test cases to verify the new logic.

### What problem does this PR solve?

fix this bug:https://github.com/infiniflow/ragflow/issues/6607

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-04-02 19:20:17 +08:00
0d1c5fdd2f Test: Added test cases for Create Chat Assistant HTTP API (#6763)
### What problem does this PR solve?

cover [create chat
assistant](https://ragflow.io/docs/v0.17.2/http_api_reference#create-chat-assistant)
endpoints

### Type of change

- [x] add test cases
2025-04-02 18:49:59 +08:00
6c77ef5a5e Docs(api): align default values in create chat assistant HTTP API dos with implementation (#6764)
### What problem does this PR solve?

align default values in create chat assistant HTTP API dos with
implementation.
llm.presence_penalty  0.2 -> 0.4
prompt.top_n  8->6


### Type of change

- [x] Documentation Update
2025-04-02 18:48:31 +08:00
e7a2a4b7ff Log llm response on exception (#6750)
### What problem does this PR solve?

Log llm response on exception

### Type of change

- [x] Refactoring
2025-04-02 17:10:57 +08:00
724a36fcdb Fix: Issue with Markdown Code Blocks Breaking Frontend Layout #5789 (#6758)
### What problem does this PR solve?

Fix: Issue with Markdown Code Blocks Breaking Frontend Layout #5789

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-02 16:28:55 +08:00
9ce6521582 Fix: Change the field name of the document ID from "documents" to "do… (#6753)
…cument_ids" to maintain consistency.

### What problem does this PR solve?

Close #6752

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-04-02 15:52:52 +08:00
160bf4ccb3 Fix: The file upload prompt indicates "No authorization." #6516 (#6756)
### What problem does this PR solve?

Fix: The file upload prompt indicates "No authorization." #6516

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-02 15:52:35 +08:00
aa25d09b0c Fix: Using the Enter key does not send a complete message #6754 (#6755)
### What problem does this PR solve?

Fix: Using the Enter key does not send a complete message #6754

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-02 15:02:16 +08:00
2471a6e115 Updated max_tokens descriptions (#6751)
### What problem does this PR solve?

#6721 

### Type of change


- [x] Documentation Update
2025-04-02 13:56:55 +08:00
fc02929946 Feat: Support deleting knowledge graph #6747 (#6748)
### What problem does this PR solve?

Feat: Support deleting knowledge graph #6747

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-02 11:20:37 +08:00
3ae1e9e3c4 Test: Skip test case for PR 6443 (#6724)
### What problem does this PR solve?

Skip test case for PR #6443

### Type of change

- [x] update test cases
2025-04-02 10:41:01 +08:00
117f18240d Feat: Add a notification logic to the team member invite feature #6610 (#6729)
### What problem does this PR solve?
Feat: Add a notification logic to the team member invite feature #6610

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-02 09:15:13 +08:00
31296ad70f Miscellaneous doc updates and refactored team management doc. (#6730)
### What problem does this PR solve?

#5576, #6672

### Type of change


- [x] Documentation and UI Update
2025-04-01 19:05:30 +08:00
132eae9d5b Feat: Interrupt streaming #6515 (#6723)
### What problem does this PR solve?

Feat: Interrupt streaming #6515
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-01 17:26:54 +08:00
ead5f7aba9 Fix infinite recursion in RagTokenizer when processing repetitive characters (#6109)
### What problem does this PR solve?
fix #6085 
RagTokenizer's dfs_() function falls into infinite recursion when
processing text with repetitive Chinese characters (e.g.,
"一一一一一十一十一十一..." or "一一一一一一十十十十十十十二十二十二..."), causing memory leaks.
### Type of change
Implemented three optimizations to the dfs_() function:
1.Added memoization with _memo dictionary to cache computed results
2.Added recursion depth limiting with _depth parameter (max 10 levels)
3.Implemented special handling for repetitive character sequences
- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-04-01 13:59:52 +08:00
58e6e7b668 Test: Refactor test fixtures and test cases (#6709)
### What problem does this PR solve?

 Refactor test fixtures and test cases

### Type of change

- [ ] Refactoring test cases
2025-04-01 13:39:07 +08:00
20b8ccd1e9 Hotfix ece5903 (#6705)
I'm really sorry, I found that in graphrag/general/extractor.py under
def __call__, the line change.removed_nodes.extend(nodes[1:]) causes an
AttributeError: 'set' object has no attribute 'extend'. Could you please
merge the branch e666528 again? I made some modifications.
2025-04-01 12:06:28 +08:00
d0dca16fee Feat: Allows users to search for models in the model selection drop-down box #3221 (#6708)
### What problem does this PR solve?

Feat: Allows users to search for models in the model selection drop-down
box #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-04-01 11:53:48 +08:00
fc21dd0a4a Feat: add qwq-plus-latest (#6702)
### What problem does this PR solve?

#6697

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-04-01 11:06:03 +08:00
61c0dfab70 Fix: Email error. (#6701)
### What problem does this PR solve?

#6695

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-04-01 10:37:04 +08:00
67330833af fix: correct [AttributeError: 'set' object has no attribute 'nodes' T… (#6699)
### Related Issue: 
https://github.com/infiniflow/ragflow/issues/6653 

### Environment:
Using nightly version [ece5903]

Elasticsearch database

Thanks for the review! My fault! I realize my initial testing wasn't
passed.

In graphrag/entity_resolution.py 
 `sub_connect_graph` is a set like` {'HELLO', 'Hi', 'How are you'}`, 
Neither accessing `.nodes` nor `.nodes()` will work, **it still causes
`AttributeError: 'set' object has no attribute 'nodes'`**

In graphrag/general/extractor.py  
The `list.extend() `method performs an in-place operation, directly
modifying the original list and returning ‘None’ rather than the
modified list.
Neither accessing
`sorted(set(node0_attrs[attr].extend(node1_attrs.get(attr, []))))` nor
`sorted(set(node0_attrs[attr].extend(node1_attrs[attr])))` will work,
**it still causes `TypeError: 'NoneType' object is not iterable`**
### Type of change

- [ ] Bug Fix AttributeError: graphrag/entity_resolution.py 
- [ ] Bug Fix TypeError: graphrag/general/extractor.py
2025-04-01 09:38:21 +08:00
ece59034f7 fix: Resolve KnowledgeGraph entity resolution errors (#6653) (#6691)
### Related Issue: #6653
### Environment:

Using nightly version

Elasticsearch database

### Bug Description:
When clicking the "Entity Resolution" button in KnowledgeGraph,
encountered the following errors:

graphrag/entity_resolution.py

```
list(sub_connect_graph.nodes) AttributeError
```

graphrag/general/extractor.py
```
node0_attrs[attr] = sorted(set(node0_attrs[attr].extend(node1_attrs[attr])))
TypeError: 'NoneType' object is not iterable
```
```
for attr in ["keywords", "source_id"]:  
 KeyError I think attribute "keywords" is in edges not nodes
```
graphrag/utils.py
```
settings.docStoreConn.delete()  # Sync function called as async
```
### Changes Made:

Fixed AttributeError in entity_resolution.py by properly handling graph
nodes

Fixed TypeError and KeyError in extractor.py by separate operations

Corrected async/sync mismatch in document deletion call
2025-03-31 22:31:35 +08:00
0a42e5777e Refa: docker/.env comment refinement. (#6689)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2025-03-31 18:26:20 +08:00
e2b66628f4 Feat: extend S3 storage compatibility and add knowledge base ID prefix (#6355)
### What problem does this PR solve?

- Added support for S3-compatible protocols.
- Enabled the use of knowledge base ID as a file prefix when storing
files in S3.
- Updated docker/README.md to include detailed S3 and OSS configuration
instructions.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-31 16:09:43 +08:00
46b5e32cd7 Feat: support vision llm for gpustack (#6636)
### What problem does this PR solve?
https://github.com/infiniflow/ragflow/issues/6138

This PR is going to support vision llm for gpustack, modify url path
from `/v1-openai` to `/v1`

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-31 15:33:52 +08:00
7d9dd1e5d3 Refa: remove default build-in rerank model. (#6682)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
- [x] Performance Improvement
2025-03-31 15:33:19 +08:00
1985ff7918 add type canvas (#6680)
add type canvas
### Type of change
- [x] Refactoring
2025-03-31 14:46:29 +08:00
60b9c027c8 Refa: add meta data to retrieval. (#6676)
### What problem does this PR solve?

#6619
### Type of change


- [x] Performance Improvement
2025-03-31 11:45:56 +08:00
2793c8e4fe Added a guide on setting page rank. (#6645)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update

---------

Co-authored-by: balibabu <cike8899@users.noreply.github.com>
2025-03-31 11:44:18 +08:00
805a8f1f47 Update broken discord (#6678)
### Type of change

- [x] Documentation Update
2025-03-31 11:29:34 +08:00
d4a3e9a7cc Fix table migration on non-exist-yet indexed columns. (#6666)
### What problem does this PR solve?

Fix #6334

Hello, I encountered the same problem in #6334. In the
`api/db/db_models.py`, it calls `obj.create_table()` unconditionally in
`init_database_tables`, before the `migrate_db()`. Specially for the
`permission` field of `user_canvas` table, it has `index=True`, which
causes `peewee` to issue a SQL trying to create the index when the field
does not exist (the `user_canvas` table already exists), so
`psycopg2.errors.UndefinedColumn: column "permission" does not exist`
occurred.

I've added a judgement in the code, to only call `create_table()` when
the table does not exist, delegate the migration process to
`migrate_db()`.

Then another problem occurs: the `migrate_db()` actually does nothing
because it failed on the first migration! The `playhouse` blindly issue
DDLs without things like `IF NOT EXISTS`, so it fails... even if the
exception is `pass`, the transaction is still rolled back. So I removed
the transaction in `migrate_db()` to make it work.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-31 11:27:20 +08:00
ad4e59edb2 Don't split and strip input in retrieval component. (#6662)
### What problem does this PR solve?

Actually fix #6241 

Hello, I ran into the same problem as #6241. When I'm testing my agent
flow in the web ui using `Run` button with a file input, the retrieval
component always gave an empty output.

In the code I found that:

`web/src/pages/flow/debug-content/index.tsx`:

```tsx
const onOk = useCallback(async () => {
    const values = await form.validateFields();
    const nextValues = Object.entries(values).map(([key, value]) => {
      const item = parameters[Number(key)];
      let nextValue = value;
      if (Array.isArray(value)) {
        nextValue = ``;

        value.forEach((x) => {
          nextValue +=
            x?.originFileObj instanceof File
              ? `${x.name}\n${x.response?.data}\n----\n`    // Here, the file content always ends in '\n'
              : `${x.url}\n${x.result}\n----\n`;
        });
      }
      return { ...item, value: nextValue };
    });

    ok(nextValues);
  }, [form, ok, parameters]);
```

while in the `agent/component/retrieval.py`:

```python
def _run(self, history, **kwargs):
        query = self.get_input()
        query = str(query["content"][0]) if "content" in query else ""
        lines = query.split('\n')                     # inputs are split to ['xxx','yyy','----','']
        query = lines[-1] if lines else ""      # Here we always get '', thus no result
        kbs = KnowledgebaseService.get_by_ids(self._param.kb_ids)
        if not kbs:
            return Retrieval.be_output("")
```

so the code will never got correct result.

I'm not sure why the input needs such a split here, so I just removed
the splitting, and it works well on my side.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-31 11:26:49 +08:00
aca4cf4369 Test: Added test cases for Retrieval Chunks HTTP API (#6649)
### What problem does this PR solve?

cover [retrieval
chunk](https://ragflow.io/docs/v0.17.2/http_api_reference#retrieve-chunks)
endpoints

### Type of change

- [x]  add test cases
2025-03-31 10:05:35 +08:00
9aa047257a Fix agent completion requiring calling twice with parameters in begin component (#6659)
### What problem does this PR solve?

Fix #5418

Actually, the fix #4329 also works for agent flows with parameters, so
this PR just relaxes the `else` branch of that. With this PR, it works
fine on my side, may need more testing to make sure this does not break
something.

I guess the real problem may be deeply hidden in the code which relates
to conversation and canvas execution. After a few hours of debugging, I
see the only difference between with and without parameters in `begin`
component, is the `history` field of canvas data. When the `begin`
component contains some parameters, the debug log shows:

```
025-03-29 19:50:38,521 DEBUG    356590 {
            "component_name": "Begin",
            "params": {"output_var_name": "output", "message_history_window_size": 22, "query": [{"type": "fileUrls", "key": "fileUrls", "name": "files", "optional": true, "value": "问题.txt\n今天天气怎么样"}], "inputs": [], "debug_inputs": [], "prologue": "你好! 我是你的助理,有什么可以帮到你的吗?", "output": null},
            "output": null,
            "inputs": []
        }, history: [["user", "请回答我上传文件中的问题。"]], kwargs: {"stream": false}
2025-03-29 19:50:38,523 DEBUG    356590 {
            "component_name": "Answer",
            "params": {"output_var_name": "output", "message_history_window_size": 22, "query": [], "inputs": [], "debug_inputs": [], "post_answers": [], "output": null},
            "output": null,
            "inputs": []
        }, history: [["user", "请回答我上传文件中的问题。"]], kwargs: {"stream": false}
```

Then it does not go further along the flow.

When the `begin` component does not contain any parameter, the debug log
shows:

```
2025-03-29 19:41:13,518 DEBUG    353596 {
            "component_name": "Begin",
            "params": {"output_var_name": "output", "message_history_window_size": 22, "query": [], "inputs": [], "debug_inputs": [], "prologue": "你好! 我是你的助理,有什么可以帮到你的吗?", "output": null},
            "output": null,
            "inputs": []
        }, history: [], kwargs: {"stream": false}
2025-03-29 19:41:13,520 DEBUG    353596 {
            "component_name": "Answer",
            "params": {"output_var_name": "output", "message_history_window_size": 22, "query": [], "inputs": [], "debug_inputs": [], "post_answers": [], "output": null},
            "output": null,
            "inputs": []
        }, history: [], kwargs: {"stream": false}
2025-03-29 19:41:13,556 INFO     353596 127.0.0.1 - - [29/Mar/2025 19:41:13] "POST /api/v1/agents/fee6886a0c6f11f09b48eb8798e9aa9b/sessions?user_id=123 HTTP/1.1" 200 -
2025-03-29 19:41:21,115 DEBUG    353596 Canvas.prepare2run: Retrieval:LateGuestsNotice
2025-03-29 19:41:21,116 DEBUG    353596 {
            "component_name": "Retrieval",
            "params": {"output_var_name": "output", "message_history_window_size": 22, "query": [], "inputs": [], "debug_inputs": [], "similarity_threshold": 0.2, "keywords_similarity_weight": 0.3, "top_n": 8, "top_k": 1024, "kb_ids": ["9aca3c700c5911f0811caf35658b9385"], "rerank_id": "", "empty_response": "", "tavily_api_key": "", "use_kg": false, "output": null},
            "output": null,
            "inputs": []
        }, history: [["user", "请回答我上传文件中的问题。"]], kwargs: {"stream": false}
```

It correctly goes along the flow and generates correct answer.

You can see the difference: when the `begin` component has any
parameter, the `history` field is filled from the beginning, while it is
just `[]` if the `begin` component has no parameter.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-31 09:57:56 +08:00
65a8cd1772 Fix knowledge_graph_kwd on infinity. Close #6476 and #6624 (#6651)
### What problem does this PR solve?

Fix knowledge_graph_kwd on infinity. Close #6476 and #6624

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-28 22:05:40 +08:00
563a84beaf Docs: fix retrieval docs. (#6633)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-03-28 16:03:37 +08:00
d32a35d8fd Fix entity_types. Close #6287 and #6608 (#6632)
### What problem does this PR solve?

Fix entity_types. Close #6287 and #6608

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-28 15:00:24 +08:00
2632493c8b Consolidate entrypoint to support broader deployment scenarios (#6566)
### What problem does this PR solve?

This PR gives better control over how we distribute which service will
be loaded. With this approach, we can create containers to run only the
web server and others to run the task executor. It also introduces the
unique ID per task executor host, this will be important when scaling
task executors horizontally, considering unique task executor ids will
be required.

This new `entrypoint.sh` maintains the default behavior of starting the
web server and task executor in the same host.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [X] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-28 12:39:34 +08:00
c61df5dd25 Dynamic Context Window Size for Ollama Chat (#6582)
# Dynamic Context Window Size for Ollama Chat

## Problem Statement
Previously, the Ollama chat implementation used a fixed context window
size of 32768 tokens. This caused two main issues:
1. Performance degradation due to unnecessarily large context windows
for small conversations
2. Potential business logic failures when using smaller fixed sizes
(e.g., 2048 tokens)

## Solution
Implemented a dynamic context window size calculation that:
1. Uses a base context size of 8192 tokens
2. Applies a 1.2x buffer ratio to the total token count
3. Adds multiples of 8192 tokens based on the buffered token count
4. Implements a smart context size update strategy

## Implementation Details

### Token Counting Logic
```python
def count_tokens(text):
    """Calculate token count for text"""
    # Simple calculation: 1 token per ASCII character
    # 2 tokens for non-ASCII characters (Chinese, Japanese, Korean, etc.)
    total = 0
    for char in text:
        if ord(char) < 128:  # ASCII characters
            total += 1
        else:  # Non-ASCII characters
            total += 2
    return total
```

### Dynamic Context Calculation
```python
def _calculate_dynamic_ctx(self, history):
    """Calculate dynamic context window size"""
    # Calculate total tokens for all messages
    total_tokens = 0
    for message in history:
        content = message.get("content", "")
        content_tokens = count_tokens(content)
        role_tokens = 4  # Role marker token overhead
        total_tokens += content_tokens + role_tokens

    # Apply 1.2x buffer ratio
    total_tokens_with_buffer = int(total_tokens * 1.2)
    
    # Calculate context size in multiples of 8192
    if total_tokens_with_buffer <= 8192:
        ctx_size = 8192
    else:
        ctx_multiplier = (total_tokens_with_buffer // 8192) + 1
        ctx_size = ctx_multiplier * 8192
    
    return ctx_size
```

### Integration in Chat Method
```python
def chat(self, system, history, gen_conf):
    if system:
        history.insert(0, {"role": "system", "content": system})
    if "max_tokens" in gen_conf:
        del gen_conf["max_tokens"]
    try:
        # Calculate new context size
        new_ctx_size = self._calculate_dynamic_ctx(history)
        
        # Prepare options with context size
        options = {
            "num_ctx": new_ctx_size
        }
        # Add other generation options
        if "temperature" in gen_conf:
            options["temperature"] = gen_conf["temperature"]
        if "max_tokens" in gen_conf:
            options["num_predict"] = gen_conf["max_tokens"]
        if "top_p" in gen_conf:
            options["top_p"] = gen_conf["top_p"]
        if "presence_penalty" in gen_conf:
            options["presence_penalty"] = gen_conf["presence_penalty"]
        if "frequency_penalty" in gen_conf:
            options["frequency_penalty"] = gen_conf["frequency_penalty"]
            
        # Make API call with dynamic context size
        response = self.client.chat(
            model=self.model_name,
            messages=history,
            options=options,
            keep_alive=60
        )
        return response["message"]["content"].strip(), response.get("eval_count", 0) + response.get("prompt_eval_count", 0)
    except Exception as e:
        return "**ERROR**: " + str(e), 0
```

## Benefits
1. **Improved Performance**: Uses appropriate context windows based on
conversation length
2. **Better Resource Utilization**: Context window size scales with
content
3. **Maintained Compatibility**: Works with existing business logic
4. **Predictable Scaling**: Context growth in 8192-token increments
5. **Smart Updates**: Context size updates are optimized to reduce
unnecessary model reloads

## Future Considerations
1. Fine-tune buffer ratio based on usage patterns
2. Add monitoring for context window utilization
3. Consider language-specific token counting optimizations
4. Implement adaptive threshold based on conversation patterns
5. Add metrics for context size update frequency

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-28 12:38:27 +08:00
1fbc4870f0 Fix: HTTP API delete_chunks issue. (#6621)
### What problem does this PR solve?

#6611

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-28 12:13:43 +08:00
f304492716 Fix: binlog_expire_logs_seconds (#6626)
This PR updates the MySQL container configuration by setting the
parameter --binlog_expire_logs_seconds to 604800 seconds (7 days). This
change ensures that MySQL automatically purges binary logs older than 7
days, helping to conserve disk space and maintain precise log
management.

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-28 11:37:53 +08:00
f35c226ce7 Feat: Add RadioGroup component #3221 (#6622)
### What problem does this PR solve?

Feat: Add RadioGroup component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-28 10:20:49 +08:00
0b48a2e0d1 Fix: When Excel is a formula, the parsed result is a formula, but cannot be correctly parsed as a value type (#6613)
### What problem does this PR solve?

Fix: When Excel is a formula, the parsed result is a formula, but cannot
be correctly parsed as a value type

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: tangyu <1@1.com>
2025-03-28 09:33:49 +08:00
fd614a7aef Test: Added test cases for Delete Chunks HTTP API (#6612)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] add test cases
2025-03-28 09:33:23 +08:00
0758c04941 Refa: token similarity calculations. (#6614)
### What problem does this PR solve?

#6507

### Type of change

- [x] Performance Improvement
2025-03-28 09:33:08 +08:00
fe0396bbb9 Introduced delete_knowledge_graph (#6605)
### What problem does this PR solve?

Introduced delete_knowledge_graph

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] Documentation Update
2025-03-27 17:16:48 +08:00
974a467cf6 Fix: The rule of Categorize operator is adjusted. (#6599)
### What problem does this PR solve?

When I use the categorization operator, I find that if the keyword I
want to Categorize appears repeatedly in the input, then I cannot judge
the word that appears most frequently. Instead, I simply get the word
that matches and return all the ones that have made the following
changes to the categorize filter.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring
- [x] Performance Improvement
2025-03-27 17:02:21 +08:00
36b62e0fab EntityResolution batch. Close #6570 (#6602)
### What problem does this PR solve?

EntityResolution batch

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-27 16:40:36 +08:00
d2043ff9f2 Fix: LmStudioChat issue. (#6591)
### What problem does this PR solve?

#6577

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-27 14:59:15 +08:00
ecc9605a32 Fix: team doc deletion issue. (#6589)
### What problem does this PR solve?

#6557

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-27 13:26:38 +08:00
70dc56d26b Feat: Add logo-with-text-white.svg #3221 (#6588)
### What problem does this PR solve?

Feat: Add logo-with-text-white.svg #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-27 12:28:17 +08:00
82ccbd2cba fix:  Remove unnecessary minio initialization (#6544)
### What problem does this PR solve?

Prevent applications from failing to start due to calling non-existent
or incorrect Minio connection configurations when using file storage
outside of Minio

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-27 09:54:25 +08:00
c4998d0e09 Rename graphrag task lock (#6576)
### What problem does this PR solve?

Rename graphrag task lock

### Type of change

- [x] Refactoring
2025-03-26 23:48:47 +08:00
5eabfe3912 Update values.yaml image to infiniflow/infinity:v0.6.0-dev3 issue#5882 (#6568)
related issue #5882

### What problem does this PR solve?

update helm infinity image version from v0.5.0 
 image to infiniflow/infinity:v0.6.0-dev3 

to solve issue #5882

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-26 21:15:26 +08:00
df3890827d Refa: change LLM chat output from full to delta (incremental) (#6534)
### What problem does this PR solve?

Change LLM chat output from full to delta (incremental)

### Type of change

- [x] Refactoring
2025-03-26 19:33:14 +08:00
6599db1e99 Test: Update test cases for PR #6405 #6504 #6538 (#6565)
### What problem does this PR solve?

PR #6405 #6504 #6538

### Type of change

- [x] update test cases
2025-03-26 19:23:13 +08:00
b7d7ad536a AI search vs. chat (#6569)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-03-26 18:46:34 +08:00
24d8ff7425 Fix:flow DB Assistant module translate to zh (#6562)
### What problem does this PR solve?

Fix:flow DB Assistant module translate to zh

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-26 17:32:05 +08:00
735d9dd949 Feat: add "tools" to llm_factories.json (#6552)
### What problem does this PR solve?



### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Chenzy <chenzy901@gmail.com>
2025-03-26 17:31:18 +08:00
cc5f4a5efa Fix: python_api_reference.md update dataset bug (#6527)
### What problem does this PR solve?

There is a small bug in the update dataset of this document. The return
type of rag_oobject.list_datasets is a list type, and the first item
should be taken as' ragflow_stdk.modules.dataset ' DataSet`, Adapt to
the update.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 17:30:09 +08:00
93c26ae1ef Test: Added test cases for Update Chunk HTTP API (#6556)
### What problem does this PR solve?

cover [update
chunk](https://ragflow.io/docs/v0.17.2/http_api_reference#update-chunk)
endpoints

### Type of change

- [x] add test cases
2025-03-26 16:47:47 +08:00
cc8029a732 Fix: uploading in chat box issue. (#6547)
### What problem does this PR solve?

#6228

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 15:37:48 +08:00
6bf26e2a81 Optimize graphrag again (#6513)
### What problem does this PR solve?

Removed set_entity and set_relation to avoid accessing doc engine during
graph computation.
Introduced GraphChange to avoid writing unchanged chunks.

### Type of change

- [x] Performance Improvement
2025-03-26 15:34:42 +08:00
7a677cb095 Fix: image_id is None. (#6538)
### What problem does this PR solve?

#6499

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 12:04:21 +08:00
12ad746ee6 Fix: Bedrock model invocation error. (#6533)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 11:27:12 +08:00
163e71d06f Fix: Hunyuan model adding error. (#6531)
### What problem does this PR solve?

#6523
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 10:33:33 +08:00
c8c91fd827 Fix: link to KB from filemanager. (#6530)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 09:41:14 +08:00
d17970ebd0 0321 chunkmethods (#6520)
### What problem does this PR solve?

#6061 

### Type of change


- [x] Documentation Update
2025-03-26 09:03:18 +08:00
bf483fdf02 Fix: describe parameter error. (#6519)
### What problem does this PR solve?
#6228

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-26 09:02:48 +08:00
b2b7ed8927 Fix: abnormal chunk id (#6506)
### What problem does this PR solve?

#6500

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 19:03:29 +08:00
0a79dfd5cf Test: Added test cases for List Chunks HTTP API (#6514)
### What problem does this PR solve?

cover [list
chunks](https://ragflow.io/docs/v0.17.2/http_api_reference#list-chunks)
endpoints

### Type of change

- [x] update test cases
2025-03-25 17:28:58 +08:00
1d73baf3d8 Feat: improve '/mv' '/list' API performance (#6502)
### What problem does this PR solve?

1. for /mv API use get by ids to avoid O(n) DB IO

2. for /list remove one useless call
### Type of change

- [x] Performance Improvement
2025-03-25 16:30:25 +08:00
f3ae4a3bae Fix: img_id errror. (#6504)
### What problem does this PR solve?

#6499

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 15:57:03 +08:00
814a210f5d Fix: failed to acquire lock exception with retry mechanism for postgres and mysql (#6483)
Added the with_retry decorator in db_models.py to add a retry mechanism
for database operations. Applied the retry mechanism to the lock and
unlock methods of the PostgresDatabaseLock and MysqlDatabaseLock classes
to enhance the reliability of lock operations.

### What problem does this PR solve?
resolve failed to acquire lock exception with retry mechanism

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-03-25 15:09:56 +08:00
60c3a253ad Fix: api-key issue for xinference. (#6490)
### What problem does this PR solve?

#2792

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 15:01:13 +08:00
384b6549a6 Fix: remove doc status checking while creating an assistant. (#6486)
### What problem does this PR solve?

#6461

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 11:13:22 +08:00
b2ec39c59d Fix: Resolve FlowSetting not reading Title from .ts files (#6469)
### What problem does this PR solve?

Fix: Resolve FlowSetting not reading Title from .ts files

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 11:07:29 +08:00
095fc84cf2 Fix: claude max tokens. (#6484)
### What problem does this PR solve?

#6458

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-25 10:41:55 +08:00
542cf16292 Feat: add project_id and project_name to Langfuse API (#6481)
### What problem does this PR solve?

Enhance Langfuse API: add project_id and project_name

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-25 10:36:34 +08:00
27989eb9a5 Test: Add list chunk checkpoint for the add chunk API (#6482)
### What problem does this PR solve?

Add list chunk checkpoint for the add chunk API

### Type of change

- [x] update test cases
2025-03-25 10:36:21 +08:00
05997e8215 Remove thinking block from keyword node's result (#6474)
### What problem does this PR solve?

For now, if you use thinking model (deepseek-r1:32b with ollama server
in my case) in "Keyword" node, result contains all <think> block and so
node return not only keywords

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-25 10:22:41 +08:00
5d9afce12d Feat: improve the performance for '/upload' API (#6479)
### What problem does this PR solve?
improve the logic to fetch parent folder, remove the useless DB IO logic

### Type of change

- [x] Performance Improvement
2025-03-25 10:22:19 +08:00
ee6a0bd9db Refa: enhancement: enhance the prompt of related_question API (#6463)
### What problem does this PR solve?

Enhance the prompt of `related_question` API.

### Type of change

- [x] Enhancement
- [x] Documentation Update
2025-03-25 10:00:10 +08:00
b6f3242c6c Test: Update test cases to reduce execution time (#6470)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] update test cases
2025-03-25 09:17:05 +08:00
390086c6ab Fix: split process bug in graphrag extract (#6423)
### What problem does this PR solve?

1. miss completion delimiter.
2. miss bracket process.
3. doc_ids return by update_graph is a set, and insert operation in
extract_community need a list.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 21:41:20 +08:00
a40c5aea83 Miscellaneous UI updates (#6471)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-24 19:36:47 +08:00
f691b4ddd2 Feat: Improve "/convert" API's performance (#6465)
### What problem does this PR solve?

for batch requests based on get_by_ids to fetch all files first replace
the O(n) IO logic.

### Type of change


- [x] Performance Improvement
2025-03-24 19:08:22 +08:00
3c57a9986c Feat: Add LangfuseCard component. #6155 (#6468)
### What problem does this PR solve?

Feat: Add LangfuseCard component. #6155

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-24 19:07:55 +08:00
5e0a77df2b Feat: add Langfuse APIs (#6460)
### What problem does this PR solve?

Add Langfuse APIs

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-24 18:25:43 +08:00
66e557b6c0 Fix: Langfuse update model has no fields attribute (#6453)
### What problem does this PR solve?

Langfuse update model has no fields attribute

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 15:37:14 +08:00
200b6f55c6 Fix: NameError: free variable 'langfuse_generation' referenced before assignment in enclosing scope (#6451)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: lizheng@ssc-hn.com <lizheng@ssc-hn.com>
2025-03-24 15:14:36 +08:00
b77ce4e846 Feat: support api-key for Ollama. (#6448)
### What problem does this PR solve?

#6189

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 14:53:17 +08:00
85eb367ede Feat: add basic Langfuse support for LLM module (#6443)
### What problem does this PR solve?

#6155

Add basic Langfuse support for LLM module.

A trace example:

<img width="755" alt="image"
src="https://github.com/user-attachments/assets/25c1f852-5116-486c-a47f-6097187142ca"
/>


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-24 13:18:47 +08:00
0b63346a1a Test: Update test case for #6081 (#6446)
### What problem does this PR solve?

Update test case for #6081

### Type of change

- [x] Update test case
2025-03-24 13:18:12 +08:00
85eb3775d6 Refa: update Anthropic models. (#6445)
### What problem does this PR solve?

#6421

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 12:34:57 +08:00
e4c8d703b5 Test: Update test cases for PR #6194 #6259 #6376 (#6444)
### What problem does this PR solve?

PR #6194 #6259 #6376

### Type of change

- [x] Update test cases
2025-03-24 12:01:33 +08:00
60afb63d44 Feat: Add background-core-standard to tailwind.css #3221 (#6437)
### What problem does this PR solve?

Feat: Add background-core-standard to tailwind.css #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-24 10:51:46 +08:00
ee5aa51d43 Fix: point in tag issue. (#6436)
### What problem does this PR solve?

#6414

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 10:45:29 +08:00
a6aed0da46 Fix: rerank with YoudaoRerank issue. (#6396)
### What problem does this PR solve?

Fix rerank with YoudaoRerank issue,"'YoudaoRerank' object has no
attribute '_dynamic_batch_size'"


![17425412353825](https://github.com/user-attachments/assets/9ed304c7-317a-440e-acff-fe895fc20f07)


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-24 10:09:16 +08:00
d77380f024 Feat: support pic base bullet for PPT (#6406)
### What problem does this PR solve?

support pic base bullet for PPT

modify one mistake in document

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-24 09:31:31 +08:00
efc4796f01 Fix ratelimit errors during document parsing (#6413)
### What problem does this PR solve?

When using the online large model API knowledge base to extract
knowledge graphs, frequent Rate Limit Errors were triggered,
causing document parsing to fail. This commit fixes the issue by
optimizing API calls in the following way:
Added exponential backoff and jitter to the API call to reduce the
frequency of Rate Limit Errors.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-22 23:07:03 +08:00
d869e4d43f Fix: Preserve quotes while handling variable substitution withTemplate component. (#6410)
###Address Problem:
The original implementation used re.sub(r"(\\\"|\")", "", content) which
stripped all quotes from the processed content. While this worked for
simple Jinja2-rendered templates, it caused formatting issues when :
-Quotes were required in the final output (e.g., JSON, Python Code
strings)

###Solution:
    1. Selective JSON Serialization.
    2. Removed Global Quote Removal

### What problem does this PR solve?

This PR addresses an issue in template processing where all quotation
marks (" and \") were being removed from content, potentially corrupting
string formatting in rendered outputs. **In fact, extra quotes is
generated by json.dumps(v, ensure_ascii=False).**

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 19:44:03 +08:00
8eefc8b5fe Test: Added test cases for Add Chunk HTTP API (#6408)
### What problem does this PR solve?

cover [add
chunk](https://ragflow.io/docs/v0.17.2/http_api_reference#add-chunk)
endpoints

### Type of change

- [x] Add test cases
2025-03-21 19:16:30 +08:00
4091af4560 Fix: multiple top-level packages error in Python project (#6370)
### What problem does this PR solve?

This PR resolves the issue of multiple top-level packages being detected
in the Python project, which caused errors when using uv pip install.
The problem occurred because the project had multiple directories files
at the root level, leading to a flat-layout error.
To fix this, the pyproject.toml file was updated to explicitly list the
packages using the [tool.setuptools] section. This ensures that the
correct packages are included during installation, avoiding the
flat-layout error.
Type of change

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 18:44:49 +08:00
394d1a86f6 Fix: add chunk, empty question issue. (#6405)
### What problem does this PR solve?

#6404

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 18:44:12 +08:00
d88964f629 Feat: If the Transfer item is disabled, the item cannot be edited. #3221 (#6409)
### What problem does this PR solve?

Feat: If the Transfer item is disabled, the item cannot be edited. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-21 18:42:52 +08:00
0e0ebaac5f Feat: Adds hierarchical title path tracking for tables in DOCX documents to improve context association (#6374)
### What problem does this PR solve?

Adds hierarchical title path tracking for tables in DOCX documents to
improve context association. Previously, extracted tables lacked
positional context within document structure.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-21 18:42:36 +08:00
8b7e53e643 Fix: miss calculate of token number. (#6401)
### What problem does this PR solve?

#6308

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 17:30:38 +08:00
979cdc3626 UI updates. (#6398)
### What problem does this PR solve?

Updated UI descriptions for delimiters and recommended chunk size

### Type of change

- [x] Documentation Update
2025-03-21 16:50:20 +08:00
a2a4bfe3e3 Fix: change ollama default num_ctx. (#6395)
### What problem does this PR solve?

#6163

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 16:22:03 +08:00
85480f6292 Fix: the error of Ollama embeddings interface returning "500 Internal Server Error" (#6350)
### What problem does this PR solve?

Fix the error where the Ollama embeddings interface returns a “500
Internal Server Error” when using models such as xiaobu-embedding-v2 for
embedding.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 15:25:48 +08:00
f537b6ca00 Fix: flow list translate to zh (#6371)
### What problem does this PR solve?

Add the Chinese translation of 'noMoreData' on the flow list page

### Type of change

- [x] Refactoring
2025-03-21 14:54:12 +08:00
b5471978b0 Fix: add chunk api, empty content issue (#6390)
### What problem does this PR solve?

#6387

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 14:05:59 +08:00
efdfb39a33 Feat: Add Duplicate ID Check and Update Deletion Logic (#6376)
- Introduce the `check_duplicate_ids` function in `dataset.py` and
`doc.py` to check for and handle duplicate IDs.
- Update the deletion operation to ensure that when deleting datasets
and documents, error messages regarding duplicate IDs can be returned.
- Implement the `check_duplicate_ids` function in `api_utils.py` to
return unique IDs and error messages for duplicate IDs.


### What problem does this PR solve?

Close https://github.com/infiniflow/ragflow/issues/6234

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-21 14:05:17 +08:00
7cc5603a82 Fix broken discord invitation links (#6388)
### Type of change

- [x] Documentation Update
2025-03-21 13:38:34 +08:00
9ed004e90d Refa: control the simi for entity resolution. (#6386)
### What problem does this PR solve?

#6352

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 13:16:34 +08:00
d83911b632 Fix: huggingface rerank model issue. (#6385)
### What problem does this PR solve?

#6348

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 12:43:32 +08:00
bc58ecbfd7 Remove feature_request.md (#6383)
### What problem does this PR solve?


### Type of change


- [x] Refactoring
2025-03-21 12:03:38 +08:00
221eae2c59 Refa: refine template. (#6382)
### What problem does this PR solve?

### Type of change


- [x] Refactoring
2025-03-21 11:58:10 +08:00
37303e38ec Refa: refine template. (#6381)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-03-21 11:55:01 +08:00
b754bd523a Fix: let quot stay. (#6377)
### What problem does this PR solve?

#6337

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-21 11:47:42 +08:00
1bb990719e Feat: Add user registration toggle feature (#6327)
### What problem does this PR solve?

Feat: Add user registration toggle feature. Added a user registration
toggle REGISTER_ENABLED in the settings and .env config file. The user
creation interface now checks the state of this toggle to control the
enabling and disabling of the user registration feature.

the front-end implementation is done, the registration button does not
appear if registration is not allowed. I did the actual tests on my
local server and it worked smoothly.
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-21 09:38:15 +08:00
7f80d7304d Fix: Optimized the get_by_id method to resolve the issue of missing exceptions and improve query performance (#6320)
Fix: Optimized the get_by_id method to resolve the issue of missing
exceptions and improve query performance

### What problem does this PR solve?

Optimized the get_by_id method to resolve the issue of missing
exceptions and improve query performance.
Optimization details:
1. The original method used a custom query method that required
concatenating SQL, which impacted performance.
2. The query method returned a list, which needed to be accessed by
index, posing a risk of index out-of-bounds errors.
3. The original method used except Exception to catch all errors, which
is not a best practice in Python programming and may lead to missing
exceptions. The get_or_none method accurately catches DoesNotExist
errors while allowing other errors to be raised normally.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Performance Improvement
2025-03-20 23:23:48 +08:00
ca9c3e59fa Call register_scripts on connecting redis (#6361)
### What problem does this PR solve?

Call register_scripts on connecting redis

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 23:20:37 +08:00
674f94228b Chore: unify Ruff config and enable async checks (ASYNC, TRIO) (#6351)
### What problem does this PR solve?

Unify Ruff config and enable async checks (ASYNC, TRIO)

### Type of change

- [x] CI/CD or tooling improvement
2025-03-20 22:31:18 +08:00
ef7e96e486 Feat: Add the functionality to load environment variables from a .env file (#6331)
### Change Content

- A new function `load_env_file` has been added to load environment
variables from a .env file in the current script directory.
- If the .env file exists, the variables within it will be loaded; if it
does not exist, a warning message will be output.

I found this issue while testing this pr:
https://github.com/infiniflow/ragflow/pull/6327. The locally started
server did not read the REGISTER_ENABLED variables in the .env. The
result has always been the default True
### What problem does this PR solve?

Follow the tutorial in the README.md to start from source code. base's
container that is es、redis,etc will load .env. Therefore,
`launch_backend_service.sh` should also load .env to be consistent with
the configuration of the docker container when it was started

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-20 18:35:04 +08:00
dba0caa00b Fix update_progress (#6340)
### What problem does this PR solve?

Fix update_progress

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 17:01:28 +08:00
1d9ca172e3 Fix(api): correct document parsing progress check logic (#6318)
- Fix incorrect progress check condition that prevented re-parsing of
completed documents
- Allow parsing for documents with progress 0.0 (not started) or 1.0
(completed)
- Only block parsing for documents currently in progress (0.0 < progress
< 1.0)

Close #6312

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-20 16:00:17 +08:00
f0c4b28c6b Fix: type import (#6328)
### What problem does this PR solve?

fixed type import .

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 15:23:15 +08:00
6784e0dfee Fix: Resolved a bug where sibling components in Canvas were not restricted to fetching data from the upstream when parallel components were present. (#6315)
### What problem does this PR solve?

Fix: Resolved a bug where sibling components in Canvas were not
restricted to fetching data from the upstream when parallel components
were present.
Issue: When parallel components existed in Canvas, sibling components
incorrectly fetched data without being limited to the upstream scope,
causing data retrieval issues.
Solution: Adjusted the data fetching logic to ensure sibling components
only retrieve data from the upstream scope.
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 15:06:18 +08:00
95497b4aab Fix: adapt to old configurations. (#6321)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 14:50:59 +08:00
5b04b7d972 Fix: rerank with vllm issue. (#6306)
### What problem does this PR solve?

#6301

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 11:52:42 +08:00
4eb3a8e1cc Test: Skip unstable 'stop parse documents' test cases (#6310)
### What problem does this PR solve?

 Skip unstable 'stop parse documents' test cases

### Type of change

- [x] update test cases
2025-03-20 11:35:19 +08:00
9611185eb4 Feat: add VLM-boosted DocX parser (#6307)
### What problem does this PR solve?

Add VLM-boosted DocX parser

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-20 11:24:44 +08:00
e4380843c4 Feat: add fallback for PDF figure parser (#6305)
### What problem does this PR solve?

Add fallback for PDF figure parser

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-20 10:48:38 +08:00
046f0bba74 Fix: optimize setting config initialization to resolve Minio initialization error (#6282)
### What problem does this PR solve?

Optimize setting configuration initialization to resolve Minio
initialization error caused by using a specific storage.

Reproduction Scenario:
Using Aliyun OSS as the backend storage with the STORAGE_IMPL
environment variable set to OSS.
The service_conf.yaml.template configuration file contains OSS-related
configurations, while other storage configurations are commented out.
When the service starts, it still attempts to initialize the Minio
storage. Since there is no Minio configuration in
service_conf.yaml.template, it results in an error due to the missing
configuration file.

Optimization Measures:
Automatically determine the required initialization configuration based
on the environment variable.
Do not initialize configurations for unused resources.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-20 10:45:40 +08:00
e0c436b616 UI updates (#6290)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-20 10:26:16 +08:00
dbf2ee56c6 Test: Added test cases for Stop Parse Documents HTTP API (#6285)
### What problem does this PR solve?

cover [stop parse
documents](https://ragflow.io/docs/dev/http_api_reference#stop-parsing-documents)
endpoints

### Type of change

- [x] Add test cases
2025-03-20 09:42:50 +08:00
1d6760dd84 Feat: add VLM-boosted PDF parser (#6278)
### What problem does this PR solve?

Add VLM-boosted PDF parser if VLM is set.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-20 09:39:32 +08:00
344727f9ba Feat: add agent share team viewer (#6222)
### What problem does this PR solve?
Allow member view agent  
#  Canvas editor

![image](https://github.com/user-attachments/assets/042af36d-5fd1-43e2-acf7-05869220a1c1)
# List agent

![image](https://github.com/user-attachments/assets/8b9c7376-780b-47ff-8f5c-6c0e7358158d)
# Setting 

![image](https://github.com/user-attachments/assets/6cb7d12a-7a66-4dd7-9acc-5b53ff79a10a)
 
_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-19 19:04:13 +08:00
d17ec26c56 Fix: In the Agent's workflow, the input content cannot be wrapped, and \n will not work, otherwise an error will be reported #6241 (#6284)
### What problem does this PR solve?

Fix: In the Agent's workflow, the input content cannot be wrapped, and
\n will not work, otherwise an error will be reported #6241

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 18:54:23 +08:00
lei
4236d81cfc Docs: Update accelerate_doc_indexing.mdx (#6268)
### What problem does this PR solve?
The word is written incorrectly

### Type of change

- [x] Documentation Update
2025-03-19 18:04:03 +08:00
bb869aca33 Fix get_unacked_iterator (#6280)
### What problem does this PR solve?

Fix get_unacked_iterator. Close #6132 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 17:46:58 +08:00
9cad60fa6d Fix: Add a basic example when the example of content_tagging is empty (#6276)
### What problem does this PR solve?

When using LLM for auto-tag, if there are no examples, the tag format
generated by LLM may be wrong. This will cause Elasticsearch insert
errors. Adding basic examples can avoid this problem.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 17:30:47 +08:00
42e89e4a92 Fix: swich follow interact issue. (#6279)
### What problem does this PR solve?

#6188

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 17:30:12 +08:00
8daec9a4c5 Feat: Alter TreeView component #3221 (#6272)
### What problem does this PR solve?

Feat: Alter TreeView component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-19 15:44:59 +08:00
53ac27c3ff Feat: support agent version history. (#6130)
### What problem does this PR solve?
Add history version save
- Allows users to view and download agent files by version revision
history

![image](https://github.com/user-attachments/assets/c300375d-8b97-4230-9fc4-83d148137132)

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-19 15:22:53 +08:00
e689532e6e Fix: long api key issue. (#6267)
### What problem does this PR solve?

#6248

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 13:30:40 +08:00
c2302abaf1 Fix: remove dup ids for APIs. (#6263)
### What problem does this PR solve?

#6234

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 13:10:59 +08:00
8157285a79 Fix: Nan response for retrieval component. (#6265)
### What problem does this PR solve?

#6247

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 13:10:45 +08:00
c6e1a2ca8a Feat: add TTS support for SILICONFLOW. (#6264)
### What problem does this PR solve?

#6244

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-19 12:52:12 +08:00
41e112294b Fix: let parsing continue. (#6259)
### What problem does this PR solve?

#6229

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 12:18:19 +08:00
49086964b8 Fix: type violations. (#6262)
### What problem does this PR solve?

#6238
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 12:12:34 +08:00
dd81c30976 Fix: tag_feas deletion error. (#6257)
### What problem does this PR solve?

#6218

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 11:25:11 +08:00
1d8daad223 Fix: read flow blank template strings from i18n file (#6240)
### What problem does this PR solve?

Blank and createFromNothing were not read from the i18n file when Agent
was created
创建Agent的时候 Blank 和 createFromNothing  没从i18n文件中读取

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-19 10:56:35 +08:00
f540559c41 Miscellaneous updates (#6245)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-03-18 19:49:06 +08:00
d16033dd2c Fix: #5719 Added type check for parser_config (#6243)
### What problem does this PR solve?

Fix #5719 
Add data type validation for parser_config

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 18:40:06 +08:00
7eb417b24f Fix: Nan issue. (#6242)
### What problem does this PR solve?

#6065

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 17:58:54 +08:00
9515ed401f Test: Added test cases for Parse Documents HTTP API (#6235)
### What problem does this PR solve?

cover [parse
documents](https://ragflow.io/docs/dev/http_api_reference#parse-documents)
endpoints

### Type of change

- [x] add test cases
2025-03-18 17:39:24 +08:00
f982771131 Fix: empty retrieval kb ids. (#6236)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 17:39:10 +08:00
a087d13ccb Feat: text file support position retaining. (#6231)
### What problem does this PR solve?

#5832

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-18 16:55:11 +08:00
6e5cbd0196 Feat: Alter TransferList props #3221 (#6226)
### What problem does this PR solve?

Feat: Alter TransferList props #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-18 16:07:49 +08:00
6e8d0e3177 Fix: rank feat issue. (#6225)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 16:07:29 +08:00
5cf610af40 Feat: add vision LLM PDF parser (#6173)
### What problem does this PR solve?

Add vision LLM PDF parser

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-18 14:52:20 +08:00
897fe85b5c Fix: add support for non-stream response with session.ask_without_stream (#6207)
Add support for non-stream response with session.ask_without_stream and
fix a typo mistake in python API doc
There are requirements for non-stream response, especially for commands
exection, e.g. text2SQL. The commands have to be completed before the
agent is triggered.

### What problem does this PR solve?

It's to fix the [Issue:
6206](https://github.com/infiniflow/ragflow/issues/6206)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Howard WU <yuanhao.wu@ifudata.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-18 14:20:19 +08:00
57cbefa589 Feat: Add TreeView component #3221 (#6214)
### What problem does this PR solve?

Feat: Add TreeView component #3221

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-18 14:03:12 +08:00
09291db805 Fix: miss url path. (#6211)
### What problem does this PR solve?

#6210

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 14:02:57 +08:00
e9a6675c40 Fix: enable ollama api-key. (#6205)
### What problem does this PR solve?

#6189

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 13:37:34 +08:00
1333d3c02a Fix: float transfer exception. (#6197)
### What problem does this PR solve?

#6177

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 11:13:44 +08:00
222a2c8fa5 Docs: rm max token (#6202)
### What problem does this PR solve?

#6178

### Type of change

- [x] Documentation Update
2025-03-18 11:13:24 +08:00
5841aa8189 Docs: remove max tokens. (#6198)
### What problem does this PR solve?

#6178

### Type of change

- [x] Documentation Update
2025-03-18 11:05:06 +08:00
1b9f63f799 Fix: doc deletion failure with invalid docid. (#6194)
### What problem does this PR solve?

#6174

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 10:44:50 +08:00
1b130546f8 Fix: NaN data error. (#6192)
### What problem does this PR solve?

#6065

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 10:23:29 +08:00
7e4d693054 Fix: in case response.choices[0].message.content is None. (#6190)
### What problem does this PR solve?

#6164

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-18 10:00:27 +08:00
b0b4b7ba33 Feat: Improve Recognizer.py performance (#6185)
### What problem does this PR solve?

For the create_inputs method based on np operation to replace for loop

### Type of change

- [x] Performance Improvement
2025-03-18 09:39:49 +08:00
d0eda83697 Fix: none item while concating df. (#6176)
### What problem does this PR solve?

#6065

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-17 18:17:25 +08:00
503e5829bb Test: Added test cases for Delete Documents HTTP API (#6175)
### What problem does this PR solve?

cover [delete
documents](https://ragflow.io/docs/dev/http_api_reference#delete-documents)
endpoints

### Type of change

- [x] add test cases
2025-03-17 18:17:03 +08:00
79482ff672 Refa: Improve ppt_parser better handle list (#6162)
### What problem does this PR solve?
This pull request (PR) incorporates codes for parsing PPTX files, aiming
to more precisely depict text in list formats (hint list by .).

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-17 17:02:39 +08:00
3a99c2b5f4 Refa: PARALLEL_DEVICES is a static parameter. (#6168)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2025-03-17 16:49:54 +08:00
45fe02c8b3 Test: update test cases per pr #6144 (#6166)
### What problem does this PR solve?

fix check point per pr #6144 

### Type of change

- [x] update test case
2025-03-17 16:49:34 +08:00
2c3c4274be Fix: Correct parameter retrieval in thumbup api (#6114)
### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/5546

up_down was using req.get("set") to retrieve the parameter, but
according to the frontend code, it should be req.get("thumbup").



![image](https://github.com/user-attachments/assets/7189c982-f80e-48c9-a0a3-40f8a5d9e47b)



1842ca0334/web/src/interfaces/request/chat.ts (L3)


1842ca0334/api/apps/conversation_app.py (L327)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: zhaozhicheng <zhicheng.zhao@fastonetech.com>
2025-03-17 16:02:53 +08:00
501c017a26 Test: Added test cases for List Documents HTTP API (#6158)
### What problem does this PR solve?

cover [list
documents](https://ragflow.io/docs/dev/http_api_reference#list-documents)
endpoints

### Type of change

- [x] add test cases
2025-03-17 15:36:57 +08:00
d36420a87a Test: fix expected value validation for list dataset endpoint (#6160)
### What problem does this PR solve?

fix function is_sort() usage error

### Type of change

- [ ] update test cases
2025-03-17 15:36:48 +08:00
5983803c8b Miscellaneous UI updates (#6094)
### What problem does this PR solve?

#6049 

### Type of change

- [x] Documentation Update
- [x] Other (please describe): UI updates
2025-03-17 14:17:34 +08:00
fabc5e9259 Refa: fix re-rank scope. (#6152)
### What problem does this PR solve?

#6140

### Type of change


- [x] Refactoring
2025-03-17 13:26:29 +08:00
5748d58c74 Refa: refine the error message. (#6151)
### What problem does this PR solve?

#6138

### Type of change

- [x] Refactoring
2025-03-17 13:07:22 +08:00
bfa8d342b3 Fix: retrieval debug mode issue. (#6150)
### What problem does this PR solve?

#6139

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-17 13:07:13 +08:00
37f3486483 Fix: validation of readonly fields. (#6144)
### What problem does this PR solve?

#6104

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-17 12:22:49 +08:00
3e19044dee Feat: add OCR's muti-gpus and parallel processing support (#5972)
### What problem does this PR solve?

Add OCR's muti-gpus and parallel processing support

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

@yuzhichang I've tried to resolve the comments in #5697. OCR jobs can
now be done on both CPU and GPU. ( By the way, I've encountered a
“Generate embedding error” issue #5954 that might be due to my outdated
GPUs? idk. ) Please review it and give me suggestions.

GPU:

![gpu_ocr](https://github.com/user-attachments/assets/0ee2ecfb-a665-4e50-8bc7-15941b9cd80e)

![smi](https://github.com/user-attachments/assets/a2312f8c-cf24-443d-bf89-bec50503546d)

CPU:

![cpu_ocr](https://github.com/user-attachments/assets/1ba6bb0b-94df-41ea-be79-790096da4bf1)
2025-03-17 11:58:40 +08:00
8495036ff9 Feat: Limit view with more knowledge when list knowledge so many (#6093)
### What problem does this PR solve?

Limit view with more knowledge when list knowledge so many.

### Type of change

- [x] Refactoring
2025-03-17 10:50:25 +08:00
7f701a5756 Test: update test cases per pr #6095 to fix issue #6039 (#6143)
### What problem does this PR solve?

update test case per pr #6095 to fix issue #6039

### Type of change

- [x] update test case
2025-03-17 10:49:40 +08:00
634e7a41c5 Doc: Update readme document (#6052)
### What problem does this PR solve?

Added GPU startup script in the readme document

### Type of change

- [x] Documentation Update
2025-03-17 09:51:13 +08:00
d1d651080a Test: Added test cases for Update Documents HTTP API (#6106)
### What problem does this PR solve?

cover [update documents
endpoints](https://ragflow.io/docs/dev/http_api_reference#update-document)

### Type of change

- [x] add test cases
2025-03-17 09:36:32 +08:00
0fa44c5dd3 Fix: update link of deploy_local_llm.mdx (#6110)
### What problem does this PR solve?

Links of [How to integrate with
Ollama](https://github.com/infiniflow/ragflow/blob/main/docs/guides/models/deploy_local_llm.mdx)
need to be update after #5555

```
https://github.com/infiniflow/ragflow/blob/main/docs/guides/deploy_local_llm.mdx
->
https://github.com/infiniflow/ragflow/blob/main/docs/guides/models/deploy_local_llm.mdx
```



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jingfelix <jingfelix@outlook.com>
2025-03-17 09:35:37 +08:00
89a69eed72 Introduced task priority (#6118)
### What problem does this PR solve?

Introduced task priority

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-14 23:43:46 +08:00
1842ca0334 Fix: Fixed the issue that events cannot be triggered after the shadcn-ui dialog is closed #3221. (#6108)
### What problem does this PR solve?

Fix: Fixed the issue that events cannot be triggered after the shadcn-ui
dialog is closed #3221.

Refer to [Combobox in a form in a dialog isn't working.
#1748](https://github.com/shadcn-ui/ui/issues/1748#issuecomment-2720130543)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 17:36:24 +08:00
e5a8b23684 Fix: empty tag field issue. (#6103)
### What problem does this PR solve?

#6102

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 17:35:57 +08:00
4fffee6695 Regards kb_id at ElasticSearch insert, update, delete. (#6105)
### What problem does this PR solve?

Regards kb_id at ElasticSearch insert, update, delete. Close #6066

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 17:34:02 +08:00
485bc7d7d6 Fix: limit the depth of DFS (#6101)
### What problem does this PR solve?

#6085

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 17:10:38 +08:00
b5ba8b783a Refa: enlarge http body size. (#6100)
### What problem does this PR solve?



### Type of change


- [x] Refactoring
2025-03-14 16:47:39 +08:00
d7774cf049 Fix: fix document concurrent upload issue (#6095)
### What problem does this PR solve?

Resolve document concurrent upload issue. #6039 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 16:31:44 +08:00
9d94acbedb Fix: Knowledge base page cannot upload folders #6062 (#6096)
### What problem does this PR solve?

Fix: Knowledge base page cannot upload folders #6062

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 16:17:10 +08:00
b77e844fc3 Fix: none parse_config updating. (#6092)
### What problem does this PR solve?

#6081

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 16:06:16 +08:00
a6ab2c71c3 Refa: enlarge default max request body size. (#6088)
### What problem does this PR solve?


### Type of change


- [x] Refactoring
2025-03-14 15:21:08 +08:00
5c8ad6702a Fix: check the file name length. (#6083)
### What problem does this PR solve?

#6060

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 15:01:37 +08:00
f0601afa75 Doc: update launch from source. (#6074)
### What problem does this PR solve?

#6050

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-03-14 14:20:18 +08:00
56e984f657 Fix: Prevent password boxes other than login passwords from displaying passwords saved in the browser's password manager by default. #6033 (#6084)
### What problem does this PR solve?

Fix: Prevent password boxes other than login passwords from displaying
passwords saved in the browser's password manager by default. #6033

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-14 14:15:43 +08:00
5d75b6be62 Fix executor name (#6080)
### What problem does this PR solve?

Fix executor name

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 14:13:47 +08:00
12c3023a22 Fix: remove NaN output of components. (#6079)
### What problem does this PR solve?

#6065

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 13:58:42 +08:00
56b228f187 Refa: remove max toekns for image2txt models. (#6078)
### What problem does this PR solve?

#6063

### Type of change


- [x] Refactoring
2025-03-14 13:51:45 +08:00
42eb99554f Feat: add token comsumption & speed to little lamp. (#6077)
### What problem does this PR solve?

#6059

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-14 13:37:31 +08:00
c85b468b8d Feat: Change “Document parser” to "PDF parser" #6072 (#6073)
### What problem does this PR solve?

Feat: Change “Document parser” to "PDF parser" #6072

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-14 12:03:35 +08:00
7463241896 Fix: empty doc id validation. (#6064)
### What problem does this PR solve?

#6031

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 11:45:44 +08:00
c00def5b71 Fix 6030 (#6070)
### What problem does this PR solve?

Close #6030 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-14 11:29:22 +08:00
f16418ccf7 Feat: Add deepseek to llm_factories (#6051)
### What problem does this PR solve?

AWS Bedrock has made deepseek-r1 available on its serverless inference.

This adds the R1 serverless model for use via the bedrock model
abilities.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-14 10:35:44 +08:00
2d4a60cae6 Fix: Reduce excessive IO operations by loading LLM factory configurations (#6047)
…ions

### What problem does this PR solve?

This PR fixes an issue where the application was repeatedly reading the
llm_factories.json file from disk in multiple places, which could lead
to "Too many open files" errors under high load conditions. The fix
centralizes the file reading operation in the settings.py module and
stores the data in a global variable that can be accessed by other
modules.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [x] Performance Improvement
- [ ] Other (please describe):
2025-03-14 09:54:38 +08:00
47926f7d21 Improve API Documentation, Standardize Error Handling, and Enhance Comments (#5990)
### What problem does this PR solve?  
- The API documentation lacks detailed error code explanations. Added
error code tables to `python_api_reference.md` and
`http_api_reference.md` to clarify possible error codes and their
meanings.
- Error handling in the codebase is inconsistent. Standardized error
handling logic in `sdk/python/ragflow_sdk/modules/chunk.py`.
- Improved API comments by adding standardized docstrings to enhance
code readability and maintainability.

### Type of change  
- [x] Documentation Update  
- [x] Refactoring
2025-03-13 19:06:50 +08:00
940072592f Fix: chat_completion answer data incorrect (#6041)
### What problem does this PR solve?

fix chat_completion answer data incorrect

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: renqi <renqi08266@fxomail.com>
2025-03-13 18:59:59 +08:00
4ff609b6a8 Fix: optimize OCR garbage identification to reduce unnecessary filtering (#6027)
### What problem does this PR solve?

Optimize OCR garbage identification to reduce unnecessary filtering.
#5713

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-13 18:48:32 +08:00
0a877941f4 Test: Added test cases for Download Documents HTTP API (#6032)
### What problem does this PR solve?

cover [download docments
endpoints](https://ragflow.io/docs/dev/http_api_reference#download-document)

### Type of change

- [x] add test cases
2025-03-13 18:32:57 +08:00
baf3b9be7c Added 0.17.2 release notes (#6028)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2025-03-13 15:59:58 +08:00
4df4bf68a2 DOCS: for release. (#6023)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-03-13 15:09:29 +08:00
471bd92b4c Fix: empty api-key causes problems. (#6022)
### What problem does this PR solve?
#5926

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-13 14:57:47 +08:00
3af1063737 Feat: Set the default value of Chunk token number to 512 #6016 (#6017)
### What problem does this PR solve?

Feat: Set the default value of Chunk token number to 512 #6016

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-13 14:51:55 +08:00
9c8060f619 0.17.1 release notes (#6021)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2025-03-13 14:43:24 +08:00
e213873852 Optimize graphrag cache get entity (#6018)
### What problem does this PR solve?

Optimize graphrag cache get entity

### Type of change

- [x] Performance Improvement
2025-03-13 14:37:59 +08:00
56acb340d2 Test: update test cases per issue #5920 #5923 (#6007)
### What problem does this PR solve?

update test cases per issue #5920 #5923

### Type of change

- [x] update test case
2025-03-13 10:53:07 +08:00
e05cdc2f9c Fix: encode detect error. (#6006)
### What problem does this PR solve?

#5967

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-13 10:47:58 +08:00
3571270191 Refa: refine the context window size warning. (#5993)
### What problem does this PR solve?


### Type of change
- [x] Refactoring
2025-03-12 19:40:54 +08:00
bd5eb47441 TEST: Added test cases for Upload Documents HTTP API (#5991)
### What problem does this PR solve?

cover upload docments endpoints

### Type of change

- [x] add test cases
2025-03-12 19:38:52 +08:00
7cd37c37cd Feat: add CSV file parsing support (#5989)
### What problem does this PR solve?

Add CSV file parsing support #4552, #5849, #5870

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-12 19:20:50 +08:00
d660f6b9a5 Feat: add use KG to retrieval component. (#5988)
### What problem does this PR solve?

#5973

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-12 19:10:07 +08:00
80389ae61e Feat: Alter Item to TransferListItemType #3221 (#5986)
### What problem does this PR solve?

Feat: Alter Item to TransferListItemType #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-12 18:54:41 +08:00
6e13922bdc Feat: Add qwq model support to Tongyi-Qianwen factory (#5981)
### What problem does this PR solve?

add qwq model support to Tongyi-Qianwen factory
https://github.com/infiniflow/ragflow/issues/5869

### Type of change

- [x] New Feature (non-breaking change which adds functionality)


![image](https://github.com/user-attachments/assets/49f5c6a0-ecaf-41dd-a23a-2009f854d62c)


![image](https://github.com/user-attachments/assets/93ffa303-920e-4942-8188-bcd6b7209204)


![1741774779438](https://github.com/user-attachments/assets/25f2fd1d-8640-4df0-9a08-78ee9daaa8fe)


![image](https://github.com/user-attachments/assets/4763cf6c-1f76-43c4-80ee-74dfd666a184)

Co-authored-by: zhaozhicheng <zhicheng.zhao@fastonetech.com>
2025-03-12 18:54:15 +08:00
c57f16d16f Feat: Why can't Retrieval component support internet web search. #5973 (#5978)
### What problem does this PR solve?

Feat: Why can't Retrieval component support internet web search. #5973

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-12 18:47:22 +08:00
3c43a7aee8 For an Agent with an Input Begin value, on the first call the return … (#5957)
…session_id does not exist in the session

For an Agent with an Input Begin value, on the first call the return
session_id does not exist in the session

### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-12 17:01:44 +08:00
dd8779b257 Feat: Retrieval supports internet search. (#5974)
### What problem does this PR solve?

#5973

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-12 16:51:01 +08:00
46bdfb9661 TEST: Remove unstable assertion introduced in PR #5924 (#5968)
### What problem does this PR solve?

Remove unstable assertion introduced in PR #5924

### Type of change

- [x] update test cases
2025-03-12 16:09:45 +08:00
e3ea4b7ec2 Fix: Add Knowledge Base Document Parsing Status Check (#5966)
When creating and updating chats, add a check for the parsing status of
knowledge base documents. Ensure that all documents have been parsed
before allowing chat creation to improve user experience and system
stability.

**Main Changes:**

- Add document parsing status check logic in `chat.py`.
- Implement the `is_parsed_done` method in `knowledgebase_service.py`.
- Prevent chat creation when documents are being parsed or parsing has
failed.

### What problem does this PR solve?

fix this bug:https://github.com/infiniflow/ragflow/issues/5960

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-03-12 16:07:45 +08:00
41c67ce8dd Fixed a Docusaurus display issue. (#5969)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-12 16:07:22 +08:00
870a6e93da Refactoring: Optimization of the Deep Research Module Code Structure (#5959)
This commit refactors the deep research module (deep_research.py), with
the following major improvements: The complex thinking and retrieval
logic has been broken down into multiple independent private methods,
enhancing code readability and maintainability. Static methods and class
methods have been introduced to simplify the logic for tag processing.
The search and reasoning processes have been optimized, increasing the
modularity of the code. The flexibility of information retrieval and
processing has been improved. The refactored code structure is now
clearer, making it easier to understand and extend the functionality of
the deep research module.

### What problem does this PR solve?

increase  the modularity of the code

### Type of change

- [x] Refactoring

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-03-12 15:34:52 +08:00
80f87913bb Fix: empty value updating. (#5949)
### What problem does this PR solve?

#5920

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-12 11:25:17 +08:00
45123dcc0a Fix: ollama model add error. (#5947)
### What problem does this PR solve?

#5944

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-12 10:56:05 +08:00
49d560583f Fix: HTTP API Updates Read-Only Dataset Fields During Modification #5923 (#5937)
### What problem does this PR solve?

Fixes #5923 

Fixes the readonly variables from payload at
 /datasets/<dataset_id> 

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

Now if user tries to modify readonly values then it will show " The
input parameters are invalid. "

invalid_keys = {"id", "embd_id", "chunk_num", "doc_num", "parser_id",
"create_date", "create_time", "created_by",
"status","token_num","update_date","update_time"}
    if any(key in req for key in invalid_keys):
return get_error_data_result(message="The input parameters are
invalid.")
i have include those readonly keys in invalid_keys

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Raghav <2020csb1115@iitrpr.ac.in>
2025-03-12 10:27:02 +08:00
1c663b32b9 Fix:signal.SIGUSR1 and signal.SIGUSR2 can't use in window. so don't bind signal.SIGUSR1 and signal.SIGUSR2 in the windows env (#5941)
### What problem does this PR solve?
Fix:signal.SIGUSR1 and signal.SIGUSR2 can't use in window. so don't bind
signal.SIGUSR1 and signal.SIGUSR2 in the windows env

### Type of change

- [✓ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: tangyu <1@1.com>
2025-03-12 09:43:18 +08:00
caecaa7562 Feat: apply LLM to optimize citations. (#5935)
### What problem does this PR solve?

#5905

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-11 19:56:21 +08:00
ed11be23bf Fix: When calling the Create chat completion API, the response data… (#5928)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: renqi <renqi08266@fxomail.com>
2025-03-11 19:56:07 +08:00
7bd5a52019 Feat: Add Breadcrumb component #3221 (#5929)
### What problem does this PR solve?

Feat: Add Breadcrumb component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-11 18:55:25 +08:00
87763ef0a0 TEST: Added test cases for Update Dataset HTTP API (#5924)
### What problem does this PR solve?

cover dataset update endpoints

### Type of change

- [x] Add test cases
2025-03-11 18:55:11 +08:00
939e668096 Optimized graphrag again (#5927)
### What problem does this PR solve?

Optimized graphrag again

### Type of change

- [x] Performance Improvement
2025-03-11 18:36:10 +08:00
45318e7575 Docs: updates. (#5921)
### What problem does this PR solve?


### Type of change

- [x] Other (please describe):
2025-03-11 16:43:50 +08:00
8250b9f6b0 Feat: Add german translations (#5866)
### What problem does this PR solve?

Add Support for german language 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-11 16:13:58 +08:00
1abf03351d Docs: reformat. (#5914)
### What problem does this PR solve?


### Type of change

- [x] Other (please describe):
2025-03-11 16:11:27 +08:00
46b95d5cfe Reverted some of the version changes (#5908)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-11 16:03:11 +08:00
59ba4777ee Docs: updates issue templates. (#5913)
### What problem does this PR solve?


### Type of change

- [x] Other (please describe):
2025-03-11 16:02:28 +08:00
d44739283c Docs: prepare docs for release v0.17.1 (#5900)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-03-11 14:39:41 +08:00
9c953a67a6 UI updates (#5899)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-11 14:14:37 +08:00
bd3fa317e7 Add docs for tag sets (#5890)
### What problem does this PR solve?

#5716, #5529

### Type of change

- [x] Documentation Update
2025-03-11 13:57:36 +08:00
715e2b48ca Test: Update test cases per PR #5748 #5878 (#5894)
### What problem does this PR solve?

update test cases per PR #5748 #5878  issue #5709 

### Type of change

- [x] update test cases
2025-03-11 13:35:28 +08:00
90d18143ba Refa: add prompt to empty retrieved answwer. (#5892)
### What problem does this PR solve?

#5883

### Type of change

- [x] Refactoring
2025-03-11 13:11:14 +08:00
4b6809b32d Fix: docs updates. (#5889)
### What problem does this PR solve?

#5852

### Type of change

- [x] Documentation Update
2025-03-11 11:55:39 +08:00
7b96146d3f Fix: check desc parameter value. (#5884)
### What problem does this PR solve?

#5851

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-11 11:43:21 +08:00
21c55a2e0f Test: Update test cases per PR #5778 (#5880)
### What problem does this PR solve?

update test cases per PR https://github.com/infiniflow/ragflow/pull/5778

### Type of change

- [x] update test cases
2025-03-11 11:07:09 +08:00
8e965040ce Fix: rm <think> for ES sql generation. (#5881)
### What problem does this PR solve?

#5850

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-11 10:41:19 +08:00
780ee2b2be Fix: empty dataset parser id. (#5878)
### What problem does this PR solve?

#5709

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-11 10:23:08 +08:00
6f9cd96ec5 Fix: dataset_ids parameter (#5864)
### What problem does this PR solve?

Fixed  #5839
This PR fix  error code 102, stating dataset_ids is required.

curl --request POST \
     --url http://{address}/api/v1/chats \
     --header 'Content-Type: application/json' \
     --header 'Authorization: Bearer <YOUR_API_KEY>' \
     --data '{
         "name": "test_chat"
     }'
     
     this is not getting datasetids , fix for it. 

file location : sdk\python\ragflow_sdk\ragflow.py

added : "dataset_ids": dataset_list if dataset_list else [],



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Raghav <2020csb1115@iitrpr.ac.in>
2025-03-11 09:44:06 +08:00
47e244ee9f Test: Update test cases per PR #5755 (#5857)
### What problem does this PR solve?

 Update test cases per PR #5755

### Type of change

- [x] update test cases
2025-03-10 19:04:39 +08:00
df11fe75d3 Feat: Add AvatarGroup component. #3221 (#5858)
### What problem does this PR solve?
Feat: Add AvatarGroup component. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-10 19:03:48 +08:00
bf0d516e49 Agent Update: Fix Role Issue and Enhance KB Search (#5842)
### What problem does this PR solve?

**generate.py 更新:**
问题:部分模型提供商对输入对话内容的格式有严格校验,要求第一条内容的 role 不能为 assistant,否则会报错。
解决:删除了系统设置的 agent 开场白,确保传递给模型的对话内容中,第一条内容的 role 不为 assistant。

**retrieval.py 更新:**
问题:当前知识库检索使用全部对话内容作为输入,可能导致检索结果不准确。
解决:改为仅使用用户最后提出的一个问题进行知识库检索,提高检索的准确性。

**Update generate.py:**
Issue: Some model providers have strict validation rules for the format
of input conversation content, requiring that the role of the first
content must not be assistant. Otherwise, an error will occur.
Solution: Removed the system-set agent opening statement to ensure that
the role of the first content in the conversation passed to the model is
not assistant.

**Update retrieval.py:**
Issue: The current knowledge base retrieval uses the entire conversation
content as input, which may lead to inaccurate retrieval results.
Solution: Changed the retrieval logic to use only the last question
asked by the user for knowledge base retrieval, improving retrieval
accuracy.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Performance Improvement
2025-03-10 18:29:58 +08:00
b18da35da6 TEST: Added test cases for List Dataset HTTP API (#5856)
### What problem does this PR solve?

cover dataset list endpoints

### Type of change

- [x] Add test cases
2025-03-10 18:29:33 +08:00
8ba1e6c183 Feat: add sync_dsl parameter to support synchronizing modifications to existing sessions (#5843)
When accessing the /api/v1/agents/{agent_id}/completions API, sessions
created before agent modifications retain the old DSL data. To use the
latest agent configuration (like new prompts) in historical sessions, I
added the sync_dsl parameter. It defaults to False to maintain existing
behavior and only synchronizes when set to True. If needed, a manual
synchronization API can be created to trigger the sync explicitly.
2025-03-10 17:46:08 +08:00
d4f84f0b54 Fix: keyword compont display issue #5794 (#5844)
### What problem does this PR solve?

Fix: keyword compont display issue #5794

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-10 16:15:44 +08:00
6ec6ca6971 Refactor graphrag to remove redis lock (#5828)
### What problem does this PR solve?

Refactor graphrag to remove redis lock

### Type of change

- [x] Refactoring
2025-03-10 15:15:06 +08:00
1163e9e409 Feat: When selecting a reordering model, give a prompt that it takes too long. #5834 (#5835)
### What problem does this PR solve?

Feat: When selecting a reordering model, give a prompt that it takes too
long. #5834

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-10 14:14:38 +08:00
15736c57c3 Fix: empty query issue. (#5830)
### What problem does this PR solve?

#5214

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-10 13:56:56 +08:00
fa817a8ab3 Refa: SiliconFlow model list refresh. (#5825)
### What problem does this PR solve?

#5806

### Type of change


- [x] Refactoring
2025-03-10 12:51:12 +08:00
8b99635eb3 Feat: Add TransferList component. #3221 (#5822)
### What problem does this PR solve?

Feat: Add TransferList component. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-10 11:22:06 +08:00
1919780880 Refa: reduce default value of MAX_CONCURRENT_CHATS (#5821)
### What problem does this PR solve?

#5786

### Type of change

- [x] Refactoring
2025-03-10 11:22:06 +08:00
82f5d901c8 Refa: add model. (#5820)
### What problem does this PR solve?

#5783

### Type of change

- [x] Refactoring
2025-03-10 11:22:06 +08:00
dek
dc4d4342cd Fix: broken /api/v1/chats endpoint (#5785)
### What problem does this PR solve?

The `/api/v1/chats` API endpoint was broken, any GET request got the
following response:
```
{"code":100,"data":null,"message":"TypeError(\"'int' object is not callable\")"}
```

With this log ragflow-server side:

```
2025-03-07 14:36:26,297 ERROR    20 'int' object is not callable
Traceback (most recent call last):
  File "/ragflow/.venv/lib/python3.10/site-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
  File "/ragflow/.venv/lib/python3.10/site-packages/flask/app.py", line 865, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
  File "/ragflow/api/utils/api_utils.py", line 303, in decorated_function
    return func(*args, **kwargs)
  File "/ragflow/api/apps/sdk/chat.py", line 323, in list_chat
    logging.WARN(f"Don't exist the kb {kb_id}")
TypeError: 'int' object is not callable
2025-03-07 14:36:26,298 INFO     20 172.18.0.6 - - [07/Mar/2025 14:36:26] "GET /api/v1/chats HTTP/1.1" 200 -
``` 
This was caused by the incorrect use of `logging.WARN` as a method (it's
a loglevel object), instead of the correct `logging.warning()` method.

This PR fixes that, and also rewrites the message to be grammaticaly
correct.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-10 11:22:06 +08:00
e05658685c Refa: update mistral model list. (#5818)
### What problem does this PR solve?

#5782

### Type of change

- [x] Refactoring
2025-03-10 11:22:06 +08:00
b29539b442 Fix: CoHereRerank not respecting base_url when provided (#5784)
### What problem does this PR solve?

vLLM provider with a reranking model does not work : as vLLM uses under
the hood the [CoHereRerank
provider](https://github.com/infiniflow/ragflow/blob/v0.17.0/rag/llm/__init__.py#L250)
with a `base_url`, if this URL [is not passed to the Cohere
client](https://github.com/infiniflow/ragflow/blob/v0.17.0/rag/llm/rerank_model.py#L379-L382)
any attempt will endup on the Cohere SaaS (sending your private api key
in the process) instead of your vLLM instance.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-10 11:22:06 +08:00
b1a46d5adc Fix:when start with source code not in docker env report 'UnicodeDec… (#5802)
### What problem does this PR solve?

fix:when start with  source code not in docker env report
"UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 5:
illegal multibyte sequence" in windows

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: tangyu <1@1.com>
2025-03-10 11:22:06 +08:00
50c510d16b Fix: bugs mentioned by#5760 (#5778)
### What problem does this PR solve?

Fixed the issue of "stop deleting when encountering invalid dataset ID"

#5760

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-10 11:22:06 +08:00
8a84d1048c TEST: Added test cases for Delete Dataset HTTP API (#5770)
### What problem does this PR solve?

1. cover dataset deletion endpoints
2. format code with ruff

### Type of change

- [x] add testcases
- [ ] style
2025-03-07 17:44:51 +08:00
2ad852d8df Fix: truncate message issue. (#5776)
### What problem does this PR solve?

Close #5761
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 17:41:56 +08:00
ca39f5204d Initial draft of Implemnt deep research (#5774)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-07 17:06:49 +08:00
5b0e38060a Feat:Optimize the table extraction logic in the Markdown parser: (#5663)
Enhance the recognition of both borderless and bordered Markdown tables.
Add support for extracting HTML tables, including various scenarios with
nested HTML tags. Improve performance by using conditional checks to
reduce unnecessary regular expression matching.

### What problem does this PR solve?

Optimize the table extraction logic in the Markdown parser:
Enhance the recognition of both borderless and bordered Markdown tables.
Add support for extracting HTML tables, including various scenarios with
nested HTML tags.
Improve performance by using conditional checks to reduce unnecessary
regular expression matching.

### Type of change

- [x] Performance Improvement

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-03-07 17:02:35 +08:00
66938e0b68 Feat(api): Add dsl parameters to control whether dsl fields are included (#5769)
1. **Issue**: When calling `list_agent_session` via the HTTP API, users
may only need to display conversation messages, and do not want to see
the associated dsl, which can be very large. Therefore, consider adding
a control option to determine whether the DSL should be returned, with
the default being to return it.

2. **Documentation Discrepancy**: In the HTTP API documentation, under
"List agent sessions," the "Response" section states that the "data"
field is a dictionary when "success" is returned. However, the actual
returned data is a list. This discrepancy has been corrected.
2025-03-07 16:58:00 +08:00
64c6cc4cf3 Fix: truncate message issue. (#5765)
### What problem does this PR solve?

Close #5761

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 16:33:25 +08:00
3418984848 Fix: meta fields updata issue, (#5764)
### What problem does this PR solve?

#4789

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 16:21:27 +08:00
3c79990934 Fix: Fixed the issue that files cannot be uploaded on the file management page. #5730 (#5763)
### What problem does this PR solve?

Fix: Fixed the issue that files cannot be uploaded on the file
management page. #5730

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 16:09:20 +08:00
da3f279495 Fix: add the validation for parser_config. (#5755)
### What problem does this PR solve?

#5719

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 15:34:34 +08:00
b1bbb9e210 Refa: make Rewrite component effective to relative data expression. (#5752)
### What problem does this PR solve?

#5716

### Type of change

- [x] Refactoring
2025-03-07 13:48:13 +08:00
0e3e129a83 Fix: Resolve inconsistency in APIToken dialog_id field definition (#5749)
The `dialog_id` field was inconsistently defined:
- In the `migrate_db()` function, it was set to `null=True`.
- In the model class, it was defined as `null=False`.

This inconsistency caused an issue during the initial deployment where
the database table did not allow `dialog_id` to be null. As a result,
calling `APITokenService.save(**obj)` in `system_app.py` raised the
following error:

```
peewee.IntegrityError: null value in column "dialog_id" violates not-null constraint
```

### What problem does this PR solve?

Error: peewee.IntegrityError: null value in column "dialog_id" violates
not-null constraint

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 13:26:08 +08:00
c87b58511e Fix: API empty field input. (#5748)
### What problem does this PR solve?

#5709

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 13:11:07 +08:00
8d61dcc8ab Fix: can not upload file close #5730 (#5742)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

close #5730 

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-03-07 11:24:23 +08:00
06b29d7da4 Fix: empty description (#5747)
### What problem does this PR solve?

#5705

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 11:23:37 +08:00
5229a76f68 Fix: Remove the document language parameter. #5640 (#5728)
### What problem does this PR solve?

Fix: Remove the document language parameter. #5686

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-07 11:03:58 +08:00
4f9504305a TEST: Added test cases for Create Dataset HTTP API (#5724)
### What problem does this PR solve?

1. add test cases
2. integrate workflows/tests.yml into CI pipeline

### Type of change

- [x] add testcases
2025-03-06 20:22:17 +08:00
27153dde85 Updated instructions in the UI (#5733)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-06 19:56:15 +08:00
9fc7174612 Fix: too long context during KG issue. (#5723)
### What problem does this PR solve?

#5088

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-06 19:21:07 +08:00
8fb8374dfc Fix: delimiter issue. (#5720)
### What problem does this PR solve?

#5704

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-06 17:51:22 +08:00
ff35c140dc Refa: remove dataset language and validate dataset name length. (#5707)
### What problem does this PR solve?

#5686
#5702

### Type of change

- [x] Refactoring
2025-03-06 17:08:28 +08:00
df9b7b2fe9 Fix: rerank issue. (#5696)
### What problem does this PR solve?

#5673

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-06 15:05:19 +08:00
48f3f49e80 Fix: docs inconsistency. (#5695)
### What problem does this PR solve?

#5662

### Type of change

- [x] Documentation Update
2025-03-06 11:48:31 +08:00
94d7af00b8 Fix: Remove the max token parameter. #5640 #5646 (#5693)
### What problem does this PR solve?

Fix: Remove the max token parameter. #5640 #5646

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-06 11:44:27 +08:00
251ba7f058 Refa: remove max tokens since no one needs it. (#5690)
### What problem does this PR solve?

#5646 #5640

### Type of change

- [x] Refactoring
2025-03-06 11:29:40 +08:00
28296955f1 Minor: improve tips display (#5631)
### What problem does this PR solve?

1. Add the missing translations.  
![CleanShot 2025-03-05 at 10 29
32](https://github.com/user-attachments/assets/85e95372-07d9-47a1-82cf-6eb4d0e1c831)

2. Shorten overly long tips.  
![CleanShot 2025-03-05 at 10 34
49](https://github.com/user-attachments/assets/fae8ce4c-6495-4abf-958d-2febeb38b893)

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe):
2025-03-06 11:03:49 +08:00
1b2fc3cc9a Feat: Add rerank option to huggingface's model type drop-down box. #5658 (#5689)
### What problem does this PR solve?

Feat: Add rerank option to huggingface's model type drop-down box. #5658

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-06 11:03:08 +08:00
b8da2eeb69 Feat: support huggingface re-rank model. (#5684)
### What problem does this PR solve?

#5658

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-06 10:44:04 +08:00
5f62f0c9d7 Miscellaneous updates (#5670)
### What problem does this PR solve?

#5625 #5614 

### Type of change


- [x] Documentation Update
2025-03-06 09:55:27 +08:00
a54843cc65 Feat: Use react-hook-form to synchronize the data of the categorize form to the agent node. #3221 (#5665)
### What problem does this PR solve?

Feat: Use react-hook-form to synchronize the data of the categorize form
to the agent node. #3221

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-03-05 19:43:08 +08:00
4326873af6 refactor: no need to inherit in python3 clean the code (#5659)
### What problem does this PR solve?

As title

### Type of change


- [x] Refactoring

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-03-05 18:03:53 +08:00
a64f4539e7 Docs: updates. (#5661)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2025-03-05 17:54:34 +08:00
ec68ab1c8c Fix: search citation issue. (#5657)
### What problem does this PR solve?
#5649
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 17:25:47 +08:00
e5041749a2 Fix: tavily search error. (#5653)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 17:03:05 +08:00
78b2e0be89 fix: issue #5600 (#5645)
fix: issue https://github.com/infiniflow/ragflow/issues/5600

### What problem does this PR solve?

close issue https://github.com/infiniflow/ragflow/issues/5600 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 16:50:37 +08:00
b6aded378d Feat: The parsing method is paper and needs to display Document parser. #5467 (#5652)
### What problem does this PR solve?

Feat: The parsing method is paper and needs to display Document parser.
#5467

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-05 16:25:34 +08:00
11e3f5e8b2 Feat: Upload file UI/UX enhancements (#5359)
### What problem does this PR solve?

Modifies the UX for uploading process on the website.

- Adds option to parse on creation the files
- Adds progress bar to display progress of chunk
- Adds per file feedback on uploading operation

#### Screenshots:

- Show files uploading:

![image](https://github.com/user-attachments/assets/a5693f42-8232-4d5c-a240-20ed343634a5)

- Errors on specific files

![image](https://github.com/user-attachments/assets/986a7f54-ab32-4634-89ab-a098fe1954aa)


### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2025-03-05 15:20:32 +08:00
f65c3ae62b Refactored DocumentService.update_progress (#5642)
### What problem does this PR solve?

Refactored DocumentService.update_progress

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 14:48:03 +08:00
02c955babb Fix: parameter error. (#5641)
### What problem does this PR solve?

#5600

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 14:37:51 +08:00
ca04ae9540 Minor: improve doc and rm unused file (#5634)
### What problem does this PR solve?

The `ocr.res` file is already included in the model directory
`rag/res/deepdoc`, but it doesn't seem to be utilized here.

### Type of change

- [x] Documentation Update
2025-03-05 12:59:54 +08:00
b0c21b00d9 Refactor: Optimize error handling and support parsing of XLS(EXCEL97—2003) files. (#5633)
Optimize error handling and support parsing of XLS(EXCEL97—2003) files.
2025-03-05 11:55:27 +08:00
47684fa17c Fix: image file can't preview (#5626)
### What problem does this PR solve?

![CleanShot 2025-03-05 at 10 12
28](https://github.com/user-attachments/assets/412b1663-5d65-4dca-9137-63d0ec5eaadd)
the preview botton of image not work for me.

request url:
`http://127.0.0.1:9222/document/af570920f80e11efb8e967fd67f0d8c7?ext=jpg&prefix=file`
response: `{"code":401,"data":null,"message":"<Unauthorized '401:
Unauthorized'>"}`


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-05 11:30:41 +08:00
148a7e7002 fix: issue #5600 (#5620)
### What problem does this PR solve?

close issue #5600 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-03-05 11:10:04 +08:00
76e8285904 use to_df replace to_pl when get infinity Result (#5604)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Performance Improvement

---------

Co-authored-by: wangwei <dwxiayi@163.com>
2025-03-05 09:35:40 +08:00
555c70672e Fix:Fix the bug of incorrectly gets the APIToken. (#5597)
### What problem does this PR solve?

Fix the issue where, when getting a user's APIToken, if the user is part
of another user's team, it incorrectly gets the Team owner's APIToken
instead.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-04 19:35:42 +08:00
850e218051 Feat: Render DynamicCategorize with shadcn-ui. #3221 (#5610)
### What problem does this PR solve?

Feat: Render DynamicCategorize with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-04 19:31:32 +08:00
fb4b5b0a06 Added 0.17.0 release notes (#5608)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-04 19:21:28 +08:00
f256e1a59a Feat: Render MessageForm with shadcn-ui. #3221 (#5596)
### What problem does this PR solve?

Feat: Render MessageForm with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-04 15:47:05 +08:00
9816b868f9 Docs: about meta files in API reference. (#5594)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2025-03-04 15:43:09 +08:00
6e828f0fcb Fix: better start experience PYTHONPATH in shell (#5593)
### What problem does this PR solve?

As title export PYTHONPATH in the shell

### Type of change

- [x] Refactoring

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-03-04 15:23:44 +08:00
4d6484b03e Fix nursery.start_soon. Close #5575 (#5591)
### What problem does this PR solve?

Fix nursery.start_soon. Close #5575

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-04 14:46:54 +08:00
afe9269534 Introduced jemalloc (#5590)
### What problem does this PR solve?

Introduced jemalloc.
Python uses pymalloc (which is an reimplementation of gblibc malloc) to
manage RES. It has pools for small objects to avoid returning memory to
OS aggressively. My experience is: Replacing pymalloc with
[jemalloc](https://github.com/jemalloc/jemalloc) can reduce RES and
speedup task_executor.py.

### Type of change

- [x] Performance Improvement
2025-03-04 12:49:39 +08:00
688cb8f19d Fix: remove KB id restriction while creating chat. (#5588)
### What problem does this PR solve?

#5586

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-04 12:36:37 +08:00
f6dd2cd1af Fix: fix may lose part of information of last stream chunck (#5584)
### What problem does this PR solve?

 Fix may lose part of information of last stream chunck

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-04 11:58:10 +08:00
69dc14f5d6 Add separate API service resource to Helm chart (#5572)
### What problem does this PR solve?

Adds a new Kubernetes Service resource to the Helm chart which
specifically targets the RAGFlow API. This feature useful for cases
where you want to expose the RAGFlow HTTP API separately from the web
interface, for example if RAGFlow is running behind an authenticating
proxy it allows a route to bypass the proxy (e.g. by defining a separate
ingress resource which forwards to the separate API-only k8s service
added here) to provide RAGFlow API access. This is still secure since
API access is already authenticated by API keys inside RAGFlow itself.

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2025-03-04 11:35:43 +08:00
202acbd628 Perf: update novita.ai LLM library (#5574)
### What problem does this PR solve?

LLM library update

### Type of change

- [x] Other : config update
2025-03-04 11:35:25 +08:00
a283fefd18 Fix: LLM with ___ return cannot be deleted #5585 (#5587)
### What problem does this PR solve?

Fix: LLM with ___ return cannot be deleted #5585

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-04 11:35:12 +08:00
d9bbaf5d6c Minor: Fixed broken links (#5565)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-03-03 19:24:28 +08:00
1075b975c5 Feat: Render WikipediaForm and BaiduForm with shadcn-ui. #3221 (#5564)
### What problem does this PR solve?

Feat: Render WikipediaForm and BaiduForm with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-03 19:01:15 +08:00
c813c1ff4c Made task_executor async to speedup parsing (#5530)
### What problem does this PR solve?

Made task_executor async to speedup parsing

### Type of change

- [x] Performance Improvement
2025-03-03 18:59:49 +08:00
abac2ca2c5 Feat: add toc to api doc (#5552)
### What problem does this PR solve?

the api doc is too long,  add a toc might be better

![CleanShot 2025-03-03 at 16 53
17](https://github.com/user-attachments/assets/9dfbc682-fdbf-4b37-8a01-87049db51f86)


### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-03-03 18:54:01 +08:00
64e9702a26 Feat: Render QWeatherForm with shadcn-ui. #3221 (#5558)
### What problem does this PR solve?

Feat: Render QWeatherForm with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-03 17:59:55 +08:00
76cb4cd174 Feat: add 'delete' for agent's sessions api and unify apis of agent sdk (#5525)
### What problem does this PR solve?

Add sessions deletion support for agent in http and python api

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-03-03 17:15:16 +08:00
65d7c19979 Feat: Render RewriteQuestionForm with shadcn-ui #3221 (#5551)
### What problem does this PR solve?

Feat: Render RewriteQuestionForm with shadcn-ui #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-03 17:14:19 +08:00
b67697b6f2 Restructured guides (#5555)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-03-03 17:13:37 +08:00
131f272e69 Feat: Combine Select and LlmSettingFieldItems into LLMSelect. #3221 (#5548)
### What problem does this PR solve?

Feat: Combine Select and LlmSettingFieldItems into LLMSelect. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-03 15:44:37 +08:00
03d1265cfd Restructured guides (#5549)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2025-03-03 15:42:39 +08:00
c190086707 Fix: bad case for tokenizer. (#5543)
### What problem does this PR solve?

#5492

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-03 15:36:16 +08:00
5d89a8010b Feat: Add NextLLMSelect with shadcn-ui. #3221 (#5542)
### What problem does this PR solve?
Feat: Add NextLLMSelect with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-03-03 13:54:06 +08:00
7a81fa00e9 Optimize prompt. (#5541)
### What problem does this PR solve?

#5526

### Type of change

- [x] Performance Improvement
2025-03-03 13:12:38 +08:00
606ed0c8ab Fix: in case running KG repeatly. (#5538)
### What problem does this PR solve?

#5512

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-03-03 12:22:36 +08:00
8b1a4365ed Fix email validation regex (#5533)
### What problem does this PR solve?

This pull request aims to fix a bug that prevents certain email
addresses from signing up. The affected TLDs were returning 'invalid
email address' errors:

.museum
.software
.photography
.technology
.marketing
.education
.international
.community
.construction
.government
.consulting
....

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2025-03-03 10:55:10 +08:00
8a2542157f Fix: possible memory leaks close #5277 (#5500)
### What problem does this PR solve?

close #5277 by make sure the file close

### Type of change

- [x] Performance Improvement

---------

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-03-03 10:26:45 +08:00
d6836444c9 DOC: for release. (#5472)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update

---------

Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2025-03-02 18:47:06 +08:00
3b30799b7e minor (#5497)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-02-28 19:36:50 +08:00
e61da33672 Moved agent components into the agent folder (#5496)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-28 19:27:57 +08:00
6a71314d70 Feat: Add the Experimental text to the option of the large model of the Image2text type of LayoutRecognizeItem (#5495)
### What problem does this PR solve?
Feat: Add the Experimental text to the option of the large model of the
Image2text type of LayoutRecognizeItem

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-28 18:44:04 +08:00
06e0c7d1a9 Feat: multiline text input for chat (#5317)
### What problem does this PR solve?

Improves the chat interface by adding a multiline chat area that grows
when multiple lines exists.

Some images:

* Empty:
<img width="1334" alt="image"
src="https://github.com/user-attachments/assets/e8a68b46-def9-45af-b5b1-db0f0b67e6d8"
/>

* With multiple lines and documents:
<img width="1070" alt="image"
src="https://github.com/user-attachments/assets/ff976c5c-08fa-492f-9fc0-17512c95f9f2"
/>


### Type of change
- [X] New Feature (non-breaking change which adds functionality)
2025-02-28 18:05:50 +08:00
7600ebd263 Feat: Hide the suffix of the large model name. #5433 (#5494)
### What problem does this PR solve?

Feat: Hide the suffix of the large model name. #5433

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-28 18:02:33 +08:00
21943ce0e2 Refine error message while embedding model error, (#5490)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-02-28 17:52:38 +08:00
aa313e112a Feat: Wrap MaxTokenNumber with DatasetConfigurationContainer. #5467 (#5491)
### What problem does this PR solve?

Feat: Wrap MaxTokenNumber with DatasetConfigurationContainer. #5467

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-28 17:52:18 +08:00
2c7428e2ee Feat: Put the configuration of different parsing methods into separate components. #5467 (#5487)
### What problem does this PR solve?

Feat: Put the configuration of different parsing methods into separate
components. #5467

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-28 16:54:04 +08:00
014f2ef900 Fix typo and error (#5479)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-02-28 16:09:40 +08:00
b418ce5643 Fix table parser issue. (#5482)
### What problem does this PR solve?

#1475
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-28 16:09:12 +08:00
fe1c48178e Refa: better gitignore (#5473)
### What problem does this PR solve?

when develop ragflow local there would be a hash file generate that is
kind of not good for develop
this patch add a regex to `.gitignore` for better developing 

### Type of change

- [x] Refactoring

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-02-28 15:07:39 +08:00
35f13e882e Fix typos (#5476)
### What problem does this PR solve?

Fix lots of typos.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-02-28 15:01:54 +08:00
85924e898e Fix: enhance aliyun oss access with adding prefix path (#5475)
### What problem does this PR solve?

Enhance aliyun oss access with adding prefix path.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-28 15:00:00 +08:00
622b72db4b Fix: add ctrl+c signal for better exit (#5469)
### What problem does this PR solve?

This patch add signal for ctrl + c that can exit the code friendly
cause code base use thread daemon can not exit friendly for being
started.

how to reproduce
1. docker-compose -f docker/docker-compose-base.yml up
2. other window `bash docker/launch_backend_service.sh`
3. stop 1 first
4. try to stop 2 then two thread can not exit which must use `kill pid`

This patch fix it 
and should fix most the related issues in the `issues`

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-02-28 14:52:40 +08:00
a0a7b46cff DOCS: amend docker image building page and more hints for mac users (#5461)
### What problem does this PR solve?

Amend docker image building page and more hints for mac users

### Type of change

- [x] Documentation Update
2025-02-28 14:46:22 +08:00
37aacb3960 Refa: drop useless fasttext (#5470)
### What problem does this PR solve?

This patch drop useless fastext which is seems useless in the code base 
and its very kind of hard install
should close #4498


### Type of change

- [x] Refactoring

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-02-28 14:30:56 +08:00
79bc9d97c9 Refa: better service conf (#5471)
### What problem does this PR solve?

This patch fix most of the issues like #4853 #5038 and so on

the root reason is that we need to add the hostname to the `/etc/hosts`
which is not wrote in main README
and the code side read `conf/service_conf.yaml` as settings 
and its hard for developers to debug, this patch fix it, or maybe can
discuss better solution here
 
### Type of change

- [x] Refactoring

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-02-28 14:28:00 +08:00
f150687dbc Fix: language selection display on the profile settings page (#5459)
### What problem does this PR solve?

Improve the language selection display on the profile settings page.

| before | after |
| --- | --- |
|![截屏2025-02-28 上午8 46
54](https://github.com/user-attachments/assets/0924275c-99d4-4ddd-8935-693286c0d07f)|![CleanShot
2025-02-28 at 09 58
21](https://github.com/user-attachments/assets/a96c9d73-8e16-40a8-aa80-d31fecc18edf)|

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-28 11:20:52 +08:00
b2a5482d2c Feat: Modify the parsing method string to an enumeration type. #5467 (#5468)
### What problem does this PR solve?

Feat: Modify the parsing method string to an enumeration type. #5467

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-28 11:13:56 +08:00
5fdfb8d465 Fix: rm think if stream is Flase. (#5458)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-28 10:05:18 +08:00
8b2c04abc4 Feat: If the user is not logged in, jump to the login page by refreshing. (#5451)
### What problem does this PR solve?

Feat: If the user is not logged in, jump to the login page by
refreshing.
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-27 18:48:53 +08:00
83d0949498 Fix: fix special delimiter parsing issue (#5448)
### What problem does this PR solve?

Fix special delimiter parsing issue #5382 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-27 18:33:55 +08:00
244cf49ba4 Feat: Use shadcn-ui to build GenerateForm. #3221 (#5449)
### What problem does this PR solve?

Feat: Use shadcn-ui to build GenerateForm. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-27 18:13:41 +08:00
651422127c Feat: Accessing Alibaba Cloud OSS with Amazon S3 SDK (#5438)
Accessing Alibaba Cloud OSS with Amazon S3 SDK
2025-02-27 17:02:42 +08:00
11de7599e5 Feat: add data type invoke (#5126)
### What problem does this PR solve?
```
Invoke agent
To be able to interact dynamically with the API, there is a customizable Data Type JSON or FormData, the default is JSON 
```

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-27 16:15:33 +08:00
7a6e70d6b3 Feat: Wrap DynamicVariableForm with Collapsible. #3221 (#5440)
### What problem does this PR solve?

Feat: Wrap DynamicVariableForm with Collapsible. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-27 16:09:12 +08:00
230865c4f7 Fix: stream post body (#5434)
### What problem does this PR solve?

Fix stream post body

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-27 16:08:54 +08:00
4c9a3e918f Fix: add image2text issue. (#5431)
### What problem does this PR solve?

#5356

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-27 14:06:49 +08:00
5beb022ee1 Fix: string format error. (#5422)
### What problem does this PR solve?

#5404

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-27 12:01:46 +08:00
170abf9b7f Fix: drop useless ABC method (#5408)
### What problem does this PR solve?

seems  no need use ABC here, there's no `abstractmethod` here

### Type of change

- [x] Performance Improvement

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
2025-02-27 11:03:21 +08:00
afaa7144a5 Fix: issue of no id for /datasets/<dataset_id>/documents (#5420)
### What problem does this PR solve?

#5401

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-27 10:39:34 +08:00
eaa1adb3b2 ci: remove may expand into attacker-controllable code (#5407)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

This patch remove dangerous code that `may expand into
attacker-controllable code`

more:

```cli
error[template-injection]: code injection via template expansion
  --> /Users/hyi/prs/ragflow/.github/workflows/tests.yml:35:9
   |
35 |         - name: Show PR labels
   |           ^^^^^^^^^^^^^^^^^^^^ this step
36 |           run: |
   |  _________^
37 | |           echo "Workflow triggered by ${{ github.event_name }}"
38 | |           if [[ ${{ github.event_name }} == 'pull_request' ]]; then
39 | |             echo "PR labels: ${{ join(github.event.pull_request.labels.*.name, ', ') }}"
40 | |           fi
   | |____________^ github.event.pull_request.labels.*.name may expand into attacker-controllable code
   |
   = note: audit confidence → High

```

using zizmor to check 
https://woodruffw.github.io/zizmor/

but this patch do not fix them all, just remove high audit confidence →
High

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe):

---------

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2025-02-27 10:20:04 +08:00
fa76974e24 Fix issue of ask API. (#5400)
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-26 19:45:22 +08:00
f372bd8809 Miscelleneous editorial updates (#5390)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-02-26 19:03:50 +08:00
0284248c93 Fix: correct wrong vLLM rerank model (#5399)
### What problem does this PR solve?

Correct wrong vLLM rerank model #4316 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-26 18:59:36 +08:00
d9dd1171a3 Feat: Support vLLM #4316 (#5395)
### What problem does this PR solve?
Feat: Support vLLM #4316

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 18:33:43 +08:00
fefea3a2a5 Fixed OpenAI compatibility stream [DONE] (#5389)
Fixed OpenAI compatibility stream [DONE]



- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-26 17:55:12 +08:00
0e920a91dd FIX: correct typo (#5387)
### What problem does this PR solve?

Correct typo in supported_models file

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-26 17:21:09 +08:00
63e3398f49 Feat: Add DualRangeSlider #3221 (#5386)
### What problem does this PR solve?

Feat: Add DualRangeSlider #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 17:02:42 +08:00
cdcaae17c6 Feat: add VLLM (#5380)
### What problem does this PR solve?

Read to add VLMM.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 16:04:53 +08:00
96e9d50060 Let parallism of RAPTOR controlable. (#5379)
### What problem does this PR solve?

#4874
### Type of change

- [x] Refactoring
2025-02-26 15:58:06 +08:00
k
5cab6c4ccb Fix:HTTP API -> Stop parsing documents(AttributeError: ‘list‘ object … (#5375)
…has no attribute ‘id‘)

### What problem does this PR solve?

No PR

![image](https://github.com/user-attachments/assets/988d31bc-6551-4bb8-846c-cbbc1883d804)


![image](https://github.com/user-attachments/assets/8b09681b-1239-4ed9-8bc3-11436c5e90bc)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2025-02-26 15:57:50 +08:00
b3b341173f DOCS: add OpenAI-compatible http and python api reference (#5374)
### What problem does this PR solve?

Add OpenAI-compatible http and python api reference

### Type of change

- [x] Documentation Update

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-02-26 15:52:26 +08:00
a9e4695b74 Fix:validate knowledge base association before document upload (#5373)
### What problem does this PR solve?

fix this bug: https://github.com/infiniflow/ragflow/issues/5368

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-02-26 15:47:34 +08:00
4f40f685d9 Code refactor (#5371)
### What problem does this PR solve?

#5173

### Type of change

- [x] Refactoring
2025-02-26 15:40:52 +08:00
ffb4cda475 Run keyword_extraction, question_proposal, content_tagging in thread pool (#5376)
### What problem does this PR solve?

Run keyword_extraction, question_proposal, content_tagging in threads

### Type of change

- [x] Performance Improvement
2025-02-26 15:21:14 +08:00
5859a3df72 Feat: Add FormSheet. #3221 (#5377)
### What problem does this PR solve?

Feat: Add FormSheet. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 15:03:09 +08:00
5c6a7cb4b8 Added OpenAI-like completion api (#5351)
### What problem does this PR solve?

Added OpenAI-like completion api, related to #4672, #4705 

This function allows users to interact with a model to get responses
based on a series of messages.
If `stream` is set to True, the response will be streamed in chunks,
mimicking the OpenAI-style API.

#### Example usage:

```bash
curl -X POST https://ragflow_address.com/api/v1/chats_openai/<chat_id>/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $RAGFLOW_API_KEY" \
    -d '{
        "model": "model",
        "messages": [{"role": "user", "content": "Say this is a test!"}],
        "stream": true
    }'
```

Alternatively, you can use Python's `OpenAI` client:

```python
from openai import OpenAI

model = "model"
client = OpenAI(api_key="ragflow-api-key", base_url=f"http://ragflow_address/api/v1/chats_openai/<chat_id>")

completion = client.chat.completions.create(
    model=model,
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who you are?"},
        {"role": "assistant", "content": "I am an AI assistant named..."},
        {"role": "user", "content": "Can you tell me how to install neovim"},
    ],
    stream=True
)

stream = True
if stream:
    for chunk in completion:
        print(chunk)
else:
    print(completion.choices[0].message.content)
```
### Type of change
- [x] New Feature (non-breaking change which adds functionality)

### Related Issues
Related to #4672, #4705
2025-02-26 11:37:29 +08:00
4e2afcd3b8 Fix FlagRerank max_length issue. (#5366)
### What problem does this PR solve?

#5352

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-26 11:01:13 +08:00
11e6d84d46 Fix: 'Chunk not found!' error in team-sharing knowledge base. (#5361)
### What problem does this PR solve?

As issue #3268 mentioned, "Chun not found!" exception will occur,
especially during the teamwork of knowledge bases.

### The reason of this bug

"tenants" are the people on current_user's team, including the team
owner itself. The old one only checks the first "tenant", tenants[0],
which will cause error when anyone editing the chunk that is not in
tenants[0]'s knowledge base.

My modification won't introduce new errors while iterate all the tenant
then retrieve knowledge bases of each.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-26 10:24:35 +08:00
53b9e7b52f Add tavily as web searh tool. (#5349)
### What problem does this PR solve?

#5198

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 10:21:04 +08:00
e5e9ca0015 Feat: Add Tavily Api Key to chat configuration modal. #5198 (#5347)
### What problem does this PR solve?

Feat: Add Tavily Api Key to chat configuration modal. #5198

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-26 10:20:40 +08:00
150ab9c6a4 Fix: Prevent message sending during IME composition and block new submissions while waiting for a response (#5331)
### What problem does this PR solve?

This pull request addresses an issue where the "Enter" key would send
the message prematurely while using Input Method Editor (IME) for text
composition. This problem occurs when users are typing with a non-Latin
input method, such as Chinese(Zhuyin), and press "Enter" to confirm
their selection, which unintentionally triggers message submission. Also
fixed the issue of blocking new submissions while waiting for a response

Before:


https://github.com/user-attachments/assets/233f3ac9-4b4b-4424-b4ab-ea2e31bb0663

After:


https://github.com/user-attachments/assets/f1c01af6-d1d7-4a79-9e81-5bdf3c0b3529

Block new submissions while waiting for a response:



https://github.com/user-attachments/assets/10a45b5f-44b9-4e36-9342-b1bbb4096312


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 18:49:08 +08:00
f789463982 Fix: Due to the reference to tailwindcss, the height attribute setting of the image is invalid, resulting in an uneven model list #5339 (#5340)
### What problem does this PR solve?

Fix: Due to the reference to tailwindcss, the height attribute setting
of the image is invalid, resulting in an uneven model list #5339

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 17:52:31 +08:00
955801db2e Resolve super class invokation error. (#5337)
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 17:42:29 +08:00
93b2e80eb8 Feat: Add DynamicVariableForm with shadcn-ui. #3221 (#5336)
### What problem does this PR solve?

Feat: Add DynamicVariableForm with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-25 16:57:46 +08:00
1a41b92f77 More robust community report. (#5328)
### What problem does this PR solve?

#5289
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 12:58:10 +08:00
58a8f1f1b0 Fix release.yml (#5327)
### What problem does this PR solve?

Fix release.yml

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 12:41:34 +08:00
daddfc9e1b Remove dup gb2312, solve currupt error. (#5326)
### What problem does this PR solve?

#5252 
#5325

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 12:22:37 +08:00
ecf5f6976f Make node merging parallel. (#5324)
### What problem does this PR solve?

#5314

### Type of change

- [x] Performance Improvement
2025-02-25 12:02:44 +08:00
e2448fb6dd Fix: type-script new change (#5159)
### What problem does this PR solve?
```
fixed type-script on MessageInput change to TextArea
```
_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-25 11:42:31 +08:00
9c9f2dbe3f Feat: Add FormDrawer to agent page. #3221 (#5323)
### What problem does this PR solve?

Feat: Add FormDrawer to agent page. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-25 11:32:01 +08:00
b3d579e2c1 Refine prompt of agentic search. (#5312)
### What problem does this PR solve?

#5173

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-25 09:21:52 +08:00
eb72d598b1 Replaced pypi.tuna.tsinghua.edu.cn with mirrors.aliyun.com/pypi (#5309)
### What problem does this PR solve?

Replaced pypi.tuna.tsinghua.edu.cn with mirrors.aliyun.com/pypi.
I notice aliyun.com sometimes is much faster than tsinghua.edu.

### Type of change

- [x] Refactoring
2025-02-24 20:15:40 +08:00
033a4cf21e Feat: Upload agent file #3221 (#5311)
### What problem does this PR solve?

Feat: Upload agent file #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 19:30:33 +08:00
fda9b58ab7 Feat: Render agent details #3221 (#5307)
### What problem does this PR solve?

Feat: Render agent details #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 17:19:06 +08:00
ca865df87f Feat: Render operator menu by category. #3221 (#5302)
### What problem does this PR solve?
Feat: Render operator menu by category. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 16:51:44 +08:00
f9f75aa119 Added a file size limit (#5301)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-24 16:38:11 +08:00
db42d0e0ae Optimize ocr (#5297)
### What problem does this PR solve?

Introduced OCR.recognize_batch

### Type of change

- [x] Performance Improvement
2025-02-24 16:21:55 +08:00
df3d0f61bd Fix base url missing for deepseek from Tongyi. (#5294)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-24 15:43:32 +08:00
c6bc69cbc5 Feat: Add AgentSidebar #3221 (#5296)
### What problem does this PR solve?

Feat: Add AgentSidebar #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 15:43:20 +08:00
8c9df482ab Added a prerequisite for ARM platforms (#5295)
### What problem does this PR solve?

#5114 

### Type of change


- [x] Documentation Update
2025-02-24 15:15:11 +08:00
1137b04154 Feat: Disable Max_token by default #5283 (#5290)
### What problem does this PR solve?

Feat: Disable Max_token by default #5283

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 14:22:15 +08:00
ec96426c00 Tongyi adapts deepseek. (#5285)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 14:04:25 +08:00
4d22daefa7 Feat: Add PageHeader to DatasetWrapper #3221 (#5284)
### What problem does this PR solve?

Feat: Add PageHeader to DatasetWrapper #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-24 13:50:21 +08:00
bcc92e04c9 Remove <think> content for Generate if it's not stream output. (#5281)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-02-24 13:44:11 +08:00
9aa222f738 Let list_chat go without kb checking. (#5280)
### What problem does this PR solve?

#5278 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-24 13:21:05 +08:00
605cfdb8dc Refine error message for re-rank model. (#5278)
### What problem does this PR solve?

#5261

### Type of change

- [x] Refactoring
2025-02-24 13:01:34 +08:00
041d72b755 Refine the error message. (#5275)
### What problem does this PR solve?

#5265

### Type of change

- [x] Refactoring
2025-02-24 12:42:52 +08:00
569e40544d Refactor rerank model with dynamic batch processing and memory manage… (#5273)
…ment

### What problem does this PR solve?
Issue:https://github.com/infiniflow/ragflow/issues/5262
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-02-24 11:32:08 +08:00
3d605a23fe Feat: add partition of file uploads (#5248)
### What problem does this PR solve?

Partitions the upload of documents in parts of 20 to avoid the size
limit error. Allows uploading 100s of documents on a single interaction.

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2025-02-24 11:12:12 +08:00
4f2816c01c Add support to boto3 default connection (#5246)
### What problem does this PR solve?
 
This pull request includes changes to the initialization logic of the
`ChatModel` and `EmbeddingModel` classes to enhance the handling of AWS
credentials.

Use cases:
- Use env variables for credentials instead of managing them on the DB 
- Easy connection when deploying on an AWS machine

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2025-02-24 11:01:14 +08:00
a0b461a18e Add configuration to choose default llm models (#5245)
### What problem does this PR solve?

This pull request includes changes to the `api/settings.py` and
`docker/service_conf.yaml.template` files to add support for default
models in the LLM configuration (specially for LIGHTEN builds). The most
important changes include adding default model configurations and
updating the initialization settings to use these defaults.

For example:
With this configuration Bedrock will be enable by default with claude
and titan embeddings.

```
user_default_llm:
  factory: 'Bedrock'
  api_key: '{}' 
  base_url: ''
  default_models:
    chat_model: 'anthropic.claude-3-5-sonnet-20240620-v1:0'
    embedding_model: 'amazon.titan-embed-text-v2:0'
    rerank_model: ''
    asr_model: ''
    image2text_model: ''
```


### Type of change

- [X] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-24 10:13:39 +08:00
7ce675030b Support downloading models from ModelScope Community. (#5073)
This PR supports downloading models from ModelScope. The main
modifications are as follows:
-New Feature (non-breaking change which adds functionality)
-Documentation Update

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-24 10:12:20 +08:00
217caecfda Added a guide on running a retrieval test, with and without knowledge graph (#5200)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-21 19:36:20 +08:00
ef8847eda7 Double check error of adding llm. (#5237)
### What problem does this PR solve?

#5227

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 19:09:49 +08:00
d78010c376 Fixed similarity on infinity (#5236)
### What problem does this PR solve?

Fixed similarity on infinity

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 18:50:54 +08:00
3444cb15e3 Refine search query. (#5235)
### What problem does this PR solve?

#5173
#5214

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 18:32:32 +08:00
0151d42156 Reuse loaded modules if possible (#5231)
### What problem does this PR solve?

Reuse loaded modules if possible

### Type of change

- [x] Refactoring
2025-02-21 17:21:01 +08:00
392f28882f Feat: Add RAGFlowSelect component #3221 (#5228)
### What problem does this PR solve?

Feat: Add RAGFlowSelect component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-21 16:37:50 +08:00
cdb3e6434a Fix empty question issue. (#5225)
### What problem does this PR solve?

#5241

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 15:47:39 +08:00
bf5f6ec262 Fix spelling errors (#5224)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 15:47:27 +08:00
1a755e75c5 Remove v1 (#5220)
### What problem does this PR solve?

#5201

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 15:15:38 +08:00
46ff897107 Feat: Chat without KB. #5216 (#5217)
### What problem does this PR solve?
Feat: Chat without KB. #5216

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-21 12:24:13 +08:00
f5d63bb7df Support chat solo. (#5218)
### What problem does this PR solve?

#5216

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-21 12:24:02 +08:00
c54ec09519 Fix session.ask return generator bug when stream=False on python sdk (#5209)
add non-stream mode support to session.ask function

### What problem does this PR solve?

same as title, I do not know why the stream=False is not work on the
server side also, when stream=False, the response in the
session._ask_chat is a fully connnected SSE string.

This is a quick fix on the sdk side to make the response format align
with API docs

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-21 11:50:08 +08:00
7b3d700d5f Apply agentic searching. (#5196)
### What problem does this PR solve?

#5173

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 17:41:01 +08:00
744ff55c62 Feat: Add AgentTemplates component. #3221 (#5194)
### What problem does this PR solve?

Feat: Add AgentTemplates component. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 17:02:42 +08:00
c326f14fed Optimized Recognizer.sort_X_firstly and Recognizer.sort_Y_firstly (#5182)
### What problem does this PR solve?

Optimized Recognizer.sort_X_firstly and Recognizer.sort_Y_firstly

### Type of change

- [x] Performance Improvement
2025-02-20 15:41:12 +08:00
07ddb8fcff Feat: Add SearchPage component. #3221 (#5184)
### What problem does this PR solve?

Feat: Add SearchPage component. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 15:37:53 +08:00
84bcd8b3bc Feat: Add agent page. #3221 (#5179)
### What problem does this PR solve?

Feat: Add agent page. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 15:02:53 +08:00
f52970b038 Feat: Add reasoning item to chat configuration modal #5173 (#5177)
### What problem does this PR solve?

Feat: Add reasoning item to chat configuration modal #5173

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 14:05:52 +08:00
39b96849a9 Fix window size issue of ES. (#5175)
### What problem does this PR solve?

#5152

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-20 12:54:29 +08:00
f298e55ded Fix: Normalize embedding model ID comparison across datasets (#5169)
Modify embedding model ID comparison to remove vendor suffixes, ensuring
consistent model identification when working with multiple knowledge
bases. This change affects dialog creation, chat operations, and
document retrieval test functions.

### What problem does this PR solve?

resolve this bug: https://github.com/infiniflow/ragflow/issues/5166

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-02-20 12:40:59 +08:00
ed943b1b5b Feat: Show formulas when answering, show reference labels in style, remove cursor flashing effect. #5173 (#5174)
### What problem does this PR solve?

Feat: Show formulas when answering, show reference labels in style,
remove cursor flashing effect. #5173

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-20 12:19:53 +08:00
0c6d787f92 Iframe should support input variables (#5156)
### What problem does this PR solve?

Right now we cannot embed a chat in website when it has variables in the
begin component.
This PR tries to read the variables values from the query string via a
data_ prefixed variable.

#5016 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: gstrat88 <gstrat@innews.gr>
2025-02-20 11:52:44 +08:00
a4f9aa2172 Fix: Improve message input handling with Shift+Enter support (#5129)
### What problem does this PR solve?

just resolve issue: [Improve message input handling with Shift+Enter
support](https://github.com/infiniflow/ragflow/issues/5116)
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
2025-02-19 19:32:35 +08:00
c432ce6be5 Feat: Add insert variable icon in the header of prompt editor. #4764 (#5142)
### What problem does this PR solve?

Feat: Add insert variable icon in the header of prompt editor. #4764

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-19 19:20:00 +08:00
c5b32b2211 Docs: Add note about docker volume deletion in README files,will be more novice-friendly (#5133)
### What problem does this PR solve?


Docs: Add note about docker volume deletion in README files
refer to this question:
https://github.com/infiniflow/ragflow/issues/5132
### Type of change

- [x] Documentation Update

---------

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-02-19 16:51:33 +08:00
24efa86f26 Feat: Support preview of HTML files #5096 (#5134)
### What problem does this PR solve?

Feat: Support preview of HTML files #5096
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-19 16:28:48 +08:00
38e551cc3d Feat: Allow the Rewrite operator to connect to the Generate operator #1739 (#5128)
### What problem does this PR solve?

Feat: Allow the Rewrite operator to connect to the Generate operator
#1739

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-19 15:47:48 +08:00
ef95f08c48 Remove redandent code. (#5121)
### What problem does this PR solve?

#5107

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-19 15:46:52 +08:00
3ced290eb5 Feat: Add support for document meta fields update through api (#5120)
### What problem does this PR solve?

add support for update document meta data through  api
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: wenju.li <wenju.li@deepctr.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-19 13:39:31 +08:00
fab0f07379 fix: Ensure that the commands are executed in the correct directory s… (#5089)
…o that all services (including the es and infinity containers) can be
started correctly, and resolve the Failed to resolve 'es01' #4875

### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/4875

### Type of change

- [x] Documentation Update
2025-02-19 13:19:36 +08:00
8525f55ad0 Fix: Option ineffective in Chat API (#5118)
### What problem does this PR solve?

API options like `stream` was ignored when no session_id was provided.

This PR fixes the issue.

Test command and expected result:
```
curl  --request POST \
     --url http://:9222/api/v1/chats/2f2e1d30ee6111efafe211749b004925/completions \
     --header 'Content-Type: application/json' \
     --header 'Authorization: Bearer ragflow-xxx' \
     --data '{
   "question":"Who are you",
   "stream":false
}'
{"code":0,"data":"data:{\"code\": 0, \"message\": \"\", \"data\": {\"answer\": \"Hi! I'm your assistant, what can I do for you?\", \"reference\": {}, \"audio_binary\": null, \"id\": null, \"session_id\": \"82ceb0fcee7111efafe211749b004925\"}}\n\n"}

```



### Type of change

- [*] Bug Fix (non-breaking change which fixes an issue)
2025-02-19 13:18:51 +08:00
e6c024f8bf Fix too many clause while searching. (#5119)
### What problem does this PR solve?

#5100

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-19 13:18:39 +08:00
c28bc41a96 Fix docx table issue. (#5117)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-19 12:40:06 +08:00
29a59ed7e2 Fix: Use self.dataStore.indexExist in all_tags method of Dealer (#5108)
### What problem does this PR solve?

This PR fixes an AttributeError in the all_tags method of the Dealer
class. Previously, the method incorrectly called
self.docStoreConn.indexExist instead of self.dataStore.indexExist. Since
self.docStoreConn was never set (and self.dataStore is already
initialized in init), this resulted in an error when attempting to check
if the index exists. This change ensures that the proper connector is
used for the index existence check, thereby resolving the issue._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-19 11:50:57 +08:00
f8b80f3f93 Feat: Write the thinking style in the MarkdownContent layer #4930 (#5091)
### What problem does this PR solve?

Feat: Write the thinking style in the MarkdownContent layer #4930

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-18 19:34:54 +08:00
189007e44d Fix: PUT method does not work as expected with Invoke component (#5081)
### What problem does this PR solve?
Invoke component can be used to call third party services.
Tried GET/POST/PUT from web UI, and found PUT request failed like this:
(test api: api/v1/chats/<assistant_id>)
 ```
{"code":100,"data":null,"message":"AttributeError("'NoneType' object has
no attribute 'get'")"}
```

Root cause: Invoke PUT with a 'data=args' parameter, which is a form-encoded data, however the default content type setting of request header is application/json. The test api could not deal with such case.

Fix: use the 'json' parameter of reqeusts.put(), same as Invoke POST. Do not use the 'data' parameter.
Another way is to use 'data=json.dumps(args)'.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-18 19:34:22 +08:00
3cffadc7a2 Added an FAQ (#5092)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-02-18 19:29:40 +08:00
18e43831bc Feat: Add ChunkedResultPanel #3221 (#5085)
### What problem does this PR solve?

Feat: Add ChunkedResultPanel #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-18 17:53:51 +08:00
3356de55ed Fix: Chunk problem tag content cannot be displayed completely. #5076 (#5077)
### What problem does this PR solve?

Fix: Chunk problem tag content cannot be displayed completely. #5076

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-18 15:26:24 +08:00
375e727f9a Feat: Extract the common parts of groupImage2TextOptions and groupOptionsByModelType #5063 (#5074)
### What problem does this PR solve?

Feat: Extract the common parts of groupImage2TextOptions and
groupOptionsByModelType #5063

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-18 15:13:55 +08:00
a2b8ba472f Feat: Add LanguageAbbreviation to simplify language resource files. #5065 (#5072)
### What problem does this PR solve?

Feat: Add LanguageAbbreviation to simplify language resource files.
#5065

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-18 15:06:53 +08:00
00c7ddbc9b Fix: The max tokens defined by the tenant are not used (#4297) (#2817) (#5066)
### What problem does this PR solve?

Fix: The max tokens defined by the tenant are not used (#4297) (#2817)


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-18 13:42:22 +08:00
3e0bc9e36b Added a graphrag guide (#4978)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-18 13:42:06 +08:00
d6ba4bd255 add option Embed into webpage (#5065)
add option Embed into webpage

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-18 13:41:19 +08:00
84b4b38cbb Remove <think> for exeSql component. (#5069)
### What problem does this PR solve?

#5061
#5067

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-18 13:39:37 +08:00
4694604836 Specify img2text model by tag (#5063)
### What problem does this PR solve?

The current design is not well-suited for multimodal models, as each
model can only be configured for a single purpose—either chat or
Img2txt. To work around this limitation, we use model aliases such as
gpt-4o-mini and gpt-4o-mini-2024-07-18.

To fix this, this PR allows specifying the Img2txt model by tag instead
of model_type.

### Type of change
- [x] Refactoring
2025-02-18 11:14:48 +08:00
224c5472c8 update locale vi (#5035)
update locale vi
2025-02-18 10:16:03 +08:00
409310aae9 Update agent session API, to support uploading files while create a new session (#5039)
### What problem does this PR solve?
Update the agent session API "POST /api/v1/agents/{agent_id}/sessions",
to support uploading files while create a new session:
- currently, the API only supports requesting with a json body. If user
wants to upload a doc or image when create session, like what is already
supported on the web client, we need to update the API.
- if upload an image, ragflow will call image2text, and a user_id is
needed for the image2text model. So we need to send user_id in the API
request. As form-data is needed to upload files, not json body, seems we
need to put the user_id in the url as an optional parameter (currently
user_id is an optional in json body).


### Type of change

- [x] Documentation Update
- [x] Other (please describe):
2025-02-18 09:45:40 +08:00
9ff825f39d Ignore exceptions when no index ahead. (#5047)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-02-18 09:09:22 +08:00
7b5d831296 Fix: Starting the source code on Windows, the 'HTTP API' returns 404 (#5042)
Fix: When starting the backend service from source code on Windows, the
"HTTP API" no longer returns 404.
2025-02-17 19:33:49 +08:00
42ee209084 Feat: Replace next-login-bg.svg #3221 (#5046)
### What problem does this PR solve?

Feat: Replace next-login-bg.svg #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-17 19:33:34 +08:00
e4096fbc33 Add another decrypt function. (#5043)
### What problem does this PR solve?



### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-17 18:09:11 +08:00
3aa5c2a699 Ignore exception of empty index. (#5030)
### What problem does this PR solve?

### Type of change


- [x] Refactoring
2025-02-17 15:59:55 +08:00
2ddf278e2d Fix: Cannot distinguish between export and import icons #5025 (#5031)
### What problem does this PR solve?

Fix: Cannot distinguish between export and import icons #5025

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 15:25:34 +08:00
f46448d04c Remove <think> for KG extraction. (#5027)
### What problem does this PR solve?

#4946

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 14:06:06 +08:00
ab17606e79 Rewrite Support specified language or language according to initial question (#4990)
Support specified language or language according to initial question

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-02-17 13:33:43 +08:00
7c90b87715 Fix window size of ES issue. (#5026)
### What problem does this PR solve?

#5015

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 12:48:56 +08:00
d2929e432e Feat: add LLM provider PPIO (#5013)
### What problem does this PR solve?

Add a LLM provider: PPIO

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
2025-02-17 12:03:26 +08:00
88daa349f9 Optimize conversation when uploading attachments (#4964)
### What problem does this PR solve?

#4929

### Type of change

- [x] Performance Improvement
2025-02-17 12:03:04 +08:00
f29da49893 Fix keyerror issue while rebuilding graph. (#5022)
### What problem does this PR solve?

#4995

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 12:02:44 +08:00
194e8ea696 Fix knowledge graph node not found (#4968) (#4970)
### What problem does this PR solve?

Fix knowledge graph node not found (#4968)

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 11:49:27 +08:00
810f997276 Fix <think> in keywords or question auto-generations. (#5021)
### What problem does this PR solve?

**#4983**

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-17 11:20:57 +08:00
6daae7f226 Added PEP 723 metadata to download_deps.py (#4988)
### What problem does this PR solve?

Added PEP 723 metadata to download_deps.py

### Type of change

- [x] Refactoring
2025-02-15 14:54:21 +08:00
f9fe6ac642 Feat: Add background color to GraphRag configuration #4980 (#4981)
### What problem does this PR solve?

Feat: Add background color to GraphRag configuration #4980

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-14 18:57:09 +08:00
b4ad565df6 Feat: Add ParsedPageCard component #3221 (#4976)
### What problem does this PR solve?

Feat: Add ParsedPageCard component #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-14 18:12:39 +08:00
754d5ea364 add gemini-2.0-flash-thinking-exp-01-21 (#4957)
add gemini-2.0-flash-thinking-exp-01-21
2025-02-14 13:31:07 +08:00
26add87c3d Feat: Jump from the chunk page to the dataset page #3221 (#4961)
### What problem does this PR solve?
Feat: Jump from the chunk page to the dataset page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-14 13:30:55 +08:00
986062a604 format number float (#4954)
format number float
2025-02-14 12:00:34 +08:00
29ceeba95f Fix hit cache error while raptoring. (#4955)
### What problem does this PR solve?

#4126

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-14 12:00:19 +08:00
849d9eb463 Ignore tenant not found error while increasing token usage. (#4950)
### What problem does this PR solve?

#4940

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-14 11:10:49 +08:00
dce7053c24 Feat: Add an id to the dataset testing route #3221 (#4951)
### What problem does this PR solve?

Feat: Add an id to the dataset testing route #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-14 10:43:59 +08:00
042f4c90c6 Fixes KeyError: 'content' when using stream=False (#4944)
### 🛠 Fixes `KeyError: 'content'` when using `stream=False`

#### 🔍 Problem  
When calling the chat API with `stream=False`, the code attempts to
access `msg[-1]["content"]` without verifying if the key exists. This
causes a `KeyError` when the message structure does not contain
`"content"`.

This issue was discussed in
[#4885](https://github.com/infiniflow/ragflow/issues/4885), where we
analyzed the root cause. The error does not occur with `stream=True`, as
the response is processed differently.

####  Solution  
- **Logging Fix:**  
  - Before accessing `msg[-1]["content"]`, we check if the key exists.  
- If it does not exist, a default value (`"[content not available]"`) is
used to prevent errors.

- **Structural Fix in `msg` Construction:**  
- Ensured that every message in `msg` contains the `"content"` key, even
if empty.
- This fixes the issue at its root and ensures consistent behavior
between `stream=True` and `stream=False`.

#### 🔄 Impact  
- Prevents the `KeyError` without affecting normal application flow.  
- Ensures the integrity of the `msg` structure, avoiding future
failures.



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-14 10:27:01 +08:00
c1583a3e1d Feat: Bind data to datasets page #3221 (#4938)
### What problem does this PR solve?

Feat: Bind data to datasets page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-14 09:38:48 +08:00
17fa2e9e8e Added a guide on setting metadata (#4935)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-02-13 18:16:45 +08:00
ff237f2dbc Feat: Display Think for Deepseek R1 model #4903 (#4930)
### What problem does this PR solve?

Feat: Display Think for Deepseek R1 model #4903

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-13 15:59:42 +08:00
50c99599f2 Fix DB assistant template error. (#4925)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-13 11:33:25 +08:00
891ee85fa6 Feat: Add ChatInput component #3221 (#4915)
### What problem does this PR solve?

Feat: Add ChatInput component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-12 19:32:49 +08:00
a03f5dd9f6 Add a list of large language models of deepseek and image2text models… (#4914)
### What problem does this PR solve?

#4870 
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-12 17:52:29 +08:00
415c4b7ed5 Organized and add a list of large language models of Nvidia.v1.1 (#4910)
### What problem does this PR solve?

#4870

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-12 17:10:19 +08:00
d599707154 Fix: After deleting all conversation lists, the chat input box can still be used for input. #4907 (#4909)
### What problem does this PR solve?

Fix: After deleting all conversation lists, the chat input box can still
be used for input. #4907

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 16:54:14 +08:00
7f06712a30 Feat: Add LlmSettingFieldItems component #3221 (#4906)
### What problem does this PR solve?

Feat: Add LlmSettingFieldItems component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-12 15:43:31 +08:00
b08bb56f6c Display thinking for deepseek r1 (#4904)
### What problem does this PR solve?
#4903
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-12 15:43:13 +08:00
9bcccadebd Remove use of eval() from search.py (#4887)
Use `json.loads()` instead.

### What problem does this PR solve?

Using `eval()` can lead to code injections. I think this loads a JSON
field, right? If yes, why is this done via `eval()` and not
`json.loads()`?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 13:15:38 +08:00
1287558f24 Fix xinference chat role order issue. (#4898)
### What problem does this PR solve?

#4831

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 13:15:23 +08:00
6b389e01b5 Remove use of eval() from operators.py (#4888)
Use `np.float32()` instead.

### What problem does this PR solve?

Using `eval()` can lead to code injections.

I think `eval()` is only used to parse a floating point number here.
This change preserves the correct behavior if the string `"None"` is
supplied. But if that behavior isn't intended then this part could be
just deleted instead, since `np.float32()` is parsing strings anyway:

```Python
        if isinstance(scale, str):
            scale = eval(scale)
```

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 12:53:42 +08:00
8fcca1b958 fix: big xls file error (#4859)
### What problem does this PR solve?

if *.xls file is too large, .eg >50M, I get error.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 12:39:25 +08:00
a1cf792245 Changed elasticsearch image url (#4897)
### What problem does this PR solve?

Changed elasticsearch image url to speed up image downloading. 

### Type of change

- [x] Refactoring
2025-02-12 12:38:13 +08:00
978b580dcf Fix: Knowledge base page crashes when network connection is lost. #4894 (#4895)
### What problem does this PR solve?

Fix: Knowledge base page crashes when network connection is lost. #4894
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-12 11:26:26 +08:00
d197f33646 Feat: Add hatPromptEngine component #3221 (#4881)
### What problem does this PR solve?

Feat: Add hatPromptEngine component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-11 19:04:10 +08:00
521d25d4e6 Feat: Add ChatBasicSetting component #3221 (#4876)
### What problem does this PR solve?

Feat: Add ChatBasicSetting component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-11 15:45:24 +08:00
ca1648052a fix categorize agent input content not format error (#4842)
### What problem does this PR solve?

Fix categorize agent input content not format error

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wangrui <wangrui@haima.me>
2025-02-11 13:32:42 +08:00
f34b913bd8 Feat: Add Sessions component #3221 (#4865)
### What problem does this PR solve?

Feat: Add Sessions component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-11 13:11:15 +08:00
0d3ed37b48 Make the update script shorter. (#4854)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-10 18:18:49 +08:00
bc68f18c48 Feat: Add ChatCard #3221 (#4852)
### What problem does this PR solve?
Feat: Add  ChatCard #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-10 17:38:10 +08:00
6e42687e65 Added a release notes (#4848)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-10 17:05:24 +08:00
e4bd879686 Feat: Modify the Preset configurations item style to distinguish it from other fields #4844 (#4845)
### What problem does this PR solve?

Feat: Modify the Preset configurations item style to distinguish it from
other fields #4844

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-10 16:49:07 +08:00
78982d88e0 Reformat error message. (#4829)
### What problem does this PR solve?

#4828

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-10 16:47:53 +08:00
fa5c7edab4 Fix: Fail to open console with Firefox #4816 (#4838)
### What problem does this PR solve?

Fix: Fail to open console with Firefox #4816

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-10 14:33:10 +08:00
6fa34d5532 Fix KG circle. (#4823)
### What problem does this PR solve?

#4760

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-10 11:02:29 +08:00
9e5427dc6e Feat: Remove begin's width from agent templates #4764 (#4809)
### What problem does this PR solve?

Feat: Remove begin's width from agent templates #4764
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-10 09:59:59 +08:00
a357190eff Feat: Fixed the issue where the prompt always displayed the initial value when switching between different generate operators #4764 (#4808)
### What problem does this PR solve?

Feat: Fixed the issue where the prompt always displayed the initial
value when switching between different generate operators #4764

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-08 18:25:25 +08:00
bfcc2abe47 Feat: Add VariablePickerMenuPlugin to select variables in the prompt text box by menu #4764 (#4765)
### What problem does this PR solve?

Feat: Add VariablePickerMenuPlugin to select variables in the prompt
text box by menu #4764

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-08 18:09:13 +08:00
f64ae9dc33 Inner prompt parameter setting. (#4806)
### What problem does this PR solve?

#4764

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-08 18:09:02 +08:00
5a51bdd824 Fix: The requested interface timeout will cause the page to crash #4787 (#4788)
### What problem does this PR solve?

Fix: The requested interface timeout will cause the page to crash #4787

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-08 11:26:36 +08:00
b48c85dcf9 Increase ES update script length. (#4785)
### What problem does this PR solve?

#4749

### Type of change

- [x] Performance Improvement
2025-02-08 11:03:31 +08:00
f374dd38b6 Fix divided by zero issue. (#4784)
### What problem does this PR solve?

#4779

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-08 10:36:26 +08:00
ccb72e6787 Add a comment to valkey. (#4783)
### What problem does this PR solve?
#4775

### Type of change

- [x] Documentation Update
2025-02-08 10:31:50 +08:00
55823dbdf6 Refresh Gemini model list. (#4780)
### What problem does this PR solve?

#4761

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-08 10:19:51 +08:00
588207d7c1 optimize TenantLLMService.increase_usage for "can't update token usag… (#4755)
…e error " message

### What problem does this PR solve?

optimize TenantLLMService.increase_usage Performance

### Type of change

- [x] Performance Improvement

Co-authored-by: che_shuai <che_shuai@massclouds.com>
2025-02-07 12:16:17 +08:00
2aa0cdde8f Fix Gemini chat issue. (#4757)
### What problem does this PR solve?

#4753

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-07 12:00:19 +08:00
44d798d8f0 Config chat share (#4700)
Config chat share
2025-02-07 10:35:49 +08:00
4150805073 More models for siliconflow. (#4756)
### What problem does this PR solve?

#4751

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-02-07 10:32:52 +08:00
448fa1c4d4 Robust for abnormal response from LLMs. (#4747)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-06 17:34:53 +08:00
e786f596e2 Updated template description (#4744)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-02-06 17:14:13 +08:00
fe9e9a644f Preparation for release. (#4739)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-02-06 15:15:13 +08:00
d2961b2d25 Feat: Supports docx in the MANUAL chunk method and docx, markdown, and PDF in the Q&A chunk method #3957 (#4741)
### What problem does this PR solve?

Feat: Supports docx in the MANUAL chunk method and docx, markdown, and
PDF in the Q&A chunk method #3957
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-02-06 14:41:46 +08:00
a73e1750b6 Resume content flow ExecSQL (#4738)
resume content flow, instead of closed with errors.
2025-02-06 12:09:47 +08:00
c1d71e9a3f Fix: New user can't accept invite without configuring LLM API #4379 (#4736)
### What problem does this PR solve?

Fix: New user can't accept invite without configuring LLM API #4379

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-06 11:41:02 +08:00
2a07eb69a7 Fix too long context issue. (#4735)
### What problem does this PR solve?

#4728

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-06 11:37:23 +08:00
a3a70431f3 Avoid misunderstanding LLMs about the numbers value (#4724)
Avoid misunderstanding LLMs about the numbers value
2025-02-06 10:17:56 +08:00
6f2c3a3c3c Fix too long query exception. (#4729)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-06 10:11:52 +08:00
54803c4ef2 Fix: pt_br translation and adding pt to knoledg-add (#4674)
### What problem does this PR solve?

Fix Portuguese (Brazil) translation
Adding portuguese to Knowledge adding settings.

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
- [X] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
2025-02-05 18:20:24 +08:00
efbaa484d7 Fix: Chat Assistant page goes blank #4566 (#4727)
### What problem does this PR solve?

Fix: Chat Assistant page goes blank #4566

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-05 18:19:38 +08:00
3411d0a2ce Added cuda_is_available (#4725)
### What problem does this PR solve?

Added cuda_is_available

### Type of change

- [x] Refactoring
2025-02-05 18:01:23 +08:00
283d036cba Fitin for infinity. (#4722)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-02-05 16:47:05 +08:00
307717b045 Fix exesql re-generate SQL issue. (#4717)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-05 16:23:48 +08:00
8e74bc8e42 Update readme. (#4715)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-02-05 14:24:30 +08:00
4b9c4c0705 Update deepseek model provider info. (#4714)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2025-02-05 13:43:40 +08:00
b2bb560007 Import akshare lazzily. (#4708)
### What problem does this PR solve?

#4696

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-05 12:04:11 +08:00
e1526846da Fixed GPU detection on CPU only environment (#4711)
### What problem does this PR solve?

Fixed GPU detection on CPU only environment. Close #4692

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-02-05 12:02:43 +08:00
7a7f98b1a9 Reverted build slim image documentation (#4687)
### Fixed documentation for building docker image

I'm assuming that this was a mistake (but I could be missing something)
[here](https://github.com/infiniflow/ragflow/pull/4658/files#:~:text=docker%20build%20%2D%2Dbuild%2Darg%20LIGHTEN%3D1%20%2Df%20Dockerfile%20%2Dt%20infiniflow/ragflow%3Anightly%2Dslim%20.)
when the docker building instructions for the slim image was just
changed away from an actual `docker build` command to the mac os `docker
compose up` command. This is just reverting the change.

### Type of change

- [X] Documentation Update
2025-02-05 10:35:08 +08:00
036f37a627 fix: err object has no attribute 'iter_lines' (#4686)
### What problem does this PR solve?

ERROR: 'Stream' object has no attribute 'iter_lines' with reference to
Claude/Anthropic chat streams

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kyle Olmstead <k.olmstead@offensive-security.com>
2025-02-01 22:39:30 +08:00
191587346c Fix macOS startup (#4658)
### What problem does this PR solve?

https://github.com/infiniflow/ragflow/issues/4319

This pull request includes several changes to improve the Docker setup
and documentation for the project. The most important changes include
updating the Dockerfile to support modern versions of Rust, adding a new
Docker Compose configuration for macOS, and updating the build
instructions in the documentation.

Improvements to Docker setup:

*
[`Dockerfile`](diffhunk://#diff-dd2c0eb6ea5cfc6c4bd4eac30934e2d5746747af48fef6da689e85b752f39557L80-R107):
Added installation steps for a modern version of Rust and updated the
logic for installing the correct ODBC driver based on the architecture.
*
[`docker/docker-compose-macos.yml`](diffhunk://#diff-8e8587143bb2442c02f6dff4caa217ebbe3ba4ec8e7c23b2e568886a67b00eafR1-R56):
Added a new Docker Compose configuration file specifically for macOS,
including service dependencies, environment variables, and volume
mappings.

Updates to documentation:

*
[`docs/guides/develop/build_docker_image.mdx`](diffhunk://#diff-d6136bb897f7245aae33b0accbcf7c508ceaef005c545f9f09cad3cada840a19L44-R44):
Updated the build instructions to use the new Docker Compose
configuration for macOS instead of the previous Docker build command.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Documentation Update

---------

Signed-off-by: Samuel Giffard <samuel.giffard@mytomorrows.com>
2025-01-28 16:51:16 +08:00
50055c47ec Infinity mapping refine. (#4665)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-01-27 18:53:49 +08:00
6f30397bb5 Infinity adapt to graphrag. (#4663)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-27 18:35:18 +08:00
d970d0ef39 Fix typos (#4662)
### What problem does this PR solve?

Fix typos in the documents

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-01-27 15:45:16 +08:00
ce8658aa84 Update FAQ (#4661)
### What problem does this PR solve?

Update FAQ

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-01-27 12:56:48 +08:00
bc6a768b90 Refactor the delimiter name (#4659)
### What problem does this PR solve?

Rename from 'Diagonal' to 'Forward slash'
Rename from 'Minus' to 'Dash'

issue: #4655 

### Type of change

- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-01-27 11:04:43 +08:00
656a2fab41 Refresh deepseek models. (#4660)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-27 11:01:39 +08:00
47b28a27a6 Added description of the Iteration component (#4656)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-27 10:12:23 +08:00
c354239b79 Make infinity adapt to condition exist. (#4657)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 18:45:36 +08:00
b4303f6010 Update README. (#4654)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2025-01-26 14:14:58 +08:00
4776fa5e4e Refactor for total_tokens. (#4652)
### What problem does this PR solve?

#4567
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 13:54:26 +08:00
c24137bd11 Fix too long integer for Table. (#4651)
### What problem does this PR solve?

#4594

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 12:54:58 +08:00
4011c8f68c Fix potential error. (#4650)
### What problem does this PR solve?
#4622

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 12:38:32 +08:00
2cb8edc42c Added GPUStack (#4649)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-26 12:25:02 +08:00
284b4d4430 Align table heading with 'System Model Settings' (#4646)
…the 'System Model Settings'

### What problem does this PR solve?

### Type of change


- [x] Documentation Update
2025-01-26 11:12:38 +08:00
42f7261509 Fix param error. (#4645)
### What problem does this PR solve?

#4633

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 10:40:02 +08:00
f33415b751 refactor: better vertical alignment for icon and text in some setting buttons (#4615)
### What problem does this PR solve?

Fixed vertical alignment issues between icons and text in API-Key and
System Model Settings buttons. This improves visual consistency across
the settings interface.

### Type of change

- [x] Refactoring

Before: Icons and text were slightly misaligned vertically
<img width="635" alt="Screenshot 2025-01-23 at 20 22 46"
src="https://github.com/user-attachments/assets/28f15637-d3fd-45a2-aae8-ca72fb12a88e"
/>

After: Icons and text are now properly centered with consistent spacing
<img width="540" alt="Screenshot 2025-01-23 at 20 23 02"
src="https://github.com/user-attachments/assets/98bb0ca5-6995-42d8-bd23-8a8f44ec0209"
/>
2025-01-26 10:36:03 +08:00
530b0dab17 Make infinity able to cal embedding sim only. (#4644)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 10:29:52 +08:00
c4b1c4e6f4 Fix onnxruntime-gpu marks (#4643)
### What problem does this PR solve?

Fix onnxruntime-gpu marks

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-26 09:37:59 +08:00
3c2c8942d5 Removed onnxruntime (#4632)
### What problem does this PR solve?

Removed onnxruntime. It conflicts with the onnxruntime-gpu.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 23:41:52 +08:00
71c132f76d Make infinity adapt (#4635)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 17:45:04 +08:00
9d717f0b6e Fix csv reader exception. (#4628)
### What problem does this PR solve?

#4552
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 14:47:19 +08:00
8b49734241 Added onnxruntime-gpu (#4631)
### What problem does this PR solve?

Added onnxruntime-gpu

### Type of change

- [x] Refactoring
2025-01-24 14:33:21 +08:00
898ae7fa80 Fix missplace for vector sim weight and token sim weight. (#4627)
### What problem does this PR solve?

#4610

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 12:41:06 +08:00
fa4277225d Added document: Accelerate document indexing and retrieval (#4600)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-24 11:58:15 +08:00
1bff6b7333 Fix t_ocr.py for PNG image. (#4625)
### What problem does this PR solve?
#4586

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 11:47:27 +08:00
e9ccba0395 Add timestamp to messages (#4624)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-24 11:07:55 +08:00
f1d9f4290e Fix TogetherAIEmbed. (#4623)
### What problem does this PR solve?

#4567

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-24 10:29:30 +08:00
4230402fbb deepdoc use GPU if possible (#4618)
### What problem does this PR solve?

deepdoc use GPU if possible

### Type of change

- [x] Refactoring
2025-01-24 09:48:02 +08:00
e14d6ae441 Refactor. (#4612)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-01-23 18:56:02 +08:00
55f2b7c4d5 Code format. (#4611)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2025-01-23 18:43:32 +08:00
07b3e55903 Feat: Set the style of the header tag #3221 (#4608)
### What problem does this PR solve?

Feat: Set the style of the header tag #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-23 18:16:52 +08:00
86892959a0 Rebuild graph when it's out of time. (#4607)
### What problem does this PR solve?

#4543

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Refactoring
2025-01-23 17:26:20 +08:00
bbc1d02c96 Template conversion adds Jinjia2 syntax support (#4545)
### What problem does this PR solve?

Template conversion adds Jinjia2 syntax support

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: wangrui <wangrui@haima.me>
Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-01-23 17:11:14 +08:00
b23a4a8fea Feat: Add keyword item to AssistantSetting #4543 (#4603)
### What problem does this PR solve?

Feat: Add keyword item to AssistantSetting #4543

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-23 15:58:22 +08:00
240e7d7c22 Unified user_service.py (#4606)
### What problem does this PR solve?

Unified user_service.py

### Type of change

- [x] Refactoring
2025-01-23 15:49:21 +08:00
52fa8bdcf3 fix bug KGSearch.search() got an unexpected keyword argument 'rank_feature' (#4601)
`graphrag/search.py`中`search`方法缺少参数`rank_feature`

Co-authored-by: xubh <xubh@wikiflyer.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-01-23 14:03:18 +08:00
13f04b7cca Fix pdf applying Q&A issue. (#4599)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-23 12:30:46 +08:00
c4b9e903c8 Fix index not found for new user. (#4597)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-23 11:45:22 +08:00
15f9406e7b Fix: Capture the problem that the knowledge graph interface returns null and causes page errors #4543 (#4598)
### What problem does this PR solve?

Fix: Capture the problem that the knowledge graph interface returns null
and causes page errors #4543

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-23 11:32:49 +08:00
c5c0dd2da0 Feat: Display the knowledge graph on the knowledge base page #4543 (#4587)
### What problem does this PR solve?

Feat: Display the knowledge graph on the knowledge base page #4543

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-22 19:43:27 +08:00
dd0ebbea35 Light GraphRAG (#4585)
### What problem does this PR solve?

#4543

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-22 19:43:14 +08:00
1a367664f1 Remove usage of eval() from postprocess.py (#4571)
Remove usage of `eval()` from postprocess.py

### What problem does this PR solve?

The use of `eval()` is a potential security risk. While the use of
`eval()` is guarded and thus not a security risk normally, `assert`s
aren't run if `-O` or `-OO` is passed to the interpreter, and as such
then the guard would not apply. In any case there is no reason to use
`eval()` here at all.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Other (please describe):

Potential security fix if somehow the passed `modul_name` could be user
controlled.
2025-01-22 19:37:24 +08:00
336e5fb37f Renamed entrypoint_task_executor.sh entrypoint-parser.sh (#4583)
### What problem does this PR solve?

Renamed entrypoint_task_executor.sh entrypoint-parser.sh

### Type of change

- [x] Refactoring
2025-01-22 18:21:51 +08:00
598e142c85 re-fix (#4584)
re-fix docs
2025-01-22 18:13:26 +08:00
cbc3c5297e Revert the chat history for rewrite. (#4579)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-22 16:55:11 +08:00
4b82275ae5 Fix Latest Release button on PT README (#4572)
### What problem does this PR solve?

Latest Release button on Portugese Read me is not looking like it shuld 

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2025-01-22 11:46:55 +08:00
3894de895b Update comments (#4569)
### What problem does this PR solve?

Add license statement.

### Type of change

- [x] Refactoring

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-01-21 20:52:28 +08:00
583050a876 minor (#4568)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-21 20:02:04 +08:00
a2946b0fb0 Added descriptions of the Note and Template components (#4560)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-21 19:51:30 +08:00
21052b2972 Feat: Support for Portuguese language #4557 (#4558)
### What problem does this PR solve?

Feat: Support for Portuguese language #4557

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-21 11:32:47 +08:00
5632613eb5 Add language portugese br (#4550)
### What problem does this PR solve?

Add language Portugese from Brazil

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2025-01-21 11:22:29 +08:00
fc35821f81 Feat: Make the scroll bar of the DatasetSettings page appear inside #3221 (#4548)
### What problem does this PR solve?

Feat: Make the scroll bar of the DatasetSettings page appear inside
#3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-21 10:19:38 +08:00
db80376427 Added entrypoint for task executor (#4551)
### What problem does this PR solve?

Added entrypoint for task executor

### Type of change

- [x] Refactoring
2025-01-20 22:49:46 +08:00
99430a7db7 Added description of the Concentrator component (#4549)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2025-01-20 19:54:02 +08:00
a3391c4d55 Feat: Rename document name #3221 (#4544)
### What problem does this PR solve?

Feat: Rename document name #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-20 16:49:45 +08:00
e0f52eebc6 Added descriptions of Rewrite and Switch components. To be continued (#4526)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-01-20 15:56:21 +08:00
367babda2f Make Categorize see more chat hisotry. (#4538)
### What problem does this PR solve?

#4521

### Type of change
- [x] Performance Improvement
2025-01-20 11:57:56 +08:00
2962284c79 Bump akshare (#4536)
### What problem does this PR solve?

Bump akshare. Close #4525 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-20 11:17:59 +08:00
75e1981e13 Remove use of eval() from recognizer.py (#4480)
`eval(op_type)` -> `getattr(operators, op_type)`

### What problem does this PR solve?

Using `eval()` can lead to code injections and is entirely unnecessary
here.

### Type of change

- [x] Other (please describe):

Best practice code improvement, preventing the possibility of code
injection.
2025-01-20 09:52:47 +08:00
4f9f9405b8 Remove use of eval() from ocr.py (#4481)
`eval(op_name)` -> `getattr(operators, op_name)`

### What problem does this PR solve?

Using `eval()` can lead to code injections and is entirely unnecessary
here.

### Type of change

- [x] Other (please describe):

Best practice code improvement, preventing the possibility of code
injection.
2025-01-20 09:52:30 +08:00
938492cbae Fix: Rename segmented.tsx #3221 (#4522)
### What problem does this PR solve?

Fix: Rename segmented.tsx #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-17 19:01:09 +08:00
f4d084bcf1 Fix doc progress issue. (#4520)
### What problem does this PR solve?

#4516
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-17 18:28:15 +08:00
69984554a5 Fix: Translate the operator options of the Switch operator #1739 (#4519)
### What problem does this PR solve?

Fix: Translate the operator options of the Switch operator #1739

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-17 18:23:08 +08:00
03d7a51d49 add file README_tzh.md (#4513)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Other (please describe):
2025-01-17 18:22:02 +08:00
0efe7a544b Change index url per NEED_MIRROR (#4515)
### What problem does this PR solve?

Change index url per NEED_MIRROR. Close #4507

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-17 12:01:04 +08:00
c0799c53b3 Added descriptions of Message and Keyword agent components (#4512)
### What problem does this PR solve?

### Type of change


- [x] Documentation Update
2025-01-16 19:47:15 +08:00
4946e43941 Feat: Make the category operator form displayed in collapsed mode by default #4505 (#4510)
### What problem does this PR solve?

Feat: Make the category operator form displayed in collapsed mode by
default #4505

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-16 17:16:58 +08:00
37235315e1 Fix: Fixed an issue where math formulas could not be displayed correctly #4405 (#4506)
### What problem does this PR solve?

[remarkjs/react-markdown/issues/785](https://github.com/remarkjs/react-markdown/issues/785)
Fix: Fixed an issue where math formulas could not be displayed correctly
#4405

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-16 15:13:40 +08:00
39be08c83d Feat: Add the MessageHistoryWindowSizeItem to RewriteQuestionForm #1739 (#4502)
### What problem does this PR solve?

Feat: Add the MessageHistoryWindowSizeItem to RewriteQuestionForm #1739
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-16 15:01:15 +08:00
3805621564 Fix xinference rerank issue. (#4499)
### What problem does this PR solve?
#4495
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-16 11:35:51 +08:00
a75cda4957 Feat: Add LinkToDatasetDialog #3221 (#4500)
### What problem does this PR solve?

Feat: Add LinkToDatasetDialog #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-16 11:35:39 +08:00
961e8c4980 Fix: the Display when the knowledge base empty. (#4496)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-16 10:27:45 +08:00
57b4e0c464 Bump infinity to v0.6.0-dev2 (#4497)
### What problem does this PR solve?

Bump infinity to v0.6.0-dev2. Close #4477 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-16 10:07:17 +08:00
c852a6dfbf Accelerate titles' embeddings. (#4492)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2025-01-15 15:20:29 +08:00
b4614e9517 Feat: Add FilesTable #3221 (#4491)
### What problem does this PR solve?

Feat: Add FilesTable #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-15 14:39:33 +08:00
be5f830878 Truncate text for zhipu embedding. (#4490)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-15 14:36:27 +08:00
7944aacafa Feat: add gpustack model provider (#4469)
### What problem does this PR solve?

Add GPUStack as a new model provider.
[GPUStack](https://github.com/gpustack/gpustack) is an open-source GPU
cluster manager for running LLMs. Currently, locally deployed models in
GPUStack cannot integrate well with RAGFlow. GPUStack provides both
OpenAI compatible APIs (Models / Chat Completions / Embeddings /
Speech2Text / TTS) and other APIs like Rerank. We would like to use
GPUStack as a model provider in ragflow.

[GPUStack Docs](https://docs.gpustack.ai/latest/quickstart/)

Related issue: https://github.com/infiniflow/ragflow/issues/4064.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)



### Testing Instructions
1. Install GPUStack and deploy the `llama-3.2-1b-instruct` llm, `bge-m3`
text embedding model, `bge-reranker-v2-m3` rerank model,
`faster-whisper-medium` Speech-to-Text model, `cosyvoice-300m-sft` in
GPUStack.
2. Add provider in ragflow settings.
3. Testing in ragflow.
2025-01-15 14:15:58 +08:00
e478586a8e Refactor. (#4487)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-01-15 14:06:46 +08:00
713f38090b Sync prerequisites with Helm Charts (#4483)
### What problem does this PR solve?

Address #4391 

### Type of change

- [x] Other (please describe):
2025-01-15 11:57:47 +08:00
8f7ecde908 Update description (#4468)
### What problem does this PR solve?

Update description

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-01-14 18:35:06 +08:00
23ad459136 Feat: Add background to next login page #3221 (#4474)
### What problem does this PR solve?

Feat: Add background to next login page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-14 13:43:18 +08:00
f556f0239c Fix dify retrieval issue. (#4473)
### What problem does this PR solve?

#4464
#4469 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-14 13:16:05 +08:00
f318342c8e Recalling the file uploaded while chatting. (#4472)
### What problem does this PR solve?

#4445

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-14 12:05:20 +08:00
d3c07794b5 Replace poetry with uv (#4471)
### What problem does this PR solve?

Replace poetry with uv

### Type of change

- [x] Refactoring
2025-01-14 11:49:43 +08:00
fd0bf3adf0 Format: dos2unix (#4467)
### What problem does this PR solve?

Format the code

### Type of change

- [x] Refactoring

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-01-13 18:19:01 +08:00
c08382099a Check meta data format in json map (#4461)
### What problem does this PR solve?

#3690

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-13 17:34:50 +08:00
d8346cb7a6 Feat: Metadata in documents for improve the prompt #3690 (#4462)
### What problem does this PR solve?

Feat: Metadata in documents for improve the prompt #3690

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-13 17:13:37 +08:00
46c52d65b7 Add meta data while chatting. (#4455)
### What problem does this PR solve?

#3690

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-13 14:35:24 +08:00
e098fcf6ad Fix csv for TAG. (#4454)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-13 12:03:18 +08:00
ecdb2a88bd Fix: Can not select GPT-4o / 4o mini as Chat Model #4421 (#4453)
### What problem does this PR solve?

Fix: Can not select GPT-4o / 4o mini as Chat Model #4421

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-13 11:54:16 +08:00
2c7ba90cb4 Fix: In order to distinguish the keys of a pair of messages, add a prefix to the id when rendering the message. #4409 (#4451)
### What problem does this PR solve?

Fix: In order to distinguish the keys of a pair of messages, add a
prefix to the id when rendering the message. #4409

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-13 10:51:59 +08:00
95261f17f6 Bump infinity to v0.6.0-dev1 (#4448)
### What problem does this PR solve?

Bump infinity to v0.6.0-dev1 and poetry to 2.0.1

### Type of change

- [x] Refactoring
2025-01-12 19:54:33 +08:00
7d909d4d1b Add doc meta data. (#4442)
### What problem does this PR solve?

#3690

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-10 19:06:59 +08:00
4dde73f897 Error message: Infinity not support table parsing method (#4439)
### What problem does this PR solve?

Specific error message.

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2025-01-10 16:39:13 +08:00
93b30b2fb5 update res vi (#4437)
update typo vi
2025-01-10 11:35:58 +08:00
06c54367fa Feat: Display tag word cloud on recall test page #4368 (#4438)
### What problem does this PR solve?

Feat: Display tag word cloud on recall test page #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-10 11:35:07 +08:00
6acbd374d8 fix duckduckgo search subsection error (#4430)
### What problem does this PR solve?

duckduckgo search 6.3.0 still has error sometimes, need to update to
7.2.0, after updated, it works ok.
this PR is going to fix this issue
https://github.com/infiniflow/ragflow/issues/4396

### Type of change

 Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: xiaohzho <xiaohzho@cisco.com>
2025-01-10 09:34:20 +08:00
48bca0ca01 Fix: Modify the text of the category operator form #4412 (#4433)
### What problem does this PR solve?

Fix: Modify the text of the category operator form #4412

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-09 19:17:22 +08:00
300d8ecf51 Feat: Add TagFeatureItem #4368 (#4432)
### What problem does this PR solve?

Feat: Add TagFeatureItem #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-09 18:24:27 +08:00
dac54ded96 Added a description of the Categorize agent component (#4428)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-01-09 18:10:18 +08:00
c5da3cdd97 Tagging (#4426)
### What problem does this PR solve?

#4367

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-09 17:07:21 +08:00
f892d7d426 Let the agent talk while there's pre-set param. (#4423)
### What problem does this PR solve?

#4385

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-09 14:07:57 +08:00
f86d8906e7 Fixed code error when mssql returns multiple columns (#4420)
Fixed code error when mssql returns multiple columns
2025-01-09 11:55:18 +08:00
bc681e2ee9 Remove redundant param of rewrite component. (#4422)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-09 11:54:31 +08:00
b6c71c1e01 Fix typo in helm charts (#4419)
### What problem does this PR solve?

Fix typo in helm chart

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-09 10:20:27 +08:00
7bebf4b7bf Added descriptions of the retrieval agent component (#4416)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update

---------

Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2025-01-09 10:11:05 +08:00
d64df4de9c Update error message (#4417)
### What problem does this PR solve?

1. Update error message
2. Remove space characters

### Type of change

- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2025-01-08 20:18:27 +08:00
af43cb04e8 Feat: Add tag_kwd parameter to chunk configuration modal #4368 (#4414)
### What problem does this PR solve?

Feat: Add tag_kwd parameter to chunk configuration modal  #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-08 19:45:34 +08:00
3d66d78304 Fix API retrieval error. (#4408)
### What problem does this PR solve?

#4403

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-08 11:27:46 +08:00
b7ce4e7e62 fix:t_recognizer TypeError: 'super' object is not callable (#4404)
### What problem does this PR solve?

[Bug]: layout recognizer failed for wrong boxes class type #4230
(https://github.com/infiniflow/ragflow/issues/4230)

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: youzhiqiang <zhiqiang.you@aminer.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-01-08 10:59:35 +08:00
5e64d79587 Added generate component description (#4399)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2025-01-07 19:56:11 +08:00
49cebd9fec Feat: Add description for tag parsing method #4368 (#4402)
### What problem does this PR solve?

Feat: Add description for tag parsing method #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-07 19:33:53 +08:00
d9a4e4cc3b Fix page size error. (#4401)
### What problem does this PR solve?

#4400

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-07 19:06:31 +08:00
ac89a2dda1 [Fix] fix duckduck go search 202 ratelimit failed (#4398)
this PR is going to fix issue
https://github.com/infiniflow/ragflow/issues/4396

### Type of change

 Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: xiaohzho <xiaohzho@cisco.com>
2025-01-07 18:40:46 +08:00
01a122dc9d fix bug, agent invoke can not get params from begin (#4390)
### What problem does this PR solve?

fix bug, agent invoke can not get params from begin

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: wangrui <wangrui@haima.me>
2025-01-07 18:40:27 +08:00
8ec392adb0 Feat: Add TagWorkCloud #4368 (#4393)
### What problem does this PR solve?

Feat: Add TagWorkCloud #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-07 18:03:41 +08:00
de822a108f Refine variable display name. (#4397)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-01-07 18:02:33 +08:00
2e40c2a6f6 Fix t_recognizer issue. (#4387)
### What problem does this PR solve?

#4230

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-07 13:17:46 +08:00
d088a34fe2 Feat: Add LoadingButton #4368 (#4384)
### What problem does this PR solve?

Feat: Add LoadingButton #4368

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-07 12:53:06 +08:00
16e1681fa4 Refine DB assistant template. (#4383)
### What problem does this PR solve?

#4326

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-07 11:30:15 +08:00
bb24e5f739 Added instructions on embedding agent or assistant into a third-party webpage (#4369)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2025-01-06 20:25:47 +08:00
1d93eb81ae Feat: Add TagTable #4367 (#4368)
### What problem does this PR solve?

Feat: Add TagTable #4367

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-06 18:58:42 +08:00
439d20e41f Use LTS polars to resolve some machines don't support AVX CPU flag (#4364)
### What problem does this PR solve?

Some old types of machine or virtual machine doesn't support AVX CPU
flag. This PR is to use lts polars module to avoid this fault.

fix issue: #4349

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2025-01-06 18:52:17 +08:00
45619702ff Updated outdated descriptions and added multi-turn optimization (#4362)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update
2025-01-06 16:54:22 +08:00
b93c136797 Fix gemini embedding error. (#4356)
### What problem does this PR solve?

#4314

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-06 14:41:29 +08:00
983ec0666c Fix param error. (#4355)
### What problem does this PR solve?

#4230

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-06 13:54:17 +08:00
a9ba051582 Adds a research report generator. (#4354)
### What problem does this PR solve?

#4242

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2025-01-06 13:28:54 +08:00
bad764bcda Improve storage engine (#4341)
### What problem does this PR solve?

- Bring `STORAGE_IMPL` back in `rag/svr/cache_file_svr.py`
- Simplify storage connection when working with AWS S3

### Type of change

- [x] Refactoring
2025-01-06 12:06:24 +08:00
9c6cf12137 Refactor model list. (#4346)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2025-01-03 19:55:42 +08:00
6288b6d02b chrome extensions (#4308)
Build chrome extensions that allow interaction with browser content
2025-01-03 10:15:36 +08:00
52c20033d7 Fix total number error. (#4339)
### What problem does this PR solve?

#4328

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-03 10:02:30 +08:00
5dad15600c Feat: Add FileUploadDialog #3221 (#4327) (#4335)
### What problem does this PR solve?

Feat: Add ConfirmDeleteDialog #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-03 09:47:05 +08:00
8674156d1c Fix potential SSRF attack vulnerability (#4334)
### What problem does this PR solve?

Fix potential SSRF attack vulnerability

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2025-01-02 18:45:45 +08:00
5083d92998 Feat: Add model id to ExeSql operator form. #1739 (#4333)
### What problem does this PR solve?

Feat: Add model id to ExeSql operator form. #1739

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-02 17:38:01 +08:00
59a78408be Fix t_recognizer.py after model updating. (#4330)
### What problem does this PR solve?

#4230

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2025-01-02 17:00:11 +08:00
df22ead841 Fix agent_completion bug (#4329)
### What problem does this PR solve?

Fix agent_completion bug  #4320

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2025-01-02 16:59:54 +08:00
5883493c7d Feat: Add FileUploadDialog #3221 (#4327)
### What problem does this PR solve?

Feat: Add FileUploadDialog #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2025-01-02 16:10:41 +08:00
50f209204e Synchronize with enterprise version (#4325)
### Type of change

- [x] Refactoring
2025-01-02 13:44:44 +08:00
564277736a Update exesql component for agent (#4307)
### What problem does this PR solve?

Update exesql component for agent

### Type of change

- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-31 19:58:56 +08:00
061a22588a Feat: Add DatasetCreatingDialog #3221 (#4313)
### What problem does this PR solve?

Feat: Add DatasetCreatingDialog #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-31 19:17:09 +08:00
5071df9de1 Fix parameter name error. (#4312)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-31 17:38:01 +08:00
419b546f03 Update displayed_name to display_name (#4311)
### What problem does this PR solve?

Update displayed_name to display_name

### Type of change

- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-31 17:25:24 +08:00
e5b1511c66 Fix: Fixed the issue that the graph could not display the grouping #4180 (#4306)
### What problem does this PR solve?

Fix: Fixed the issue that the graph could not display the grouping #4180

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-31 15:32:14 +08:00
0e5124ec99 Show the errors out. (#4305)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-12-31 15:32:02 +08:00
7c7b7d2689 Update error message for agent name conflict (#4299)
### What problem does this PR solve?

Update error message for agent name conflict

### Type of change

- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-31 14:36:23 +08:00
accd3a6c7e Support OpenAI gpt-4o and gpt-4o-mini for img2text (#4300)
### What problem does this PR solve?

OpenAI has deprecated the gpt-4-vision-preview model. This PR adds
support for the newer gpt-4o and gpt-4o-mini models in the img2text
feature.


![image](https://github.com/user-attachments/assets/6dddf2dc-1b9e-4e94-bf07-6bf77d39122b)

This PR add addtional 4o/4o-mini entry for img2text besides original
ones. Utilized [alias](https://platform.openai.com/docs/models#gpt-4o)
model names (e.g., gpt-4o-2024-08-06) because the database schema uses
the model name as the primary key.



- [x] Other (please describe): model update
2024-12-31 14:36:06 +08:00
4ba4f622a5 Refactor (#4303)
### What problem does this PR solve?

### Type of change
- [x] Refactoring
2024-12-31 14:31:31 +08:00
b52b0f68fc Add top_k for create_chat and update_chat api (#4294)
### What problem does this PR solve?

Add top_k for create_chat and update_chat api #4157

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-30 19:22:57 +08:00
d42e78bce2 Fix bugs in chunk api (#4293)
### What problem does this PR solve?

Fix bugs in chunk api #4149

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-30 19:01:44 +08:00
8fb18f37f6 Code refactor. (#4291)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-12-30 18:38:51 +08:00
f619d5a9b6 Fix: After executing npm i --force locally, the login page cannot be opened #4290 (#4292)
### What problem does this PR solve?

Fix: After executing npm i --force locally, the login page cannot be
opened #4290

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-30 18:19:58 +08:00
d1971e988a Feat: The Begin and IterationStart operators cannot be deleted using shortcut keys #4287 (#4288)
### What problem does this PR solve?

Feat: The Begin and IterationStart operators cannot be deleted using
shortcut keys #4287

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-30 17:47:47 +08:00
54908ebd30 Fix the bug in create_dataset function (#4284)
### What problem does this PR solve?

Fix the bug in create_dataset function #4136

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-30 13:04:51 +08:00
3ba2b8d80f Fix agent session list by user_id. (#4285)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-30 12:18:16 +08:00
713b837276 Feat: Translate the system prompt of the generate operator #3993 (#4283)
### What problem does this PR solve?

 Feat: Translate the system prompt of the generate operator #3993

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-30 12:07:06 +08:00
8feb4c1a99 Fix BaiduFanyi TestRun parameter validation and debug method missing … (#4275)
### What problem does this PR solve?

Fix BaiduFanyi TestRun parameter validation and debug method missing
errors
![Uploading Snipaste_2024-12-27_19-56-31.png…]()


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: wangrui <wangrui@haima.me>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-30 10:34:57 +08:00
dd13a5d05c Fix some bugs in text2sql.(#4279)(#4281) (#4280)
Fix some bugs in text2sql.(#4279)(#4281)

### What problem does this PR solve?
- The incorrect results in parsing CSV files of the QA knowledge base in
the text2sql scenario. Process CSV files using the csv library. Decouple
CSV parsing from TXT parsing
- Most llm return results in markdown format ```sql query ```, Fix
execution error caused by LLM output SQLmarkdown format.### Type of
change
- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-30 10:32:19 +08:00
8cdf10148d Initial draft of the begin component reference (#4272)
### What problem does this PR solve?

### Type of change


- [x] Documentation Update
2024-12-27 17:07:31 +08:00
7773afa561 Update text2sql agent manual document (#4226) (#4271)
### What problem does this PR solve?
- Create a text2sql agent document: Receipe, procedure, debug (
including step run), run.

### Type of change
- [ ] Documentation Update

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-27 16:48:17 +08:00
798eb3647c Fix chat listing error. (#4270)
### What problem does this PR solve?

#4220
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-27 16:03:59 +08:00
2d17e5aa04 Feat: Delete useless code #4242 (#4267)
### What problem does this PR solve?

Feat: Delete useless code #4242

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-27 15:09:03 +08:00
c75aa11ae6 Fix: The edit box for the headers parameter of the invoke operator is always loading. #4265 (#4266)
### What problem does this PR solve?

Fix: The edit box for the headers parameter of the invoke operator is
always loading. #4265

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-27 15:03:42 +08:00
c7818770f4 Fix Python SDK example error. (#4263)
### What problem does this PR solve?

#4253
### Type of change

- [x] Documentation Update
2024-12-27 14:49:43 +08:00
6f6303d017 Fix Python SDK example error. (#4262)
### What problem does this PR solve?

#4252

### Type of change

- [x] Documentation Update
2024-12-27 14:40:00 +08:00
146e8bb793 Feat: Limit the iteration start node to only be the source node #4242 (#4260)
### What problem does this PR solve?

Feat: Limit the iteration start node to only be the source node #4242

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-27 14:25:15 +08:00
f948c0d9f1 Clean query. (#4259)
### What problem does this PR solve?

#4239

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-27 14:25:03 +08:00
c3e3f0fbb4 Add iteration for agent. (#4258)
### What problem does this PR solve?

#4242
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-27 11:38:33 +08:00
a1a825c830 Feat: Add the iteration Node #4242 (#4247)
### What problem does this PR solve?

Feat: Add the iteration Node #4242

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-27 11:24:17 +08:00
a6f4153775 Update UI text (#4248)
### What problem does this PR solve?

Update UI text

### Type of change

- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-27 10:48:11 +08:00
097aab09a2 Replace image2text model check with internal image. (#4250)
### What problem does this PR solve?

#4243

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-26 19:46:42 +08:00
600f435d27 Fix text (#4244)
### What problem does this PR solve?

Fix frontend text

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-26 17:03:48 +08:00
722545e5e0 Fix bugs (#4241)
### What problem does this PR solve?

1. Refactor error message
2. Fix knowledges are created on ES and can't be found in Infinity. The
document chunk fetch error.

### Type of change

- [x] Fix bug
- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-26 16:08:17 +08:00
9fa73771ee Fixed invoke component parameters #4236 (#4237)
### What problem does this PR solve?

to fixed issue https://github.com/infiniflow/ragflow/issues/4236

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-26 16:06:19 +08:00
fe279754ac Update version info (#4232)
### What problem does this PR solve?

Update version info to 0.15.1

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-26 12:15:28 +08:00
7e063283ba Removing invisible chars before tokenization. (#4233)
### What problem does this PR solve?

#4223

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-26 11:48:16 +08:00
28eeb29b88 Fix component input error. (#4231)
### What problem does this PR solve?

#4108

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-26 10:13:47 +08:00
85511cb1fd Miscellaneous updates (#4228)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-12-25 20:21:38 +08:00
a3eeb5de32 Fix: Q&A chunk modification (#4227)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-25 19:11:16 +08:00
1160b58b6e Update pyproject.toml to 0.15.1 (#4222)
### What problem does this PR solve?

Missing update information

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-25 14:06:00 +08:00
61790ebe15 Fix: Rename chat name, missing field 'avatar' #4125 (#4221)
### What problem does this PR solve?

Fix: Rename chat name, missing field 'avatar' #4125

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-25 11:25:50 +08:00
bc3288d390 Fix misspell. (#4219)
### What problem does this PR solve?
#4216

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-25 10:48:59 +08:00
4e5f92f01b Fix interface as input variable for component. (#4212)
### What problem does this PR solve?

#4108

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-24 17:58:11 +08:00
7d8e0602aa Remove session owner check. (#4211)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-24 17:40:31 +08:00
03cbbf7784 Add user_id for third-party system to record sessions. (#4206)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-12-24 15:59:11 +08:00
b7a7413419 Bump infinity to 0.5.2 (#4207)
### What problem does this PR solve?

Bump infinity to 0.5.2

### Type of change

- [x] Refactoring
2024-12-24 15:17:37 +08:00
321e9f3719 fix: stop rerank by model when search result is empty (#4203)
### What problem does this PR solve?


stop rerank by model when search result is empty, otherwise rerank may
raise an error (qwen).

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: 刘博 <liubo@ynby.cn>
2024-12-24 14:33:46 +08:00
76cd23eecf Catch the exception while parsing pptx. (#4202)
### What problem does this PR solve?
#4189

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-24 10:49:28 +08:00
d030b4a680 Update progress time info (#4193)
### What problem does this PR solve?

Ignore the millisecond and microsecond value.

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-23 21:04:44 +08:00
a9fd6066d2 Fix score() issue (#4194)
### What problem does this PR solve?

as title

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-23 21:01:20 +08:00
c373dba0bc Fix raptor bug. (#4192)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-23 18:59:48 +08:00
cf62230548 Fix: Fixed the issue that the page crashed when the node ID was the same as the combo ID #4180 (#4191)
### What problem does this PR solve?

Fix: Fixed the issue that the page crashed when the node ID was the same
as the combo ID #4180

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-23 18:13:56 +08:00
8d73cf6f02 Added time to progress message (#4185)
### What problem does this PR solve?

Added time to progress message

### Type of change

- [x] Refactoring
2024-12-23 17:25:55 +08:00
b635002666 Fix duplicated communitiy (#4187)
### What problem does this PR solve?

#4180

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-23 17:07:12 +08:00
4abc144d3d Fix error of changing embedding model (#4184)
### What problem does this PR solve?

1. Change embedding model of knowledge base won't change the default
embedding model.
2. Retrieval test bug

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-23 16:23:54 +08:00
a4bccc1ae7 Feat: If there is no result in the recall test, an empty data image will be displayed. #4182 (#4183)
### What problem does this PR solve?

Feat: If there is no result in the recall test, an empty data image will
be displayed. #4182
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-23 15:17:56 +08:00
8f070c3d56 Fix 'SCORE' not found bug (#4178)
### What problem does this PR solve?

As title

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-23 14:50:12 +08:00
31d67c850e Fetch chunk by batches. (#4177)
### What problem does this PR solve?

#4173

### Type of change

- [x] Performance Improvement
2024-12-23 12:12:15 +08:00
2cbe064080 Add Llama3.3 (#4174)
### What problem does this PR solve?

#4168

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-23 11:18:01 +08:00
cac7851fc5 Update jin10.svg (#4159)
Can custom color and size instead of base64
2024-12-23 10:34:13 +08:00
96da618b6a Fix bug over chunks classification by document in the promp (#4156)
The refactor in 0.15 contains a small bug that eliminate the
classification

### What problem does this PR solve

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2024-12-23 10:22:57 +08:00
f13f503952 Use s3 configuration from settings module (#4167)
### What problem does this PR solve?

Fix the issue when retrieving AWS credentials from the S3 configuration
from the settings module instead of getting from the environment
variables.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-23 10:22:45 +08:00
cb45431412 Fix Voyage re-rank model. Limit file name length. (#4171)
### What problem does this PR solve?

#4152 
#4154

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-23 10:03:50 +08:00
85083ad400 Validate returned chunk at list_chunks and add_chunk (#4153)
### What problem does this PR solve?

Validate returned chunk at list_chunks and add_chunk

### Type of change

- [x] Refactoring
2024-12-20 22:55:45 +08:00
35580af875 Update the component of the agent API with parameters. (#4131)
### What problem does this PR solve?

Update the  component of the agent API with parameters.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-12-20 17:34:16 +08:00
a0dc9e1bdf Fix position_int on infinity (#4144)
### What problem does this PR solve?

Fix position_int on infinity

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-20 11:30:33 +08:00
6379a934ff Fix redis get error. (#4140)
### What problem does this PR solve?

#4126
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-20 10:39:50 +08:00
10a62115c7 Fix example in doc (#4133)
### What problem does this PR solve?

Fix example in doc

### Type of change

- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-19 20:08:22 +08:00
e38e3bcc3b Mask password in log (#4129)
### What problem does this PR solve?

Mask password in log

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-19 18:37:01 +08:00
8dcf99611b Corrections. (#4127)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-12-19 18:19:56 +08:00
213218a094 Refactor ask decorator (#4116)
### What problem does this PR solve?

Refactor ask decorator

### Type of change

- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-19 18:13:33 +08:00
478da3118c add gemini 2.0 (#4115)
add gemini 2.0
2024-12-19 17:30:45 +08:00
101b8ff813 fix chunk method "Table" losing content when the Excel file has multi… (#4123)
…ple sheets

### What problem does this PR solve?
discussed in https://github.com/infiniflow/ragflow/pull/4102
- In excel_parser.py, `total` means the total number of rows in Excel,
but it return in the first iterate, that lead to the wrong `to_page`
- In table.py, it when Excel file has multiple sheets, it will be
divided into multiple parts, every part size is 3000, `data` may be
empty, because it has recorded in the last iterate.
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-19 17:30:26 +08:00
d8fca43017 Make fast embed and default embed mutually exclusive. (#4121)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-12-19 17:27:09 +08:00
b35e811fe7 Add parameters for ask_chat and fix bugs in list_sessions (#4119)
### What problem does this PR solve?

Add parameters for ask_chat and fix bugs in list_sessions
#4105
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-19 17:24:26 +08:00
7474348394 Fix fastembed reloading issue. (#4117)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-19 16:18:18 +08:00
8939206531 Separated list_agents() from session management (#4111)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-12-19 14:36:51 +08:00
57c99dd811 Fixed infinity exception SCORE() / SCORE_FACTORS() requires Fusion or MATCH TEXT or MATCH TENSOR (#4110)
### What problem does this PR solve?

Fixed infinity exception SCORE() / SCORE_FACTORS() requires Fusion or
MATCH TEXT or MATCH TENSOR. Close #4109

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-19 13:49:36 +08:00
561eeabfa4 add typo locale (#4099)
Add typo vi
2024-12-19 13:34:11 +08:00
5fb9136251 Miscellaneous updates to session APIs (#4097)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-18 19:01:05 +08:00
044bb0334b Fix release.yml (#4100)
### What problem does this PR solve?

Fix release.yml

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-18 17:23:29 +08:00
a5cf6fc546 Feat: Translate the previous run into parsing #4094 (#4095)
### What problem does this PR solve?

Feat: Translate the previous run into parsing #4094

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-18 16:16:57 +08:00
57fe5d0864 Add latest updates. (#4093)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-12-18 16:00:24 +08:00
bfdc4944a3 Added release notes for v0.15.0 (#4056)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-12-18 15:46:31 +08:00
a45ba3a91e Prepare docs for v0.15.0 release (#4077)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-12-18 15:32:15 +08:00
e513ad2f16 Feat: Add MultiSelect #3221 (#4090)
### What problem does this PR solve?

Feat: Add MultiSelect #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-18 14:51:24 +08:00
1fdad50dac Fix raptor (#4089)
### What problem does this PR solve?

Fix raptor

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-18 14:42:33 +08:00
4764ca5ef7 Bump infinity to 0.5.0 (#4088)
### What problem does this PR solve?

Bump infinity to 0.5.0

### Type of change

- [x] Refactoring
2024-12-18 14:39:09 +08:00
85f3d92816 Update team invite message (#4085)
### What problem does this PR solve?

Refactor inviting team member message.

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-18 14:20:09 +08:00
742eef028f Add huqie trie to docker image. (#4084)
### What problem does this PR solve?



### Type of change

- [x] Performance Improvement
2024-12-18 14:19:43 +08:00
dfbdeaddaf Fix: Fixed the issue where the required information in the input box was incorrect when inviting users #2834 (#4086)
### What problem does this PR solve?

Fix: Fixed the issue where the required information in the input box was
incorrect when inviting users #2834

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-18 14:07:56 +08:00
50c2b9d562 Refactor trie load and construct (#4083)
### What problem does this PR solve?

1. Fix initial build and load trie
2. Update comment

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-18 12:52:56 +08:00
f8cef73244 Fix abnormal user invitaion message. (#4081)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-18 12:45:24 +08:00
f8c9ec4d56 Fix arm doc (#4080)
### What problem does this PR solve?

Fix arm doc

### Type of change

- [x] Documentation Update
2024-12-18 11:51:03 +08:00
db74a3ef34 Fix conversation bug in agent session (#4078)
### What problem does this PR solve?

Fix conversation bug in agent session

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-18 11:49:25 +08:00
00f99ecbd5 Fix: Fixed the issue with external chat box reporting errors #3909 (#4079)
### What problem does this PR solve?

Fix:  Fixed the issue with external chat box reporting errors #3909

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-18 11:16:52 +08:00
0a3c6fff7c update chinese model warning message (#4075)
### What problem does this PR solve?

fix chinese warning to update model

### Type of change

- [x] Other (please describe): see the message

---------

Signed-off-by: Hui Peng <benquike@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-18 11:16:31 +08:00
79e435fc2e Fix: The cursor is lost after entering a character in the operator form #4072 (#4073)
### What problem does this PR solve?

Fix: The cursor is lost after entering a character in the operator form
#4072

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-17 18:07:22 +08:00
163c2a70fc Feat: Add AdvancedSettingForm #3221 (#4071)
### What problem does this PR solve?

Feat: Add AdvancedSettingForm #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 17:58:03 +08:00
bedc09f69c Add Architecture-Specific Logic for msodbcsql in Dockerfile #4036 (#4049)
### What problem does this PR solve?

For the new feature Add mssql support in the Dockerfile, I suggest
including support for msodbcsql18 for ARM64.
Based on current testing results (on macOS ARM64 environment),
msodbcsql18 needs to be installed.
I hope future Dockerfiles can incorporate a conditional check for this.
Specifically:

When $ARCH=arm64 (macOS ARM64 environment), install msodbcsql18.
In other cases (general x86_64 environment), install msodbcsql17.
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Mage Lu <magelu@MagedeMac-mini.local>
2024-12-17 17:44:51 +08:00
251592eeeb show avatar dialog instead of default (#4033)
show avatar dialog instead of default

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-17 17:29:35 +08:00
09436f6c60 Elasticsearch disk-based shard allocator use absolute byte values instead of ratio (#4069)
### What problem does this PR solve?

Elasticsearch disk-based shard allocator use absolute byte values
instead of ratio. Close #4018

### Type of change

- [ ] Documentation Update
- [x] Refactoring
2024-12-17 16:48:40 +08:00
e8b4e8b3d7 Feat: Bind event to the theme Switch #3221 (#4067)
### What problem does this PR solve?

Feat: Bind event to  the theme Switch #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 16:32:17 +08:00
000cd6d615 Fix position lost issue. (#4068)
### What problem does this PR solve?

#4040

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-17 16:31:58 +08:00
1d65299791 Fix rerank_model bug in chat and markdown bug (#4061)
### What problem does this PR solve?

Fix rerank_model bug in chat and markdown bug
#4000
#3992
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-17 16:03:37 +08:00
bcccaccc2b Added pagerank support to infinity (#4059)
### What problem does this PR solve?

Added pagerank support to infinity

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-17 15:45:01 +08:00
fddac1345d Fix raptor resuable issue. (#4063)
### What problem does this PR solve?

#4045

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 15:28:35 +08:00
4a95349492 Feat: Modify the link address of the agent id #3909 (#4062)
### What problem does this PR solve?

Feat: Modify the link address of the agent id #3909

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 15:13:22 +08:00
0fcb564261 Feat: Modify the text of the embedded website button #3909 (#4057)
### What problem does this PR solve?

Feat: Modify the text of the embedded website button #3909

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 14:46:54 +08:00
96667696d2 Compatible with former API keys. (#4055)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-17 13:58:26 +08:00
ce1e855328 Upgrades Document Layout Analysis model. (#4054)
### What problem does this PR solve?

#4052

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 11:27:19 +08:00
b5e4a5563c Feat: Set the color of the canvas's control button #3851 (#4053)
### What problem does this PR solve?

Feat: Set the color of the canvas's control button #3851

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 11:23:00 +08:00
1053ef5551 Fix: Hide the upload button in the external chat box #2242 (#4048)
### What problem does this PR solve?

Fix: Hide the upload button in the external chat box  #2242

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-17 10:32:52 +08:00
cb6e9ce164 Cache the result from llm for graphrag and raptor (#4051)
### What problem does this PR solve?

#4045

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-17 09:48:03 +08:00
8ea631a2a0 Fix: Every time you switch the page number of a chunk, the PDF document will be reloaded. #4046 (#4047)
### What problem does this PR solve?

Fix: Every time you switch the page number of a chunk, the PDF document
will be reloaded. #4046

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-16 18:51:45 +08:00
7fb67c4f67 Fix chunk number error after re-parsing. (#4043)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-16 15:23:49 +08:00
44ac87aef4 Remove Redundant None Check for vector_similarity_weight (#4037)
### What problem does this PR solve?
The removed if statement is unnecessary and adds cognitive load for
readers.
The original code:
```
vector_similarity_weight = req.get("vector_similarity_weight", 0.3)
if vector_similarity_weight is None:
    vector_similarity_weight = 0.3
```
has been simplified to:
```
vector_similarity_weight = req.get("vector_similarity_weight", 0.3)
```

### Type of change
- [x] Refactoring
2024-12-16 14:35:21 +08:00
7ddccbb952 extraction sqlquery (#4027)
clone https://github.com/infiniflow/ragflow/pull/4023 
improve the information extraction, most llm return results in markdown
format ````sql ___ query `____ ```
2024-12-16 09:46:59 +08:00
4a7bc4df92 Updated configurations (#4032)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2024-12-13 19:45:54 +08:00
3b7d182720 Fixed a display issue (#4030)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-12-13 19:11:52 +08:00
78527acd88 Update launch_ragflow_from_source.md (#4005)
update install  poetry full package

- [x] Documentation Update
2024-12-13 18:58:01 +08:00
e5c3083826 Updated RAGFlow Agent UI (#4029)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-12-13 18:57:22 +08:00
9b9039de92 Fix connection error for adding visual llm. (#4028)
### What problem does this PR solve?

#3897

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-13 18:54:51 +08:00
9b2ef62aee Fix xinfo_groups returns unexpected result (#4026)
### What problem does this PR solve?

Fix xinfo_groups returns unexpected result. Close #3545 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-13 17:31:15 +08:00
86507af770 Set task progress on exception (#4025)
### What problem does this PR solve?

Set task progress on exception

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-13 17:15:08 +08:00
93635674c3 Feat: Reparse a file shall reuse existing chunks if possible #3793 (#4021)
### What problem does this PR solve?

Feat: Reparse a file shall reuse existing chunks if possible #3793

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-13 16:55:13 +08:00
1defe0b19b Feat: Supports to debug single component in Agent. #3993 (#4007)
### What problem does this PR solve?

Feat: Supports to debug single component in Agent. #3993
Fix: The github button on the login page is displayed incorrectly  #4002

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-13 14:43:24 +08:00
0bca46ac3a Migrate infinity at startup (#3858)
### What problem does this PR solve?

Migrate infinity at startup

#3809
https://github.com/infiniflow/infinity/issues/2321

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-13 13:43:56 +08:00
1ecb687c51 Fix bugs in agent api and update api document (#3996)
### What problem does this PR solve?

Fix bugs in agent api and update api document

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-13 10:25:52 +08:00
68d46b2a1e Fix bug in hierarchical_merge function (#4006)
### What problem does this PR solve?

Fix hierarchical_merge function. From idx vs. actual value to actual
value vs. actual value.
Related issue #4003 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: luopan <luopan@example.com>
2024-12-13 08:50:58 +08:00
7559bbd46d Component debugging funcionality. (#4012)
### What problem does this PR solve?

#3993
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-13 08:50:32 +08:00
275b5d14f2 Fix json file parse (#4004)
### What problem does this PR solve?

Fix json file parsing

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-12 20:34:46 +08:00
9ae81b42a3 Updated UI (#4011)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-12-12 19:46:53 +08:00
d6c74ff131 Add mssql support (#3985)
some thing
-  execsql  add connection mssql
- fix bug duckduckgo-search rate limit
- update typo vi res

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-12 19:26:44 +08:00
e8d74108a5 Fix: Completion AttributeError: 'list' object has no attribute 'get' (#3999)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: lizheng@ssc-hn.com <lizheng@ssc-hn.com>
2024-12-12 19:00:34 +08:00
c8b1a564aa Replaced md5 with xxhash64 for chunk id (#4009)
### What problem does this PR solve?

Replaced md5 with xxhash64 for chunk id

### Type of change

- [x] Refactoring
2024-12-12 17:47:39 +08:00
301f95837c Try to reuse existing chunks (#3983)
### What problem does this PR solve?

Try to reuse existing chunks. Close #3793
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-12 16:38:03 +08:00
835fd7abcd Updated RAGFlow edition descriptions (#4001)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-12-12 11:45:59 +08:00
bb8f97c9cd UI updates + RAGFlow image description (#3995)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-12-12 09:57:52 +08:00
6d19294ddc Support debug components. (#3994)
### What problem does this PR solve?

#3993

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-11 19:23:59 +08:00
f61c276f74 Update comment (#3981)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-12-11 18:39:09 +08:00
409acf0d9f Fix: Fixed the issue where two consecutive indexes were displayed incorrectly #3839 (#3988)
### What problem does this PR solve?

Fix: Fixed the issue where two consecutive indexes were displayed
incorrectly #3839

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-11 16:29:17 +08:00
74c6b21f3b Update api documents (#3979)
### What problem does this PR solve?

Update api documents

### Type of change

- [x] Documentation Update

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-11 12:38:57 +08:00
beeacd3e3f Fix exec sql exception issue. (#3982)
### What problem does this PR solve?
#3978

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-11 11:44:59 +08:00
95259af68f update typo vietnamese (#3973)
update typo vietnamese

### Type of change
- [x] Refactoring

---------

Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: bill <yibie_jingnian@163.com>
2024-12-11 11:12:57 +08:00
855455006b Disable SQL DB binlog in Helm chart (#3976)
### What problem does this PR solve?

The initial Helm chart implementation added in #3815 suffers from an
issue where the 5GB data volume for the SQL DB is filled up with
[binlog](https://dev.mysql.com/doc/refman/8.4/en/binary-log.html) files
after just a few days. Since the app uses a non-replicated SQL DB config
I think it makes sense to disable the binlog in the SQL DB container.
This is achieved by simply adding the required argument to the container
startup command.

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2024-12-11 11:10:33 +08:00
b844ad6e06 Added release notes (#3969)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-12-10 19:38:27 +08:00
e0533f19e9 Fix: Answers with links to information not parsing #3839 (#3968)
### What problem does this PR solve?

Fix: Answers with links to information not parsing #3839

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-10 18:58:06 +08:00
9a6d976252 Add back beartype (#3967)
### What problem does this PR solve?

Add back beartype

### Type of change

- [x] Refactoring
2024-12-10 18:43:43 +08:00
3d76f10a91 Fixed retrieval TypeError: unhashable type: 'list' (#3966)
### What problem does this PR solve?

Fixed retrieval TypeError: unhashable type: 'list'

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-10 18:28:56 +08:00
e9b8c30a38 Support iframe chatbot. (#3961)
### What problem does this PR solve?

#3909

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-10 17:03:24 +08:00
601d74160b Feat: Exclude reference from the data returned by the conversation/get interface #3909 (#3962)
### What problem does this PR solve?

Feat: Exclude reference from the data returned by the conversation/get
interface #3909

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-10 16:46:47 +08:00
fc4e644e5f Feat: Modify the data structure of the chunk in the conversation #3909 (#3955)
### What problem does this PR solve?

Feat: Modify the data structure of the chunk in the conversation #3909

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-10 16:36:16 +08:00
03f00c9e6f Rename page_num_list, top_list, position_list (#3940)
### What problem does this PR solve?

Rename page_num_list, top_list, position_list to page_num_int, top_int,
position_int

### Type of change

- [x] Refactoring
2024-12-10 16:32:58 +08:00
87e46b4425 Fixed README (#3956)
### What problem does this PR solve?

Fixed README

### Type of change

- [x] Documentation Update
2024-12-10 12:11:39 +08:00
d5a322a352 Theme switch support (#3568)
### What problem does this PR solve?
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-12-10 11:42:04 +08:00
7d4f1c0645 Case insensitive when set doc engine (#3954)
### What problem does this PR solve?

DOC_ENGINE="INFINITY" or "Infinity" or "Elasticsearch" also works

### Type of change

- [x] Refactoring

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-10 11:26:10 +08:00
927873bfa6 Fix syn error. (#3953)
### What problem does this PR solve?

Close #3696
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-10 10:54:54 +08:00
5fe0791684 Allows quick entry of entities separated by commas (#3914)
Allows quick entry of entities separated by commas

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-10 10:29:27 +08:00
3e134ac0ad Miscellaneous updates (#3942)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update

---------

Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2024-12-10 10:19:50 +08:00
7a6bf4326e Fixed log not displaying (#3946)
### What problem does this PR solve?

Fixed log not displaying

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-10 09:36:59 +08:00
41a0601735 organize chunks by document in the prompt (#3925)
### What problem does this PR solve?

This PR organize chunks in the prompt by document and indicate what is
the name of the document in this way

```
Document: {doc_name} \nContains the following relevant fragments:
chunk1
chunk2
chunk3

Document: {doc_name} \nContains the following relevant fragments:
chunk4
chunk5
```

Maybe can be a baseline to add metadata to the documents.

This allow in my case to improve llm context about the orgin of the
information.


### Type of change

- [X] New Feature (non-breaking change which adds functionality)

Co-authored-by: Miguel <your-noreply-github-email>
2024-12-10 09:06:52 +08:00
60486ecde5 api http return error (#3941)
api http  return error when content is not found


- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-10 09:04:24 +08:00
255f4ccffc Fix session API issues. (#3939)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-09 17:37:36 +08:00
afe82feb57 Fix error message for image access. (#3936)
### What problem does this PR solve?

#3883

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-09 15:24:58 +08:00
044afa83d1 Fix transformers dependencies for slim. (#3934)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-09 14:21:37 +08:00
4b00be4173 Fixed tmp in Dockerfile (#3933)
### What problem does this PR solve?

Fixed tmp in Dockerfile

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-09 14:20:18 +08:00
215e9361ea Fix field missing issue. (#3931)
### What problem does this PR solve?

#3905
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-09 13:20:58 +08:00
aaec630759 Obsoleted dev and dev-slim (#3930)
### What problem does this PR solve?

Obsoleted dev and dev-slim
### Type of change

- [x] Documentation Update
2024-12-09 12:44:57 +08:00
3d735dca87 Add support to iframe chatbot (#3929)
### What problem does this PR solve?

#3909

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-09 12:38:04 +08:00
dcedfc5ec8 Add Japanese support (#3906)
### What problem does this PR solve?

Add native translation in locales for Japanese 🇯🇵 to support new local
language



### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Hiroshi Kameya <kameya_h@sunflare.co.jp>
2024-12-09 11:38:06 +08:00
1254ecf445 Added static check at PR CI (#3921)
### What problem does this PR solve?

Added static check at PR CI

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Refactoring
2024-12-08 21:23:51 +08:00
0d68a6cd1b Fix errors detected by Ruff (#3918)
### What problem does this PR solve?

Fix errors detected by Ruff

### Type of change

- [x] Refactoring
2024-12-08 14:21:12 +08:00
e267a026f3 Fix VERSION 2024-12-07 16:56:34 +08:00
44d4686b20 Fix release.yml 2024-12-07 15:21:24 +08:00
95614175e6 Update oc9 docker compose file (#3913)
### What problem does this PR solve?

Update OC9 docker compose files

issue: #3901

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-07 11:04:45 +08:00
c817ff184b Refactor UI text (#3911)
### What problem does this PR solve?

Refactor UI text

### Type of change

- [x] Documentation Update
- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-07 11:04:36 +08:00
f284578cea Fix release.yml 2024-12-06 23:00:29 +08:00
e69e6b2274 Fix VERSION 2024-12-06 22:51:31 +08:00
8cdb805c0b Fix release.py 2024-12-06 22:31:27 +08:00
885418f3b0 Fix release.yml 2024-12-06 21:10:06 +08:00
b44321f9c3 Introduced NEED_MIRROR (#3907)
### What problem does this PR solve?

Introduced NEED_MIRROR

### Type of change

- [x] Refactoring
2024-12-06 20:47:22 +08:00
f54a8d7748 Remove vector stored in component output. (#3908)
### What problem does this PR solve?

Close #3805

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-06 18:32:57 +08:00
311a475b6f Fix: Fixed the issue that the agent list page failed to load #3827 (#3902)
### What problem does this PR solve?

Fix: Fixed the issue that the agent list page failed to load #3827

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-06 17:05:40 +08:00
655b01a0a4 Remove token check while adding model. (#3903)
### What problem does this PR solve?

#3820

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-06 17:01:19 +08:00
d4ee082735 fix 2024-12-06 15:50:58 +08:00
1f5a7c4b12 Fix release.yml 2024-12-06 15:24:53 +08:00
dab58b9311 Fix release.yml 2024-12-06 14:41:43 +08:00
e56a60b316 Fixed release.yml 2024-12-06 14:37:41 +08:00
f189452446 Fix: An error occurred when deleting a new conversation #3898 (#3900)
### What problem does this PR solve?

Fix: An error occurred when deleting a new conversation #3898

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-06 14:24:41 +08:00
f576c555e4 Fixed release.yml 2024-12-06 14:18:42 +08:00
d8eea624e2 release with CI (#3891)
### What problem does this PR solve?

Refactor Dockerfile files.
Release with CI.

### Type of change

- [x] Refactoring
2024-12-06 14:05:30 +08:00
e64c7dfdf6 Feat: Import & export the agents. #3851 (#3894)
### What problem does this PR solve?

Feat: Import & export the agents. #3851

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-06 13:43:17 +08:00
c76e7b1e28 Fix typos (#3887)
### What problem does this PR solve?

Lots of typo, also need to merge into DEMO

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-06 09:47:56 +08:00
0d5486aa57 Add a dependency blincker. (#3882)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 18:14:39 +08:00
3a0e9f9263 Feat: Add tooltip to question item of ChunkCreatingModal #3873 (#3880)
### What problem does this PR solve?

Feat: Add tooltip to question item of ChunkCreatingModal  #3873

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-05 17:03:20 +08:00
1f0a153d0e Revert "Feat: Add tooltip to question item of ChunkCreatingModal #3873" (#3879)
Reverts infiniflow/ragflow#3878
2024-12-05 16:51:33 +08:00
8bdf1d98a3 Feat: Add tooltip to question item of ChunkCreatingModal #3873 (#3878)
### What problem does this PR solve?

Feat: Add tooltip to question item of ChunkCreatingModal  #3873

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-05 16:49:55 +08:00
8037dc7b76 Fix chunk available issue (#3877)
### What problem does this PR solve?

Close #3873

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 16:49:43 +08:00
56f473b680 Feat: Add question parameter to edit chunk modal (#3875)
### What problem does this PR solve?

Close #3873

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-05 14:51:19 +08:00
b502dc7399 Feat: Adjust the input box width of EditTag to 100% #3873 (#3876)
### What problem does this PR solve?

Feat: Adjust the input box width of EditTag to 100% #3873

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-05 14:29:49 +08:00
cfe23badb0 Feat: Add question parameter to edit chunk modal #3873 (#3874)
### What problem does this PR solve?

Feat: Add question parameter to edit chunk modal #3873

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-05 13:58:33 +08:00
593ffc4067 Fix HuggingFace model error. (#3870)
### What problem does this PR solve?

#3865

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 13:28:42 +08:00
a88a1848ff Fix: The right coordinates of Categorize and Switch operators are misplaced #3868 (#3869)
### What problem does this PR solve?

Fix: The right coordinates of Categorize and Switch operators are
misplaced #3868

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 10:53:44 +08:00
5ae33184d5 Fix chunk position issue. (#3867)
### What problem does this PR solve?

Close #3864

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 10:53:26 +08:00
78601ee1bd Fix open AI compatible rerank issue. (#3866)
### What problem does this PR solve?
#3700
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-05 10:26:21 +08:00
84afb4259c Feat: Bind the route to the navigation bar in the head #3221 (#3863)
### What problem does this PR solve?
Feat: Bind the route to the navigation bar in the head #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-04 19:10:08 +08:00
1b817a5b4c Refine synonym query. (#3855)
### What problem does this PR solve?

### Type of change

- [x] Performance Improvement
2024-12-04 17:20:12 +08:00
1b589609a4 Add sdk for list agents and sessions (#3848)
### What problem does this PR solve?

Add sdk for list agents and sessions

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-04 16:23:22 +08:00
289f4f1916 Fix: Hide the download button if it is an empty file #3762 (#3853)
### What problem does this PR solve?

Fix: Hide the download button if it is an empty file #3762

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-04 15:09:41 +08:00
cf37e2ef1a Fix: Delete unused code #3651 (#3852)
### What problem does this PR solve?

Fix: Delete unused code #3651

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-04 14:15:17 +08:00
41e2dadea7 Feat: Fixed the problem of not finding EmailForm #3837 (#3847)
### What problem does this PR solve?

Feat: Fixed the problem of not finding EmailForm #3837

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-04 14:05:07 +08:00
f3318b2e49 Update docs. (#3849)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-12-04 12:23:31 +08:00
3f3469130b Fix preview issue in file manager. (#3846)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-04 11:53:23 +08:00
fc38afcec4 Web: Fixed the download and preview file not authorized. (#3652)
https://github.com/infiniflow/ragflow/issues/3651

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-04 11:48:06 +08:00
efae7afd62 Email sending tool (#3837)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._
Added the function of sending emails through SMTP
Instructions for use-
Corresponding parameters need to be configured
Need to output upstream in a fixed format

![image](https://github.com/user-attachments/assets/93bc1af7-6d4f-4406-bd1d-bc042535dd82)


### Type of change


- [√] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-12-04 11:21:17 +08:00
285bc58364 Update QRcode (#3844)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-04 10:11:20 +08:00
6657ca7cde Change default error message to English (#3838)
### What problem does this PR solve?

As title

### Type of change

- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-12-04 09:34:49 +08:00
87455d79e4 Add api for list agents and agent seesions (#3835)
### What problem does this PR solve?

Add api for list agents and agent seesions

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-03 19:03:16 +08:00
821fdf02b4 Fix parsing JSON file error (#3829)
### What problem does this PR solve?

Close issue: #3828

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-03 19:02:03 +08:00
54980337e4 Feat: Modify the style of the home page in bright mode #3221 (#3832)
### What problem does this PR solve?

Feat: Modify the style of the home page in bright mode #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-03 18:59:11 +08:00
92ab7ef659 Refactor embedding batch_size (#3825)
### What problem does this PR solve?

Refactor embedding batch_size. Close #3657

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Refactoring
2024-12-03 16:22:39 +08:00
934dbc2e2b Add more mistral models. (#3826)
### What problem does this PR solve?

#3647

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-03 15:18:38 +08:00
95da6de9e1 Fix the agent reference bug and the session prologue (#3823)
### What problem does this PR solve?

Fix the agent reference bug and the session prologue
#3285 #3819
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-03 14:49:26 +08:00
ccdeeda9cc Add Helm chart deployment method (#3815)
### What problem does this PR solve?

Add's a Helm chart for deploying RAGFlow on Kubernetes. 

Closes #864. 

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2024-12-03 14:48:36 +08:00
74b28ef1b0 Add pagerank to KB. (#3809)
### What problem does this PR solve?

#3794

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-12-03 14:30:35 +08:00
7543047de3 Fix @ in model name issue. (#3821)
### What problem does this PR solve?

#3814

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-03 12:41:39 +08:00
e66addc82d Feat: Store the pagerank field at the outermost #3794 (#3822)
### What problem does this PR solve?

Feat: Store the pagerank field at the outermost #3794

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-03 11:55:21 +08:00
7b6a5ffaff Fix: page_chars attribute does not exist in some formats of PDF (#3796)
### What problem does this PR solve?

In #3335 someone suggested to upgrade pdfplumber==0.11.1, but that
didn't solve it.
It's actually the special formatting in some of the pdfs that triggers
the problem.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-03 11:08:06 +08:00
19545282aa Web API test cases (#3812)
### What problem does this PR solve?

1. Failed update dataset case
2. Upload and parse text file

### Type of change

- [x] Other (please describe): test cases

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-03 10:33:35 +08:00
6a0583f5ad Fix voyage embedding. (#3818)
### What problem does this PR solve?

#3816 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-03 09:33:54 +08:00
ed7e46b6ca Feat: Add TestingForm #3221 (#3810)
### What problem does this PR solve?

Feat: Add TestingForm #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-02 19:33:20 +08:00
9654e64a0a Fix the bug that the agent could not find the context (#3795)
### What problem does this PR solve?

Fix the bug that the agent could not find the context
#3682
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-02 19:05:18 +08:00
8b650fc9ef Feat: Supports page rank score for different knowledge bases. #3794 (#3800)
### What problem does this PR solve?

Feat: Supports page rank score for different knowledge bases. #3794

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-02 19:00:11 +08:00
69fb323581 [DOC] We have no plan to maintain Docker images for ARM. Please build your … (#3808)
…Docker image

### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-12-02 18:56:55 +08:00
9d093547e8 Improved ollama doc (#3787)
### What problem does this PR solve?

Improved ollama doc. Close #3723

### Type of change

- [x] Documentation Update
2024-12-02 17:28:30 +08:00
c5f13629af Set Log level by env (#3798)
### What problem does this PR solve?

Set Log level by env

### Type of change

- [x] Refactoring
2024-12-02 17:24:39 +08:00
c4b6df350a More dataset test cases (#3802)
### What problem does this PR solve?

1. Test not allowed fields of dataset

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Other (please describe): Test cases

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-02 17:15:19 +08:00
976d112280 Feat: Quit from jointed team #3759 (#3797)
### What problem does this PR solve?

Feat: Quit from jointed team #3759

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-12-02 15:31:41 +08:00
8fba5c4179 Update document: how upload file large than 128MB (#3791)
### What problem does this PR solve?

As title.

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-12-02 14:37:37 +08:00
d19f059f34 Detect invalid response from api.siliconflow.cn (#3792)
### What problem does this PR solve?

Detect invalid response from api.siliconflow.cn. Close #2643

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-02 12:55:05 +08:00
deca6c1b72 Fix service_conf for oc9 docker compose file. (#3790)
### What problem does this PR solve?

#3678

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-02 12:00:58 +08:00
3ee9ca749d Fix the bug that prevented modifying dataset_ids (#3784)
### What problem does this PR solve?

Fix the bug that prevented modifying `dataset_ids`.
 #3772

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-12-02 11:40:20 +08:00
7058ac0041 Fix out of boundary. (#3786)
### What problem does this PR solve?

#3769
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-12-02 11:38:53 +08:00
a7efd3cac5 Removed obsolete instructions (#3785)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-12-02 10:51:48 +08:00
59a5813f1b add jina new models in jina connector (#3770)
### What problem does this PR solve?

add new models in jinna connector, to allow use models that support
multilingual models

### Type of change

- [X] Other (please describe): new connectors no breaking change
2024-12-02 10:06:39 +08:00
08c1a5e1e8 Refactor parse progress (#3781)
### What problem does this PR solve?

Refactor parse file progress

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-01 22:28:00 +08:00
ea84cc2e33 Update file parsing progress info (#3780)
### What problem does this PR solve?

Refine the file parsing progress info

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-01 17:03:00 +08:00
b5f643681f Update README (#3777)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-01 14:53:51 +08:00
5497ea34b9 Update QR code of wechat (#3776)
### What problem does this PR solve?

Update wechat group QR code.

### Type of change

- [x] Documentation Update

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-12-01 12:47:53 +08:00
e079656473 Update progress info and start welcome info (#3768)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-30 18:48:06 +08:00
d00297a763 Fix chunk creation using Infinity (#3763)
### What problem does this PR solve?

1. Store error type in Infinity
2. position list value read from Infinity isn't correct.

Fix issue: #3729

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-30 00:10:14 +08:00
a19210daf1 Feat: Add tooltip to delimiter filed #1909 (#3758)
### What problem does this PR solve?

Feat: Add tooltip to delimiter filed #1909

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-29 18:13:59 +08:00
b2abc36baa Optimize the knowledge base card UI (#3756)
### What problem does this PR solve?

Set the title to 2 lines, display the excess part
Set the description to 3 lines, display the excess part

![image](https://github.com/user-attachments/assets/4b01cac5-b7a3-40cc-8965-42aeba9ea233)

![image](https://github.com/user-attachments/assets/aa4230eb-100f-4905-9cf0-75ce9813a332)


### Type of change

- [x] Other (please describe):
2024-11-29 18:02:17 +08:00
fadbe23bfe Feat: Translate comments of file-util.ts to English #3749 (#3757)
### What problem does this PR solve?

Feat: Translate comments of file-util.ts to English #3749

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-29 18:01:14 +08:00
ea8a59d0b0 Image compression (#3749)
### What problem does this PR solve?

The uploaded avatar has been compressed to preserve transparency while
meeting the length requirements for the 'text' type. The current
compressed size is 100x100 pixels.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-29 17:15:46 +08:00
381219aa41 Fixed increase_usage for builtin models (#3748)
### What problem does this PR solve?

Fixed increase_usage for builtin models. Close #1803

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-29 17:02:49 +08:00
0f08b0f053 Weight up title and keywords for chunks in terms of retrieval (#3750)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-29 16:39:55 +08:00
0dafce31c4 Feat: Support for formulas #1954 (#3747)
### What problem does this PR solve?

Feat: Support for formulas #1954

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-29 16:34:30 +08:00
c93e0355c3 Feat: Add DatasetTable #3221 (#3743)
### What problem does this PR solve?

Feat: Add DatasetTable #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-29 16:05:46 +08:00
1e0fc76efa Added release notes v0.11.0 (#3745)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-29 16:00:42 +08:00
d94386e00a Pass top_p to ollama (#3744)
### What problem does this PR solve?

Pass top_p to ollama. Close #1769

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-29 14:52:27 +08:00
0a62dd7a7e Update document (#3746)
### What problem does this PR solve?

Fix description on local LLM deployment case

### Type of change

- [x] Documentation Update

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-11-29 14:50:45 +08:00
06a21d2031 Change Traditional Chinese to Simplified Chinese (#3742)
### What problem does this PR solve?

Change Traditional Chinese to Simplified Chinese

### Type of change

- [x] Other (please describe):
2024-11-29 13:45:31 +08:00
9a3febb7c5 Refactor dockerfile (#3741)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-11-29 13:37:50 +08:00
27cd765d6f Fix raptor issue (#3737)
### What problem does this PR solve?

#3732

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-29 11:55:41 +08:00
a0c0a957b4 Fix GPU docker compose file (#3736)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-11-29 10:49:15 +08:00
b89f7c69ad Fix image_id absence issue (#3735)
### What problem does this PR solve?

#3731

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-29 10:37:09 +08:00
fcdc6ad085 Fix the issue where the agent interface cannot call the context (#3725)
### What problem does this PR solve?

Fix the context of the agent interface call to the context during web
testing, and change it to the context record of user chat
Remove duplicate messages and add them, which can be viewed in the
messages section of database api_4_comversation

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-11-29 10:36:48 +08:00
834c4d81f3 Update version info to v0.14.1 (#3720)
### What problem does this PR solve?

Update version info to v0.14.1

### Type of change

- [x] Documentation Update

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-28 20:09:20 +08:00
a3e0ac9c0b Fix: Clicking the checkbox of the pop-up window for editing chunk is invalid #3726 (#3727)
### What problem does this PR solve?

Fix: Clicking the checkbox of the pop-up window for editing chunk is
invalid #3726

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-28 20:08:06 +08:00
80af3cc2d4 Don't log exception if object doesn't exist (#3724)
### What problem does this PR solve?

Don't log exception if object doesn't exist. Close #1483

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-28 19:37:01 +08:00
966bcda6b9 Updated descriptions for the Agent components (#3728)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-28 19:32:50 +08:00
112ef42a19 Ensure thumbnail be smaller than 64K (#3722)
### What problem does this PR solve?

Ensure thumbnail be smaller than 64K. Close #1443
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-28 19:15:31 +08:00
91f1814a87 Fix error response (#3719)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-11-28 18:56:10 +08:00
4e8e4fe53f Feat: Add Dataset page #3221 (#3721)
### What problem does this PR solve?

Feat: Add Dataset page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-28 18:44:36 +08:00
cdae8d28fe Fix test cases (#3718)
### What problem does this PR solve?

Fix test cases

### Type of change

- [x] Other (please describe): Fix error cases

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-28 17:37:46 +08:00
964a6f4ec4 Added an infinity configuration file to easily customize the settings of Infinity (#3715)
### What problem does this PR solve?

Added an infinity configuration file to easily customize the settings of
Infinity

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-28 15:59:00 +08:00
9fcad0500d Add more web test cases (#3702)
### What problem does this PR solve?

Test cases about dataset

### Type of change

- [x] Other (please describe): test cases

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-28 15:46:35 +08:00
ec560cc99d Feat: Scrolling knowledge base list and set the number of entries per page to 30 #3695 (#3712)
### What problem does this PR solve?

Feat: Scrolling knowledge base list and set the number of entries per
page to 30 #3695

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-28 15:25:38 +08:00
7ae8828e61 Added release notes v0.12.0 (#3711)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-11-28 14:57:50 +08:00
43e367f2ea Detect shape error of embedding (#3710)
### What problem does this PR solve?

Detect shape error of embedding. Close #2997

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-28 14:10:22 +08:00
e678819f70 Fix RGBA error (#3707)
### What problem does this PR solve?

**Passing cv_mdl.describe() is not an RGB converted image**

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-28 13:09:02 +08:00
bc701d7b4c Edit chunk shall update instead of insert it (#3709)
### What problem does this PR solve?

Edit chunk shall update instead of insert it. Close #3679 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-28 13:00:38 +08:00
9f57534843 Revert "Feat: Scrolling knowledge base list #3695" (#3708)
Reverts infiniflow/ragflow#3703
2024-11-28 11:44:23 +08:00
52b3492b18 Feat: Scrolling knowledge base list #3695 (#3703)
### What problem does this PR solve?

Feat: Scrolling knowledge base list #3695

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-28 10:51:30 +08:00
2229431803 Added release notes for v0.13.0 (#3691)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-27 19:26:03 +08:00
57208d8e53 Fix batch size issue. (#3675)
### What problem does this PR solve?

#3657

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-27 18:06:43 +08:00
535b15ace9 Feat: Add dataset sidebar #3221 (#3683)
### What problem does this PR solve?

Feat: Add dataset sidebar #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-27 18:06:05 +08:00
2249d5d413 Always open text file for write with UTF-8 (#3688)
### What problem does this PR solve?

Always open text file for write with UTF-8. Close #932 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-27 16:24:16 +08:00
6fb1a181aa Added aspose on macosx/arm64 (#3686)
### What problem does this PR solve?

Added aspose on macosx/arm64. Close #3666 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-27 15:00:07 +08:00
90ffcb4ddb Fix graphrag + infinity bugs (#3681)
### What problem does this PR solve?

Fix graphrag + infinity bugs

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-27 12:45:43 +08:00
7f48acb3fd Fix enable/disable bug (#3662)
### What problem does this PR solve?

Fix enable/disable bug   #3628

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-27 09:37:11 +08:00
d61bbe6750 Use polars-lts-cpu on arm64 (#3667)
### What problem does this PR solve?

Use polars-lts-cpu on arm64

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-27 09:32:41 +08:00
ee37ee3d28 Feat: Add Datasets page #3221 (#3661)
### What problem does this PR solve?

Feat: Add Datasets page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-27 09:31:08 +08:00
8b35776916 Fix a bug in VolcEngine (#3658)
### What problem does this PR solve?

Fix a bug in VolcEngine  #3553

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-27 09:30:49 +08:00
b6f3f15f0b Fix KB list bugs and add web api test (#3649)
### What problem does this PR solve?

1. Read KB list path parameter, page_number and page_size, which type
isn't int
2. Add cases on create / list / delete datasets.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Test cases

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-26 18:21:15 +08:00
fa8e2c1678 Added release notes (#3660)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-11-26 18:11:39 +08:00
7669fc8f52 Fix es get NotFoundError (#3659)
### What problem does this PR solve?

Fix es get NotFoundError

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-26 18:07:07 +08:00
98cf1c2a9d Feat: add PromptManagement page #3221 (#3650)
### What problem does this PR solve?

Feat: add PromptManagement page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-26 16:55:44 +08:00
5337cad7e4 Check model id when set dialog. Close #849 (#3655)
### What problem does this PR solve?

Check model id when set dialog. Close #849

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-26 16:32:46 +08:00
0891a393d7 Let ThreadPool exit gracefully. (#3653)
### What problem does this PR solve?

#3646

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-26 16:31:07 +08:00
5c59651bda Fix the bug causing garbled text (#3640)
### What problem does this PR solve?

Fix the bug causing garbled text #3613

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-26 12:06:56 +08:00
f6c3d7ccf6 Fixed es mapping (#3643)
### What problem does this PR solve?

Fixed es mapping

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-26 12:00:19 +08:00
3df1663e4f For security. (#3642)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-26 09:34:34 +08:00
32cf566a08 Feat: Add ModelManagement page #3221 (#3638)
### What problem does this PR solve?

Feat: Add ModelManagement page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-26 09:10:48 +08:00
769c67a470 Updated UI (#3639)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-11-25 19:32:25 +08:00
49494d4e3c Update version number for poetry (#3637)
### What problem does this PR solve?



### Type of change

- [x] Refactoring
2024-11-25 17:57:08 +08:00
3839d8abc7 Updated FAQ and Upgrade guide (#3636)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-25 17:29:56 +08:00
d8b150a34c Add support for folder deletion (#3635)
### What problem does this PR solve?

Add support for folder deletion.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-25 16:59:43 +08:00
4454b33e51 Feat: Add PricingCard component #3221 (#3634)
### What problem does this PR solve?

Feat: Add PricingCard component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-25 16:21:47 +08:00
ce6b4c0e05 Fix a bug in completions (#3632)
### What problem does this PR solve?

Fix a bug in completions

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-25 16:21:28 +08:00
ddf01e0450 Fix missing info in README and config error (#3633)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-25 15:53:29 +08:00
86e48179a1 Fix bugs in api (#3624)
### What problem does this PR solve?

#3488

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-25 15:25:48 +08:00
b2c33b4df7 DOC: Added health check and team management (#3630)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-25 14:31:01 +08:00
9348616659 Handle infinity empty response (#3627)
### What problem does this PR solve?

Handle infinity empty response. Close #3623
Show version in docker build log

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-25 14:09:42 +08:00
a0e9b62de5 Feat: Add TeamManagement component #3221 (#3626)
### What problem does this PR solve?

Feat: Add TeamManagement component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-25 12:21:37 +08:00
7874aaaf60 doc:rewrite some confusing statement (#3607)
rewrite some confusing statement to improve user experience
2024-11-25 11:57:31 +08:00
08ead81dde Bump infinity to v0.5.0-dev5 (#3520)
### What problem does this PR solve?

Bump infinity to v0.5.0-dev5

### Type of change

- [x] Refactoring
2024-11-25 11:53:58 +08:00
e5af18d5ea Update docs for v0.14.0 (#3625)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-11-25 11:37:56 +08:00
609236f5c1 Let 'One' applicable for tables in docx (#3619)
### What problem does this PR solve?

#3598

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Performance Improvement
2024-11-25 09:57:54 +08:00
6a3f9bc32a Restore version info to v0.13.0 (#3605)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-11-23 17:06:22 +08:00
934d6d9ad1 Update quickstart.mdx (#3603)
### What problem does this PR solve?

Fixed typo from RAGFlow_IMAGE to RAGFlOW_IMAGE

### Type of change

- [X] Documentation Update
2024-11-23 15:27:13 +08:00
875096384b when qwen rerank model not return ok, raise exception to notice user (#3593)
### What problem does this PR solve?

When calling the Qwen rerank model, if the model does not return
correctly, an exception should be raised to notify the user, rather than
simply returning a value of 0, as this would be confusing to the user.
### Type of change          

- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 22:34:34 +08:00
a10c2f2eff Fix: Solve the problem of model files in the image being soft links pointing to a non-existent address. #3584 (#3586)
### What problem does this PR solve?

Fix: Solve the problem of model files in the image being soft links
pointing to a non-existent address. #3584

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-22 21:54:39 +08:00
646ac1f2b4 Improved image build instructions (#3580)
### What problem does this PR solve?

Improved arm64 image build instructions

### Type of change

- [x] Documentation Update
- [x] Refactoring
2024-11-22 20:24:32 +08:00
8872aed512 Feat: Modify the prompt text for deleting team members #2834 (#3599)
### What problem does this PR solve?
Feat: Modify the prompt text for deleting team members #2834

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 18:50:53 +08:00
55692e4da6 Feat: Capitalize the first letter of the team's role #2834 (#3597)
### What problem does this PR solve?

Feat: Capitalize the first letter of the team's role #2834

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 18:19:34 +08:00
6314d3c727 Updates for readme (#3595)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-11-22 16:47:45 +08:00
06b9256972 Feat: remove useSetLlmSetting from GenerateForm #3591 (#3592)
### What problem does this PR solve?

Feat: remove useSetLlmSetting from GenerateForm #3591

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-22 16:31:44 +08:00
cc219ff648 Fix agent session API (#3589)
### What problem does this PR solve?

#3585
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-22 16:19:00 +08:00
ee33bf71eb Feat: Add ProfileSetting page #3221 (#3588)
### What problem does this PR solve?

Feat: Add ProfileSetting page  #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 15:11:38 +08:00
ee7fd71fdc Add an agent template: SEO bloger (#3582)
### What problem does this PR solve?

#3560

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 13:12:05 +08:00
d56f52eef8 Fix agent api invokation issue (#3581)
### What problem does this PR solve?

#3570 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-22 12:37:27 +08:00
9f3141804f Fix chunk enable/disable issue (#3579)
### What problem does this PR solve?

#3576

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-22 12:25:42 +08:00
60a3e1a8dc Update Docker .env (#3576)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-11-22 12:03:46 +08:00
9541d7e7bc Added TRACE_MALLOC_DELTA and TRACE_MALLOC_FULL (#3555)
### What problem does this PR solve?

Added TRACE_MALLOC_DELTA and TRACE_MALLOC_FULL to debug task_executor.py
heap. Relates to #3518

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-22 12:00:25 +08:00
811c49d7a2 Updated obsolete faqs (#3575)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2024-11-22 11:11:06 +08:00
482c1b59c8 Check tika.parser return result (#3564)
### What problem does this PR solve?

Check tika.parser return result. Close #3229

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
2024-11-22 11:05:06 +08:00
691ea287c2 Added RAGFlow image version into bug report template (#3561)
### What problem does this PR solve?

Add RAGFlow image version into bug report template

### Type of change

- [x] Other (please describe):
2024-11-22 10:50:13 +08:00
b87d14492f Revert "Updated obsolete faqs (#3554)" (#3573)
This reverts commit 13ff463845.

### What problem does this PR solve?


### Type of change

- [x] Other (please describe):
2024-11-22 10:42:10 +08:00
cc5960b88e Vietnamese language support on web (#3549)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2024-11-21 18:43:08 +08:00
ee50f78d99 Add component 'Template' (#3562)
### What problem does this PR solve?

#3560

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-21 18:26:22 +08:00
193b08a3ed Fix: Limit node version #3547 (#3563)
### What problem does this PR solve?

Fix: Limit node version #3547

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-21 18:14:22 +08:00
3a3e23d8d9 Feat: Add Template operator #3556 (#3559)
### What problem does this PR solve?

Feat: Add Template operator #3560

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-21 18:05:31 +08:00
30f111edb3 Fixs for translation agent (#3557)
### What problem does this PR solve?

#3556 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-11-21 16:22:25 +08:00
d47ee88454 Feat: When saving the canvas, other dls parameters passed from the backend are spliced ​​into the dsl parameters #3355 (#3558)
### What problem does this PR solve?

Feat: When saving the canvas, other dls parameters passed from the
backend are spliced ​​into the dsl parameters #3355
#3556

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-21 16:21:54 +08:00
13ff463845 Updated obsolete faqs (#3554)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-11-21 16:15:37 +08:00
bf9ebda3c8 Add tests for frontend API (#3552)
### What problem does this PR solve?

Add tests for frontend API

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-21 15:39:25 +08:00
85dd9fde43 Fix a bug in agent api (#3551)
### What problem does this PR solve?

Fix a bug in agent api
#3539

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-21 12:45:22 +08:00
c7c8b3812f Add test for document (#3548)
### What problem does this PR solve?

Add test for document

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-21 12:02:26 +08:00
0ac6dc8f8c Cut down the attempt times of ES (#3550)
### What problem does this PR solve?

#3541
### Type of change


- [x] Refactoring
- [x] Performance Improvement
2024-11-21 11:37:45 +08:00
58a2200b80 Fix: search issue for graphrag (#3546)
### What problem does this PR solve?

#3538

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-21 11:13:29 +08:00
e10b0e6b60 Fix: Inaccurate description (#3540)
### What problem does this PR solve?

Correction of inaccurate front-end description.

![image](https://github.com/user-attachments/assets/4a7330b5-1384-4092-825d-56675fb5799c)

![image](https://github.com/user-attachments/assets/b3737912-4f5a-4928-a629-404a4fa4da6e)

### Type of change

- [x] Refactoring
2024-11-21 10:09:20 +08:00
d9c882399d Ensure LIGHTEN work (#3542)
### What problem does this PR solve?
#3531

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-21 09:56:28 +08:00
8930bfcff8 Fix bugs (#3535)
### What problem does this PR solve?

1. system monitor icon and text missing
2. Team knowledge base can't be search

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-20 20:55:42 +08:00
9b9afa9d6e Feat: Display the input parameters of begin in the output result table #3355 (#3534)
### What problem does this PR solve?

Feat: Display the input parameters of begin in the output result table
#3355

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-20 20:55:31 +08:00
362db857d0 New: a new interpretor based on Andrew Ng theory. (#3532)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-20 20:55:22 +08:00
541272eb99 Fix: authorization issue (#3530)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:55:10 +08:00
5b44b99cfd Removed beartype (#3528)
### What problem does this PR solve?

The beartype configuration of
main(64f50992e0) is:
```
from beartype import BeartypeConf
from beartype.claw import beartype_all  # <-- you didn't sign up for this
beartype_all(conf=BeartypeConf(violation_type=UserWarning))    # <-- emit warnings from all code
```

ragflow_server failed at a third-party package:

```
(ragflow-py3.10) zhichyu@iris:~/github.com/infiniflow/ragflow$ rm -rf logs/* && bash docker/launch_backend_service.sh 
Starting task_executor.py for task 0 (Attempt 1)
Starting ragflow_server.py (Attempt 1)
Traceback (most recent call last):
  File "/home/zhichyu/github.com/infiniflow/ragflow/api/ragflow_server.py", line 22, in <module>
    from api.utils.log_utils import initRootLogger
  File "/home/zhichyu/github.com/infiniflow/ragflow/api/utils/__init__.py", line 25, in <module>
    import requests
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/requests/__init__.py", line 43, in <module>
    import urllib3
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/__init__.py", line 15, in <module>
    from ._base_connection import _TYPE_BODY
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/_base_connection.py", line 5, in <module>
    from .util.connection import _TYPE_SOCKET_OPTIONS
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/__init__.py", line 4, in <module>
    from .connection import is_connection_dropped
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/connection.py", line 7, in <module>
    from .timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/timeout.py", line 20, in <module>
    _DEFAULT_TIMEOUT: Final[_TYPE_DEFAULT] = _TYPE_DEFAULT.token
NameError: name 'Final' is not defined
Traceback (most recent call last):
  File "/home/zhichyu/github.com/infiniflow/ragflow/rag/svr/task_executor.py", line 22, in <module>
    from api.utils.log_utils import initRootLogger
  File "/home/zhichyu/github.com/infiniflow/ragflow/api/utils/__init__.py", line 25, in <module>
    import requests
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/requests/__init__.py", line 43, in <module>
    import urllib3
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/__init__.py", line 15, in <module>
    from ._base_connection import _TYPE_BODY
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/_base_connection.py", line 5, in <module>
    from .util.connection import _TYPE_SOCKET_OPTIONS
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/__init__.py", line 4, in <module>
    from .connection import is_connection_dropped
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/connection.py", line 7, in <module>
    from .timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
  File "/home/zhichyu/github.com/infiniflow/ragflow/.venv/lib/python3.10/site-packages/urllib3/util/timeout.py", line 20, in <module>
    _DEFAULT_TIMEOUT: Final[_TYPE_DEFAULT] = _TYPE_DEFAULT.token
NameError: name 'Final' is not defined
```

This third-package is out of our control. I have to remove beartype
entirely.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:54:57 +08:00
6be7901df2 Warning instead of exception on type mismatch (#3523)
### What problem does this PR solve?

Warning instead of exception on type mismatch.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:54:42 +08:00
4d42bcd517 Feat: merge the begin operator's url and file into one field #3355 (#3521)
### What problem does this PR solve?

Feat: merge the begin operator's url and file into one field #3355
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-20 20:54:27 +08:00
9b4c2868bd Fix set_output type hint (#3516)
### What problem does this PR solve?

Fix set_output type hint

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:54:09 +08:00
d02a2b131a Fix: potential risk (#3515)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-11-20 20:53:58 +08:00
81c7b6afc5 Make spark model robuster to model name (#3514)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:53:44 +08:00
cad341e794 Added kb_id filter to knn. Fix #3458 (#3513)
### What problem does this PR solve?

Added kb_id filter to knn. Fix #3458

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:53:30 +08:00
e559cebcdc fix: keyerror issue (#3512)
### What problem does this PR solve?

#3511

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:53:20 +08:00
8b4407a68c feat: Add Datasets component to home page #3221 (#3508)
### What problem does this PR solve?

feat: Add Datasets component to home page #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-20 20:53:07 +08:00
289034f36e smooth term weight (#3510)
### What problem does this PR solve?

#3499

### Type of change

- [x] Performance Improvement
2024-11-20 20:52:51 +08:00
17a7ea42eb fix synonym bug (#3506)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-20 20:52:36 +08:00
2044bb0039 Fix bugs (#3502)
### What problem does this PR solve?

1. Remove unused code
2. Fix type mismatch, in nlp search and infinity search interface
3. Fix chunk list, get all chunks of this user.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-20 20:52:23 +08:00
c4f2464935 fix: laws.py added missing import logging (#3501)
### What problem does this PR solve?

_Choosing Laws Chunk Method results in an error when parsing a document.
The error is caused by a missing import in the `laws.py` file._

```
Traceback (most recent call last):
  File "/ragflow/rag/svr/task_executor.py", line 445, in handle_task
    do_handle_task(task)
  File "/ragflow/rag/svr/task_executor.py", line 384, in do_handle_task
    cks = build(r)
          ^^^^^^^^
  File "/ragflow/rag/svr/task_executor.py", line 196, in build
    cks = chunker.chunk(row["name"], binary=binary, from_page=row["from_page"],
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ragflow/rag/app/laws.py", line 161, in chunk
    for txt, poss in pdf_parser(filename if not binary else binary,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ragflow/rag/app/laws.py", line 124, in __call__
    logging.debug("layouts:".format(
    ^^^^^^^
NameError: name 'logging' is not defined. Did you forget to import 'logging'

```

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: Michal Masrna <m.marna1@gmail.com>
2024-11-20 20:52:05 +08:00
bcb6f7168f [bug]import typing.cast for leiden.py (#3493)
### What problem does this PR solve?

leiden alg throws exception for lack func cast definition

### Type of change

- Bug Fix (non-breaking change which fixes an issue)
2024-11-19 18:42:30 +08:00
361cff34fc add input variables to begin component (#3498)
### What problem does this PR solve?

#3355 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-19 18:41:48 +08:00
0cd5b64c3b Changed requirement to python 3.10 (#3496)
### What problem does this PR solve?

Changed requirement to python 3.10.
Changed image base to Ubuntu 22.04 since it contains python 3.10.

### Type of change

- [x] Refactoring
2024-11-19 18:25:04 +08:00
16fbe9920d feat: Stream the greetings of the agent dialogue #3355 (#3490)
### What problem does this PR solve?

feat: Stream the greetings of the agent dialogue #3355

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-19 15:14:35 +08:00
e4280be5e5 minor (#3483)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-11-19 14:59:21 +08:00
d42362deb6 Add api for sessions and add max_tokens for tenant_llm (#3472)
### What problem does this PR solve?

Add api for sessions and add max_tokens for tenant_llm

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-19 14:51:33 +08:00
883fafde72 Fix elasticsearch status display (#3487)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-19 14:40:58 +08:00
568322aeaf fix(rag): fix error in viewing document chunk and cannot start task_executor server (#3481)
### What problem does this PR solve?

1. Fix error in viewing document chunk

<img width="1677" alt="Pasted Graphic"
src="https://github.com/user-attachments/assets/acd84cde-f38c-4190-b135-5e5139ae2613">

Viewing document chunk details in a BeartypeCallHintParamViolation
error.

Traceback (most recent call last):
File "ragflow/.venv/lib/python3.12/site-packages/flask/app.py", line
880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
File "ragflow/.venv/lib/python3.12/site-packages/flask/app.py", line
865, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
# type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "ragflow/.venv/lib/python3.12/site-packages/flask_login/utils.py",
line 290, in decorated_view
    return current_app.ensure_sync(func)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "ragflow/api/apps/chunk_app.py", line 311, in knowledge_graph
sres = settings.retrievaler.search(req, search.index_name(tenant_id),
kb_ids)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<@beartype(rag.nlp.search.Dealer.search) at 0x3381fd800>", line
39, in search
beartype.roar.BeartypeCallHintParamViolation: Method
rag.nlp.search.Dealer.search() parameter
idx_names='ragflow_0e1e67f431d711ef98fc00155d29195d' violates type hint
list[str], as str 'ragflow_0e1e67f431d711ef98fc00155d29195d' not
instance of list.
2024-11-19 11:30:29,817 ERROR 91013 Method
rag.nlp.search.Dealer.search() parameter
idx_names='ragflow_0e1e67f431d711ef98fc00155d29195d' violates type hint
list[str], as str 'ragflow_0e1e67f431d711ef98fc00155d29195d' not
instance of list.
Traceback (most recent call last):
  File "ragflow/api/apps/chunk_app.py", line 60, in list_chunk
sres = settings.retrievaler.search(query, search.index_name(tenant_id),
kb_ids, highlight=True)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<@beartype(rag.nlp.search.Dealer.search) at 0x3381fd800>", line
39, in search
beartype.roar.BeartypeCallHintParamViolation: Method
rag.nlp.search.Dealer.search() parameter
idx_names='ragflow_0e1e67f431d711ef98fc00155d29195d' violates type hint
list[str], as str 'ragflow_0e1e67f431d711ef98fc00155d29195d' not
instance of list.


because in nlp/search.py,the idx_names is only list

<img width="1098" alt="Pasted Graphic 2"
src="https://github.com/user-attachments/assets/4998cb1e-94bc-470b-b2f4-41ecb5b08f8a">

but the DocStoreConnection.search method accept list or str
<img width="1175" alt="Pasted Graphic 3"
src="https://github.com/user-attachments/assets/ee918b4a-87a5-42c9-a6d2-d0db0884b875">


and his implements also list and str
es_conn.py

<img width="1121" alt="Pasted Graphic 4"
src="https://github.com/user-attachments/assets/3e6dc030-0a0d-416c-8fd4-0b4cfd576f8c">

infinity_conn.py

<img width="1221" alt="Pasted Graphic 5"
src="https://github.com/user-attachments/assets/44edac2b-6b81-45b0-a3fc-cb1c63219015">

2. Fix cannot star task_executor server with Unresolved reference
'Mapping'
<img width="1283" alt="Pasted Graphic 6"
src="https://github.com/user-attachments/assets/421f17b8-d0a5-46d3-bc4d-d05dc9dfc934">

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-11-19 14:36:10 +08:00
31decadd8e feat: Let the top navigation bar open in a tab when you right click on it #3018 (#3486)
### What problem does this PR solve?

feat: Let the top navigation bar open in a tab when you right click on
it #3018

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-19 14:20:00 +08:00
dec9b3e540 Fix logs. Use dict.pop instead of del. Close #3473 (#3484)
### What problem does this PR solve?

Fix logs. Use dict.pop instead of del.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-19 14:15:25 +08:00
d0f94a42ff Refactor ragflow server (#3482)
### What problem does this PR solve?

1. Fix document error
2. Move start server out of if __main__ branch.

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-19 12:31:20 +08:00
ed0d47fc8a feat: "Open link in new tab" doesn't work for profile image #3018 (#3480)
### What problem does this PR solve?

feat:  "Open link in new tab" doesn't work for profile image #3018

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-19 11:40:59 +08:00
aa9a16e073 Fix document error (#3456)
### What problem does this PR solve?

1. Update README.md
2. Fix error description in docker/.env

### Type of change

- [x] Documentation Update

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-19 11:31:11 +08:00
eef84a86bf feat: Disable clicking the Next button while uploading files in RunDrawer #3355 (#3477)
### What problem does this PR solve?

feat: Disable clicking the Next button while uploading files in
RunDrawer #3355

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-19 11:03:39 +08:00
ed72d1100b minor format updates (#3471)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-18 19:19:28 +08:00
f4e9dae33a Updated upgrade guide to avoid confusion (#3469)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-18 19:07:05 +08:00
50f7b7e0a3 feat: Capture task executor null value exception #3409 (#3468)
### What problem does this PR solve?

feat: Capture task executor null value exception #3409

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-18 19:06:52 +08:00
01c2712941 feat: Display task executor tooltip with json-view #3409 (#3467)
### What problem does this PR solve?

feat: Display task executor  tooltip with json-view #3409

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-18 18:36:18 +08:00
4413683898 Introduced beartype (#3460)
### What problem does this PR solve?

Introduced [beartype](https://github.com/beartype/beartype) for runtime
type-checking.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-18 17:38:17 +08:00
3824c1fec0 feat: Show task_executor heartbeat #3409 (#3461)
### What problem does this PR solve?

feat: Show task_executor heartbeat #3409
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-18 17:23:49 +08:00
4b3eeaa6ef Added LocalAI support for rerank models (#3446)
### What problem does this PR solve?

Hi there!
LocalAI added support of rerank models
https://localai.io/features/reranker/

I've implemented LocalAIRerank class (typically copied it from
OpenAI_APIRerank class).
Also, LocalAI model response with 500 error code if len of "documents"
is less than 2 in similarity check.
So I've added the second "document" on RERANK model connection check in
`api/apps/llm_app.py`.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-18 12:05:52 +08:00
70cd5c1599 Remove unused code (#3448)
### What problem does this PR solve?

1. Remove unused code.
2. Move some codes from settings to constants

### Type of change

- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-18 12:05:38 +08:00
f9643adc43 Adjusted heartbeat format (#3459)
### What problem does this PR solve?

Adjusted heartbeat format

### Type of change

- [x] Refactoring
2024-11-18 12:03:28 +08:00
7b9e0723d6 build(deps): bump cross-spawn from 7.0.3 to 7.0.5 in /web (#3455)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from
7.0.3 to 7.0.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md">cross-spawn's
changelog</a>.</em></p>
<blockquote>
<h3><a
href="https://github.com/moxystudio/node-cross-spawn/compare/v7.0.4...v7.0.5">7.0.5</a>
(2024-11-07)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>fix escaping bug introduced by backtracking (<a
href="640d391fde">640d391</a>)</li>
</ul>
<h3><a
href="https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.4">7.0.4</a>
(2024-11-07)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>disable regexp backtracking (<a
href="https://redirect.github.com/moxystudio/node-cross-spawn/issues/160">#160</a>)
(<a
href="5ff3a07d9a">5ff3a07</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="085268352d"><code>0852683</code></a>
chore(release): 7.0.5</li>
<li><a
href="640d391fde"><code>640d391</code></a>
fix: fix escaping bug introduced by backtracking</li>
<li><a
href="bff0c87c8b"><code>bff0c87</code></a>
chore: remove codecov</li>
<li><a
href="a7c6abc6fe"><code>a7c6abc</code></a>
chore: replace travis with github workflows</li>
<li><a
href="9b9246e096"><code>9b9246e</code></a>
chore(release): 7.0.4</li>
<li><a
href="5ff3a07d9a"><code>5ff3a07</code></a>
fix: disable regexp backtracking (<a
href="https://redirect.github.com/moxystudio/node-cross-spawn/issues/160">#160</a>)</li>
<li><a
href="9521e2da94"><code>9521e2d</code></a>
chore: fix tests in recent node js versions</li>
<li><a
href="97ded399e9"><code>97ded39</code></a>
chore: convert package lock</li>
<li><a
href="d52b6b9da4"><code>d52b6b9</code></a>
chore: remove unused argument (<a
href="https://redirect.github.com/moxystudio/node-cross-spawn/issues/156">#156</a>)</li>
<li><a
href="5d843849e1"><code>5d84384</code></a>
chore: add travis jobs on ppc64le (<a
href="https://redirect.github.com/moxystudio/node-cross-spawn/issues/142">#142</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cross-spawn&package-manager=npm_and_yarn&previous-version=7.0.3&new-version=7.0.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 11:19:44 +08:00
a1d01a1b2f enlarge the default token length of RAPTOR summarization (#3454)
### What problem does this PR solve?

#3426

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-18 10:15:26 +08:00
dc05f43eee Minor: Fixed a broken link (#3451)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-16 20:22:53 +08:00
77bdeb32bd Added current task into task executor's hearbeat (#3444)
### What problem does this PR solve?

Added current task into task executor's hearbeat

### Type of change

- [x] Refactoring
2024-11-15 22:55:41 +08:00
af18217d78 feat: Add banner #3221 (#3442)
### What problem does this PR solve?

feat: Add banner #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-15 19:18:23 +08:00
4ed5ca2666 handle_task catch all exception (#3441)
### What problem does this PR solve?

handle_task catch all exception
Report heartbeats

### Type of change

- [x] Refactoring
2024-11-15 18:51:09 +08:00
1e90a1bf36 Move settings initialization after module init phase (#3438)
### What problem does this PR solve?

1. Module init won't connect database any more.
2. Config in settings need to be used with settings.CONFIG_NAME

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-15 17:30:56 +08:00
ac033b62cf fix tika-server issue (#3439)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-15 16:57:01 +08:00
cb3b9d7ada refine the message of queuing a task (#3437)
### What problem does this PR solve?



### Type of change

- [x] Refactoring
2024-11-15 15:59:54 +08:00
ca9e97d2f2 Enlarge the term weight difference (#3435)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-15 15:41:50 +08:00
6d451dbe06 Updated retrieval testing UI (#3433)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-15 15:17:34 +08:00
e0659a4f0e feat: Add RunDrawer #3355 (#3434)
### What problem does this PR solve?

feat: Translation test run form #3355
feat: Wrap QueryTable with Collapse #3355
feat: If the required fields are not filled in, the submit button will
be grayed out. #3355
feat: Add RunDrawer #3355

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-15 15:17:23 +08:00
a854bc22d1 Rework task executor heartbeat (#3430)
### What problem does this PR solve?

Rework task executor heartbeat, and print in console.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-11-15 14:43:55 +08:00
48e060aa53 rm es query escape chars (#3428)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-15 13:19:07 +08:00
47abfc32d4 Remove unused settings (#3427)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-15 13:18:16 +08:00
a1ba228bc2 fix: empty token bug (#3424)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-15 10:33:03 +08:00
996c94a8e7 Move clk100k_base tokenizer to docker image (#3411)
### What problem does this PR solve?

Move the tiktoken of cl100k_base into docker image

issue: #3338 

### Type of change

- [x] Refactoring

Signed-off-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-15 10:18:40 +08:00
220aaddc62 fix: synonym bug (#3423)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-15 10:14:51 +08:00
6878d23a57 Print configs when startup RAGFlow server (#3414)
### What problem does this PR solve?

Print configs at the RAGFlow startup phase.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

```
2024-11-14 21:27:53,090 INFO     962231 Current configs, from /home/weilongma/Documents/development/ragflow/conf/service_conf.yaml:
2024-11-14 21:27:53,090 INFO     962231 ragflow: {'host': '0.0.0.0', 'http_port': 9380}
2024-11-14 21:27:53,090 INFO     962231 mysql: {'name': 'rag_flow', 'user': 'root', 'password': 'infini_rag_flow', 'host': 'mysql', 'port': 5455, 'max_connections': 100, 'stale_timeout': 30}
2024-11-14 21:27:53,090 INFO     962231 minio: {'user': 'rag_flow', 'password': 'infini_rag_flow', 'host': 'minio:9000'}
2024-11-14 21:27:53,090 INFO     962231 es: {'hosts': 'http://es01:1200', 'username': 'elastic', 'password': 'infini_rag_flow'}
2024-11-14 21:27:53,090 INFO     962231 redis: {'db': 1, 'password': 'infini_rag_flow', 'host': 'redis:6379'}
```

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-15 09:29:40 +08:00
df9d054551 Updated descriptions of agent APIs (#3407)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-11-14 18:44:37 +08:00
30c1f7ee29 make variables access robuster (#3406)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-14 18:28:41 +08:00
e4c4fdabbd Update version display on web UI (#3405)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
2024-11-14 17:51:21 +08:00
30f6421760 Use consistent log file names, introduced initLogger (#3403)
### What problem does this PR solve?

Use consistent log file names, introduced initLogger

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-11-14 17:13:48 +08:00
ab4384e011 Updates on parsing progress, including more detailed time cost inform… (#3402)
### What problem does this PR solve?

#3401 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-14 16:28:10 +08:00
201bbef7c0 Print version when RAGFlow server startup (#3393)
### What problem does this PR solve?

Print version when RAGFlow server startup

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-14 15:51:30 +08:00
95d21e5d9f fix: standardize property name from 'chat' to 'chat_id' (#3383)
### What problem does this PR solve?

This PR addresses the inconsistency in property naming within the
codebase by renaming the 'chat' property to 'chat_id' in the session.py
file. This change aims to align the naming convention with other parts
of the application that refer to chat identifiers as 'chat_id', thereby
improving code clarity and maintainability.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-14 15:49:03 +08:00
c5368c7745 resolve halt while starting up (#3397)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-14 13:20:17 +08:00
0657a09e2c Update llm_factories.json (#3396)
### What problem does this PR solve?
Added: Claude-3-5-sonnet-20241022 version. 

### Type of change
- [x] New Feature (non-breaking change which adds functionality)
2024-11-14 13:00:16 +08:00
4caf932808 fix bug about fetching knowledge graph (#3394)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-14 12:29:15 +08:00
400fc3f5e9 Add enviroment validation at server startup phase (#3388)
### What problem does this PR solve?

1. Validate the Python version should >= 3.11
2. Download nltk data

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring

---------

Signed-off-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: jinhai <haijin.chn@gmail.com>
Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2024-11-14 11:01:08 +08:00
e44e3a67b0 adapt to lower case cohere (#3392)
### What problem does this PR solve?

#3384

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-14 10:18:25 +08:00
9d395ab74e Added doc for switching elasticsearch to infinity (#3370)
### What problem does this PR solve?

Added doc for switching elasticsearch to infinity

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
2024-11-14 00:08:55 +08:00
83c6b1f308 set DLA active for KG (#3386)
### What problem does this PR solve?

### Type of change


- [x] Refactoring
2024-11-13 16:59:19 +08:00
7ab9715b0e refine the error message (#3382)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-11-13 16:20:59 +08:00
632b23486f Fix the value issue of anthropic (#3351)
### What problem does this PR solve?

This pull request fixes the issue mentioned in
https://github.com/infiniflow/ragflow/issues/3263.

1. response should be parsed as dict, prevent the following code from
failing to take values:
ans = response["content"][0]["text"]
2. API Model ```claude-instant-1.2``` has retired (by
[model-deprecations](https://docs.anthropic.com/en/docs/resources/model-deprecations)),
it will trigger errors in the code, so I deleted it from the
conf/llm_factories.json file and updated the latest API Model
```claude-3-5-sonnet-20241022```



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: chenhaodong <chenhaodong@ctrlvideo.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-13 16:13:52 +08:00
ccf189cb7f mv service_conf.yaml to conf/ and fix: add 'answer' as a parameter to 'generate' (#3379)
### What problem does this PR solve?
#3373

### Type of change

- [x] Refactoring
- [x] Bug fix
2024-11-13 15:56:40 +08:00
1fe9a2e6fd feat: Add input parameter to begin operator #3355 (#3375)
### What problem does this PR solve?

feat: Add input parameter to begin operator #3355

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-13 14:54:10 +08:00
9fc092a911 Updated RAGFlow's dataset configuration UI (#3376)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-11-13 14:45:55 +08:00
fa54cd5f5c exstract model dir from model‘s full name (#3368)
### What problem does this PR solve?

When model’s group name contains 0-9,we can't find downloaded
model,because we do not correctly exstract model dir's name from model‘s
full name

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: 王志鹏 <zhipeng3.wang@midea.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-13 14:10:16 +08:00
667d0e5537 Turn the relative date in question to absolute date (#3372)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-13 13:49:18 +08:00
91332fa0f8 Refine english synonym (#3371)
### What problem does this PR solve?

#3361

### Type of change

- [x] Performance Improvement
2024-11-13 12:58:37 +08:00
0c95a3382b Dynamically create the service_conf.yaml file by replacing environment variables from .env (#3341)
### What problem does this PR solve?

This pull request implements the feature mentioned in #3322. 

Instead of manually having to edit the `service_conf.yaml` file when
changes have been made to `.env` and mapping it into the docker
container at runtime, a template file is used and the values replaced by
the environment variables from the `.env` file when the container is
started.
 

### Type of change

- [X] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2024-11-12 22:56:53 +08:00
7274420ecd Updated RAGFlow UI (#3362)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-12 19:56:56 +08:00
a2a5631da4 Rework logging (#3358)
Unified all log files into one.

### What problem does this PR solve?

Unified all log files into one.

### Type of change

- [x] Refactoring
2024-11-12 17:35:13 +08:00
567a7563e7 Fix bugs in api and add examples (#3353)
### What problem does this PR solve?

Fix bugs in api.
Add simple examples for api.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-12 17:14:33 +08:00
62a9afd382 Change launch backend script to handle errors gracefully (#3334)
### What problem does this PR solve?

The `launch_backend_service.sh` script enters infinite loops for both
the task executors and the backend server. When an error occurs in any
of these processes, the script continuously restarts them without
properly handling termination signals. This behavior causes the script
to even ignore interrupts, leading to persistent error messages and
making it difficult to exit the script gracefully.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

### Explanation of Modifications

1. **Signal Trapping with `trap`:** 
- The `trap cleanup SIGINT SIGTERM` line ensures that when a `SIGINT` or
`SIGTERM` signal is received, the cleanup function is invoked.
- The `cleanup` function sets the `STOP` flag to `true`, iterates
through all child process IDs stored in the `PIDS` array, and sends a
`kill` signal to each process to terminate them gracefully.
2. **Retry Limits:**
- Introduced a `MAX_RETRIES` variable to limit the number of restart
attempts for both `task_executor.py` and `ragflow_server.py`
- The loops now check if the retry count has reached the maximum limit.
If so, they invoke the `cleanup` function to terminate all processes and
exit the script.
3. **Process Tracking with `PIDS` Array:**
- After launching each background process (`task_exe` and `run_server`),
their Process IDs (PIDs) are stored in the `PIDS` array.
- This allows the `cleanup` function to terminate all child processes
effectively when needed.
4. **Graceful Shutdown:**
- When the `cleanup` function is called, it iterates over all child PIDs
and sends a termination signal (`kill`) to each, ensuring that all
subprocesses are stopped before the script exits.
5. **Logging Enhancements:**
- Added `echo` statements to provide clearer logs about the state of
each process, including attempts, successes, failures, and retries.
6. **Exit on Successful Completion:**
- If `ragflow_server.py` or a `task_executor.py` process exits with a
success code (0), the loop breaks, preventing unnecessary retries.

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-12 15:51:38 +08:00
aa68d3b8db fix: Cannot copy and paste text on agent page #3356 (#3357)
### What problem does this PR solve?

fix: Cannot copy and paste text on agent page #3356

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-12 15:49:45 +08:00
784ae896d1 add dependencies of chrome (#3352)
### What problem does this PR solve?



### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-11-12 15:49:33 +08:00
f4c52371ab Integration with Infinity (#2894)
### What problem does this PR solve?

Integration with Infinity

- Replaced ELASTICSEARCH with dataStoreConn
- Renamed deleteByQuery with delete
- Renamed bulk to upsertBulk
- getHighlight, getAggregation
- Fix KGSearch.search
- Moved Dealer.sql_retrieval to es_conn.py


### Type of change

- [x] Refactoring
2024-11-12 14:59:41 +08:00
00b6000b76 feat: Disable automatic saving of agent during running agent #3349 (#3350)
### What problem does this PR solve?

feat: Disable automatic saving of agent during running agent #3349

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-12 12:47:36 +08:00
db23d62827 feat: Add background colors such as inverse-strong #3221 (#3346)
### What problem does this PR solve?

feat: Add background colors such as inverse-strong #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-12 11:29:48 +08:00
70ea6661ed add new models for zhipu-ai (#3348)
### What problem does this PR solve?

#3345

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-12 11:27:43 +08:00
a01fceb328 feat: updates all readme to have a link to redirect to new locale (#3339)
### What problem does this PR solve?

Updates all readme to have a link to redirect to README_id.md for
documentation in Bahasa Indonesia

### Type of change

- [x] Documentation Update
2024-11-12 09:26:14 +08:00
e9e98ea093 feat: documentation updates to support Bahasa Indonesia (#3315)
### What problem does this PR solve?

Add Readme docs in Indonesia's native language (Bahasa Indonesia) for
ragflow

### Type of change

- [x] Documentation Update
2024-11-11 19:33:23 +08:00
528646a958 feat: Add custom background color #3221 (#3336)
### What problem does this PR solve?

feat: Add custom background color #3221

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-11 19:29:56 +08:00
8536335e63 Miscellaneous edits to RAGFlow's UI (#3337)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-11-11 19:29:34 +08:00
88072b1e90 fix: double brace issue (#3328)
### What problem does this PR solve?

#3299

### Type of change

- [x] Performance Improvement
2024-11-11 12:07:02 +08:00
34d1daac67 fix: Anthropic param error (#3327)
### What problem does this PR solve?

#3263

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-11 11:54:14 +08:00
3faae0b2c2 trival (#3325)
### What problem does this PR solve?



### Type of change


- [x] Performance Improvement
2024-11-11 10:39:49 +08:00
5e5a35191e fix benchmark issue (#3324)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-11 10:14:30 +08:00
7c486ee3f9 Fix typo (#3319)
### What problem does this PR solve?

Fix typo

### Type of change

- [x] Refactoring
2024-11-11 09:36:39 +08:00
20d686737a feat: Switch the login page to the registration component by changing the routing parameters #3221 (#3307)
### What problem does this PR solve?
feat: Switch the login page to the registration component by changing
the routing parameters #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 19:47:22 +08:00
85047e7e36 Added configuration guideline (#3309)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-08 19:46:18 +08:00
ac64e35a45 feat: Translate autosaved #3301 (#3304)
### What problem does this PR solve?

[_Briefly describe what this PR aims to solve. Include background
context that will help reviewers understand the purpose of the
PR._](feat: Translate autosaved #3301)

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-08 18:27:42 +08:00
004487cca0 fix term weight issue (#3306)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-08 18:25:23 +08:00
74d1eeb4d3 feat: Automatically save agent page data #3301 (#3302)
### What problem does this PR solve?

feat: Automatically save agent page data #3301

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 17:28:11 +08:00
464a4d6ead Added env. MACOS (#3297)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-08 16:50:35 +08:00
3d3913419b Updated .env and Docker README (#3295)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-11-08 16:31:52 +08:00
63f7d3bae2 feat: Support shortcut keys to copy nodes #3283 (#3293)
### What problem does this PR solve?

feat: Support shortcut keys to copy nodes #3283

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 15:50:01 +08:00
8b6e272197 fix: term weight issue (#3294)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-08 15:49:44 +08:00
5205bdab24 feat: Modify the name of the answer operator #1739 (#3288)
### What problem does this PR solve?
feat: Modify the name of the answer operator #1739

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 13:56:43 +08:00
37d4708880 Archivo ts con la traducción para el idioma español (#3274)
¿Qué problema resuelve este PR?
Archivo TS para la traducción al idioma español
Este archivo TS es un archivo de traducción que se utiliza para
proporcionar soporte multilingüe en las aplicaciones. Al agregar la
traducción al español, se facilita el cambio del idioma de la interfaz
de usuario para los usuarios hispanohablantes.

Tipo de cambio
- [x] Nueva funcionalidad (cambio no disruptivo que agrega una nueva
característica)

### What problem does this PR solve?

This TS file is a translation file used to provide multilingual support
in applications. By adding the Spanish translation, it facilitates
changing the user interface language for Spanish-speaking users._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 13:44:03 +08:00
d88f0d43ea make language judgement robuster (#3287)
### What problem does this PR solve?



### Type of change

- [x] Performance Improvement
2024-11-08 12:48:11 +08:00
a2153d61ce feat: Support shortcut keys to delete nodes #3283 (#3284)
### What problem does this PR solve?
feat: Support shortcut keys to delete nodes #3283

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-08 12:07:26 +08:00
f16ef57979 fix switch bug (#3280)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-08 10:08:57 +08:00
ff2bbb487f fix index of range (#3279)
### What problem does this PR solve?

#3273

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-08 09:58:11 +08:00
416efbe7e8 Updated Docker README (#3272)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-11-08 09:22:40 +08:00
9c6cc20356 Fix:#3230 When parsing a docx file using the Book parsing method, to_page is always -1, resulting in a block count of 0 even if parsing is successful (#3249)
### What problem does this PR solve?

When parsing a docx file using the Book parsing method, to_page is
always -1, resulting in a block count of 0 even if parsing is successful

Fix:#3230

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-11-08 09:21:42 +08:00
7c0d28b62d Refactored Docker README (#3269)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-11-07 19:38:50 +08:00
48ab6d7a45 Update authorization for team (#3262)
### What problem does this PR solve?

Update authorization for team.
#3253 #3233
### Type of change

- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-07 19:26:03 +08:00
96b5d2b3a9 fix: The name of the copy operator is displayed the same as before ##3265 (#3266)
### What problem does this PR solve?

fix: The name of the copy operator is displayed the same as before
##3265

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-07 17:53:31 +08:00
f45c29360c New locale for Bahasa Indonesia support (#3255)
### What problem does this PR solve?
Add native translation in locales for Bahasa Indonesia to support new
local language

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-07 17:53:19 +08:00
cdcbe6c2b3 Fixed broken links (#3256)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-07 14:12:32 +08:00
5038552ed9 fix: improve embedding model validation logic for dataset operations (#3235)
What problem does this PR solve?
When creating or updating datasets with custom embedding models (e.g.,
Ollama), the validation logic was too restrictive and prevented valid
models from being used. The previous implementation would reject valid
custom models if they weren't in the predefined list, even when they
existed in TenantLLMService.

Changes:
- Simplify and improve the embedding model validation flow in
create/update endpoints
- Check TenantLLMService for custom models before rejecting
- Make validation logic more consistent between create and update
operations

### What problem does this PR solve?

This fix allows users to successfully create and update datasets with
custom embedding models while maintaining proper validation checks.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: liuhua <10215101452@stu.ecnu.edu.cn>
2024-11-07 10:36:28 +08:00
1b3e39dd12 fix ci issue (#3245)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-06 19:32:30 +08:00
fbcc0bb408 accelerate tokenize (#3244)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-11-06 18:54:41 +08:00
d3bb5e9f3d feat: Display input parameters on operator nodes #3240 (#3241)
### What problem does this PR solve?
feat: Display input parameters on operator nodes #3240


### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-06 18:48:05 +08:00
4097912d59 add inputs to display to every components (#3242)
### What problem does this PR solve?

#3240

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-06 18:47:53 +08:00
f3aaa0d453 Add sdk for Agent API (#3220)
### What problem does this PR solve?

Add sdk for Agent API

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-06 18:03:45 +08:00
0dff64f6ad fix: TypeError: only length-1 arrays can be converted to Python scalars (#3211)
### What problem does this PR solve?
fix "TypeError: only length-1 arrays can be converted to Python scalars"
while using cohere embedding model.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)


![image](https://github.com/user-attachments/assets/2c21a69f-cd76-4d25-b320-058964812db8)
2024-11-06 11:15:00 +08:00
601a128cd3 feat: Add next login page with shadcn/ui #3221 (#3231)
### What problem does this PR solve?

feat: Add next login page with shadcn/ui  #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-11-06 11:13:04 +08:00
af74bf01c0 Editorial updates to Docker README (#3223)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-06 09:43:54 +08:00
a418a343d1 doc updates (#3216)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2024-11-05 16:41:43 +08:00
ab6e6019a7 Added a list of supported models (#3214)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-11-05 15:21:37 +08:00
13053172cb fix: Fixed the issue of api markdown document display being messy #2346 (#3212)
### What problem does this PR solve?

fix: Fixed the issue of api markdown document display being messy #2346

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-05 15:00:07 +08:00
38ebf6b2c0 Remove dead code (#3210)
### What problem does this PR solve?

Remove dead code

### Type of change

- [x] Refactoring
2024-11-05 14:34:49 +08:00
a7bf4ca8fc Fix bugs in API (#3204)
### What problem does this PR solve?

Fix bugs in API

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-05 14:07:31 +08:00
7e89be5ed1 feat: add qwen 2.5 models for silicon flow (#3203)
### What problem does this PR solve?

add qwen 2.5 models for silicon flow

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2024-11-05 13:58:29 +08:00
b7b30c4b57 add keyword extraction time elapsed to the little lamp. (#3207)
### What problem does this PR solve?



### Type of change

- [x] Refactoring
2024-11-05 13:39:50 +08:00
55953819c1 accelerate term weight calculation (#3206)
### What problem does this PR solve?



### Type of change

- [x] Performance Improvement
2024-11-05 13:11:26 +08:00
677f02c2a7 rm unused file (#3205)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-11-05 11:56:09 +08:00
185c6a0c71 Unified API response json schema (#3170)
### What problem does this PR solve?

Unified API response json schema

### Type of change

- [x] Refactoring
2024-11-05 11:02:31 +08:00
339639a9db add assistant to canvas chat history (#3201)
### What problem does this PR solve?

#3185

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-05 10:04:31 +08:00
18ae8a4091 raise exception if embedding model not found (#3199)
### What problem does this PR solve?

#3173 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-05 09:29:01 +08:00
cbca7dfce6 fix bugs in test (#3196)
### What problem does this PR solve?

fix bugs in test

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-11-04 20:03:14 +08:00
a9344e6838 Docs update for upgrading DLA models (#3198)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-11-04 20:02:40 +08:00
aa733b1ea4 update poetry.lock (#3197)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-04 19:18:08 +08:00
8305632852 add agent completion API (#3192)
### What problem does this PR solve?

#3105

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-04 17:20:16 +08:00
57f23e0808 feat: Add agent interface document link to agent page #3189 (#3190)
### What problem does this PR solve?

feat: Add agent interface document link to agent page #3189

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-04 17:04:35 +08:00
16b6a78c1e feat: Add tooltip to clean_html item #2908 (#3183)
### What problem does this PR solve?

feat: Add tooltip to clean_html item #2908

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-11-04 15:36:57 +08:00
dd1146ec64 feat: docs for api endpoints to generate openapi specification (#3109)
### What problem does this PR solve?

**Added openapi specification for API routes. This creates swagger UI
similar to FastAPI to better use the API.**
Using python package `flasgger`

### Type of change
- [x] New Feature (non-breaking change which adds functionality)

Not all routes are included since this is a work in progress.

Docs can be accessed on: `{host}:{port}/apidocs`
2024-11-04 15:35:36 +08:00
07c453500b set default LLM to new registered user (#3180)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-04 15:03:07 +08:00
3e4fc12d30 Updated instructions on upgrading to RAGFlow dev (#3175)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-04 13:21:29 +08:00
285fd6ae14 feat: Proxy the SDK address to the backend #3166 (#3171)
### What problem does this PR solve?

feat: Proxy the SDK address to the backend #3166

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-04 11:37:19 +08:00
8d9238db14 fix es search parameter error (#3169)
### What problem does this PR solve?

#3151

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-04 09:53:41 +08:00
c06e765a5b Added tika jar into image to avoid downloading (#3167)
### What problem does this PR solve?

Added tika jar into image to avoid downloading. Close #3017

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-03 00:20:26 +08:00
c7ea7e9974 Added jdk to happify tika (#3165)
### What problem does this PR solve?

Added jdk to happify tika(https://pypi.org/project/tika/). The image
size become ~400MB bigger. Close #2886

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-11-02 22:21:17 +08:00
37d71dfa90 Replaced redis with Valkey (#3164)
### What problem does this PR solve?

Replaced redis with Valkey. Close #3070

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-11-02 20:05:12 +08:00
44ad9a6cd7 Add test for API (#3134)
### What problem does this PR solve?

Add test for API

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2024-11-01 22:59:17 +08:00
7eafccf78a Updated descriptions for knowledge graph (#3154)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-11-01 18:57:58 +08:00
b42d24575c Updated an obsolete response (#3152)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-11-01 18:00:15 +08:00
3963aaa23e feat: Add DynamicInputVariable to RetrievalForm #1739 (#3112)
### What problem does this PR solve?

feat: Add DynamicInputVariable to RetrievalForm #1739
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-11-01 13:31:48 +08:00
33e5e5db5b Update gif for readme and add input param to every components (#3145)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
2024-11-01 13:31:34 +08:00
039cde7893 Updated obsolete screenshot. (#3141)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-10-31 19:21:34 +08:00
fa9d76224b Changed version to 0.13.0 (#3140)
### What problem does this PR solve?

Changed version to 0.13.0

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe):
2024-10-31 19:11:09 +08:00
35a451c024 Updated screenshots for Starting an AI chat (#3139)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-10-31 19:10:49 +08:00
1d0a5606b2 minor (#3137)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-10-31 18:37:08 +08:00
4ad031e97d Reworded descriptions for development versions and latest version (#3132)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-31 17:09:52 +08:00
0081d0f05f Moved the Upgrade Manuel out of FAQ (#3131)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-31 16:35:13 +08:00
800c25a6b4 Updated list_documents() (#3126)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-31 14:10:35 +08:00
9aeb07d830 Add test for CI (#3114)
### What problem does this PR solve?

Add test for CI

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-31 14:07:23 +08:00
5590a823c6 Fixed a Docusaurus display issue. (#3125)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-31 13:34:04 +08:00
3fa570f49b fix: remove useless test code (#3122)
### What problem does this PR solve?

remove useless test code

### Type of change

- [X] Refactoring
2024-10-31 11:56:46 +08:00
60053e7b02 Fixed a docusaurus display issue. (#3124)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-31 11:56:30 +08:00
fa1b873280 feat: Delete http_api_reference.md from api folder #1102 (#3121)
### What problem does this PR solve?

feat: Delete http_api_reference.md from  api folder #1102

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-31 11:14:11 +08:00
578f70817e Fixed a docusaurus display issue (#3120)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-31 10:37:13 +08:00
6c6b658ffe add yi-lightning (#3119)
### What problem does this PR solve?

#3111
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-31 10:30:23 +08:00
9a5ff320f3 Manage ragflow-sdk with poetry (#3115)
### What problem does this PR solve?

Manage ragflow-sdk with poetry
### Type of change

- [x] Refactoring
2024-10-30 21:13:59 +08:00
48688afa5e Tried to fix a link issue (#3117)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-30 20:04:45 +08:00
a2b35098c6 Publish RAGFlow's HTTP and Python API references (#3116)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-30 19:40:39 +08:00
4d5354387b docs updates for 0.13 release (#3108)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-10-30 19:29:27 +08:00
c6512e689b Added chunk methods (#3110)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-30 17:59:23 +08:00
b7aff4f560 Differentiated API key names to avoid confusion. (#3107)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-30 16:56:55 +08:00
18dfa2900c Fix bugs in API (#3103)
### What problem does this PR solve?

Fix bugs in API


- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-30 16:15:42 +08:00
86b546f657 Updated parser_config description (#3104)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-30 15:33:36 +08:00
3fb2bc7613 Update README (#3092)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-29 21:05:38 +08:00
f4cb939317 Updated HTTP API reference and Python API reference based on test results (#3090)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-29 19:56:46 +08:00
d868c283c4 feat: The order of the category operator form is messed up after refreshing the page #3088 (#3089)
### What problem does this PR solve?

feat: The order of the category operator form is messed up after
refreshing the page #3088

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-29 19:21:52 +08:00
c7dfb0193b feat: Allow the component id drop-down box to select the answer operator #3085 (#3087)
### What problem does this PR solve?

feat: Allow the component id drop-down box to select the answer operator
#3085

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-29 18:01:26 +08:00
f7705d6bc9 let 'Generate' take user's input as parameter (#3086)
### What problem does this PR solve?

#3085

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-29 17:58:47 +08:00
3ed096fd3f feat: Add InvokeNode #1908 (#3081)
### What problem does this PR solve?

feat: Add InvokeNode #1908

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-10-29 16:39:56 +08:00
2d1fbefdb5 search between multiple indiices for team function (#3079)
### What problem does this PR solve?

#2834 
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-29 13:19:01 +08:00
c5a3146a8c fix: modify the response of metadata in Dify retrieval api (#3076)
### What problem does this PR solve?

Modify the response of metadata in Dify retrieval api

resolve   #2914

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-29 11:06:02 +08:00
1c364e0e5c feat: If the model supplier is not set, click the OK button to jump directly to the page for setting the model supplier. #3068 (#3069)
### What problem does this PR solve?
feat: If the model supplier is not set, click the OK button to jump
directly to the page for setting the model supplier. #3068

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-29 11:05:31 +08:00
9906526a91 Update 'api key' (#3078)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-29 11:04:27 +08:00
7e0148c058 fix local variable ans (#3077)
### What problem does this PR solve?
#3064

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-29 10:42:45 +08:00
f86826b7a0 refactor error message of qwen (#3074)
### What problem does this PR solve?
#3055

### Type of change
- [x] Refactoring
2024-10-29 10:08:08 +08:00
497bc1438a feat: Add component Invoke #2908 (#3067)
### What problem does this PR solve?

feat: Add component Invoke #2908

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-28 18:56:38 +08:00
d133cc043b remove file size check for sdk API (#3066)
### What problem does this PR solve?

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-28 16:13:40 +08:00
e56bd770ea agent template upgrade (#3060)
### What problem does this PR solve?
#3056

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-28 15:49:14 +08:00
07bb2a6fd6 Turn resource to plural form (#3061)
### What problem does this PR solve?

Turn resource to plural form

### Type of change
- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-28 15:06:18 +08:00
396feadd4b feat: Add hint for operators, round to square, input variable, readable operator ID. #3056 (#3057)
### What problem does this PR solve?

feat: Add hint for operators, round to square, input variable, readable
operator ID. #3056

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-28 14:31:19 +08:00
f93f485696 Turn resource to plural form (#3059)
### What problem does this PR solve?

Turn resource to plural form

### Type of change

- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-28 14:15:36 +08:00
a813736194 Bump werkzeug from 3.0.3 to 3.0.6 (#3026)
Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.0.3 to
3.0.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/werkzeug/releases">werkzeug's
releases</a>.</em></p>
<blockquote>
<h2>3.0.6</h2>
<p>This is the Werkzeug 3.0.6 security fix release, which fixes security
issues but does not otherwise change behavior and should not result in
breaking changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/Werkzeug/3.0.6/">https://pypi.org/project/Werkzeug/3.0.6/</a>
Changes: <a
href="https://werkzeug.palletsprojects.com/en/stable/changes/#version-3-0-6">https://werkzeug.palletsprojects.com/en/stable/changes/#version-3-0-6</a></p>
<ul>
<li>Fix how <code>max_form_memory_size</code> is applied when parsing
large non-file fields. <a
href="https://github.com/advisories/GHSA-q34m-jh98-gwm2">GHSA-q34m-jh98-gwm2</a></li>
<li><code>safe_join</code> catches certain paths on Windows that were
not caught by <code>ntpath.isabs</code> on Python &lt; 3.11. <a
href="https://github.com/advisories/GHSA-f9vj-2wh5-fj8j">GHSA-f9vj-2wh5-fj8j</a></li>
</ul>
<h2>3.0.5</h2>
<p>This is the Werkzeug 3.0.5 fix release, which fixes bugs but does not
otherwise change behavior and should not result in breaking changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/Werkzeug/3.0.5/">https://pypi.org/project/Werkzeug/3.0.5/</a>
Changes: <a
href="https://werkzeug.palletsprojects.com/en/stable/changes/#version-3-0-5">https://werkzeug.palletsprojects.com/en/stable/changes/#version-3-0-5</a>
Milestone: <a
href="https://github.com/pallets/werkzeug/milestone/37?closed=1">https://github.com/pallets/werkzeug/milestone/37?closed=1</a></p>
<ul>
<li>The Watchdog reloader ignores file closed no write events. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2945">#2945</a></li>
<li>Logging works with client addresses containing an IPv6 scope. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2952">#2952</a></li>
<li>Ignore invalid authorization parameters. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2955">#2955</a></li>
<li>Improve type annotation fore <code>SharedDataMiddleware</code>. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2958">#2958</a></li>
<li>Compatibility with Python 3.13 when generating debugger pin and the
current UID does not have an associated name. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2957">#2957</a></li>
</ul>
<h2>3.0.4</h2>
<p>This is the Werkzeug 3.0.4 fix release, which fixes bugs but does not
otherwise change behavior and should not result in breaking changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/Werkzeug/3.0.4/">https://pypi.org/project/Werkzeug/3.0.4/</a>
Changes: <a
href="https://werkzeug.palletsprojects.com/en/3.0.x/changes/#version-3-0-4">https://werkzeug.palletsprojects.com/en/3.0.x/changes/#version-3-0-4</a>
Milestone: <a
href="https://github.com/pallets/werkzeug/milestone/36?closed=1">https://github.com/pallets/werkzeug/milestone/36?closed=1</a></p>
<ul>
<li>Restore behavior where parsing
<code>multipart/x-www-form-urlencoded</code> data with
invalid UTF-8 bytes in the body results in no form data parsed rather
than a
413 error. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2930">#2930</a></li>
<li>Improve <code>parse_options_header</code> performance when parsing
unterminated
quoted string values. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2904">#2904</a></li>
<li>Debugger pin auth is synchronized across threads/processes when
tracking
failed entries. <a
href="https://redirect.github.com/pallets/werkzeug/issues/2916">#2916</a></li>
<li>Dev server handles unexpected <code>SSLEOFError</code> due to issue
in Python &lt; 3.13.
<a
href="https://redirect.github.com/pallets/werkzeug/issues/2926">#2926</a></li>
<li>Debugger pin auth works when the URL already contains a query
string.
<a
href="https://redirect.github.com/pallets/werkzeug/issues/2918">#2918</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/werkzeug/blob/main/CHANGES.rst">werkzeug's
changelog</a>.</em></p>
<blockquote>
<h2>Version 3.0.6</h2>
<p>Released 2024-10-25</p>
<ul>
<li>Fix how <code>max_form_memory_size</code> is applied when parsing
large non-file
fields. :ghsa:<code>q34m-jh98-gwm2</code></li>
<li><code>safe_join</code> catches certain paths on Windows that were
not caught by
<code>ntpath.isabs</code> on Python &lt; 3.11.
:ghsa:<code>f9vj-2wh5-fj8j</code></li>
</ul>
<h2>Version 3.0.5</h2>
<p>Released 2024-10-24</p>
<ul>
<li>The Watchdog reloader ignores file closed no write events.
:issue:<code>2945</code></li>
<li>Logging works with client addresses containing an IPv6 scope
:issue:<code>2952</code></li>
<li>Ignore invalid authorization parameters.
:issue:<code>2955</code></li>
<li>Improve type annotation fore <code>SharedDataMiddleware</code>.
:issue:<code>2958</code></li>
<li>Compatibility with Python 3.13 when generating debugger pin and the
current
UID does not have an associated name. :issue:<code>2957</code></li>
</ul>
<h2>Version 3.0.4</h2>
<p>Released 2024-08-21</p>
<ul>
<li>Restore behavior where parsing
<code>multipart/x-www-form-urlencoded</code> data with
invalid UTF-8 bytes in the body results in no form data parsed rather
than a
413 error. :issue:<code>2930</code></li>
<li>Improve <code>parse_options_header</code> performance when parsing
unterminated
quoted string values. :issue:<code>2904</code></li>
<li>Debugger pin auth is synchronized across threads/processes when
tracking
failed entries. :issue:<code>2916</code></li>
<li>Dev server handles unexpected <code>SSLEOFError</code> due to issue
in Python &lt; 3.13.
:issue:<code>2926</code></li>
<li>Debugger pin auth works when the URL already contains a query
string.
:issue:<code>2918</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5eaefc3996"><code>5eaefc3</code></a>
release version 3.0.6</li>
<li><a
href="2767bcb10a"><code>2767bcb</code></a>
Merge commit from fork</li>
<li><a
href="87cc78a25f"><code>87cc78a</code></a>
catch special absolute path on Windows Python &lt; 3.11</li>
<li><a
href="50cfeebcb0"><code>50cfeeb</code></a>
Merge commit from fork</li>
<li><a
href="8760275afb"><code>8760275</code></a>
apply max_form_memory_size another level up in the parser</li>
<li><a
href="8d6a12e2af"><code>8d6a12e</code></a>
start version 3.0.6</li>
<li><a
href="a7b121abc7"><code>a7b121a</code></a>
release version 3.0.5 (<a
href="https://redirect.github.com/pallets/werkzeug/issues/2961">#2961</a>)</li>
<li><a
href="9caf72ac06"><code>9caf72a</code></a>
release version 3.0.5</li>
<li><a
href="e28a2451e9"><code>e28a245</code></a>
catch OSError from getpass.getuser (<a
href="https://redirect.github.com/pallets/werkzeug/issues/2960">#2960</a>)</li>
<li><a
href="e6b4cce97e"><code>e6b4cce</code></a>
catch OSError from getpass.getuser</li>
<li>Additional commits viewable in <a
href="https://github.com/pallets/werkzeug/compare/3.0.3...3.0.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=werkzeug&package-manager=pip&previous-version=3.0.3&new-version=3.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-28 11:58:25 +08:00
322bafdf2a fix baidufanyi param error (#3053)
### What problem does this PR solve?

#3052

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-28 11:05:32 +08:00
8257eeb3f2 add model moonshot-v1-auto (#3051)
### What problem does this PR solve?

#3048

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-28 10:37:22 +08:00
00810525d6 Minor editorial updates to the HTTP API reference (#3027)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-27 08:00:51 +08:00
391b950be6 Fix non-null violation when inviting people to team (#3015)
### What problem does this PR solve?

Not sure why MySQL is inserting empty string in this case, but when I
use postgres I got `null value in column "invited_by" of relation
"user_tenant" violates not-null constraint`

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2024-10-25 18:39:09 +08:00
d78f215caa Final touches to HTTP and Python API references (#3019)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-25 17:11:58 +08:00
9457d20ef1 make gemini robust (#3012)
### What problem does this PR solve?

#3003

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-25 10:50:44 +08:00
648f8e81d1 Fix issues in API (#3008)
### What problem does this PR solve?

Fix issues in API

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-24 20:10:47 +08:00
161c7a231b Fix some issues in API and test (#3001)
### What problem does this PR solve?

Fix some issues in API and test

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-24 20:05:21 +08:00
e997b42504 DRAFT: miscellaneous updates to HTTP API Reference (#3005)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-10-24 20:04:50 +08:00
524699da7d Miscellaneous updates to HTTP and PYthon APIs (#3000)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-24 16:14:07 +08:00
765a114be7 minor (#2998)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change


- [x] Documentation Update
2024-10-24 11:02:09 +08:00
c86afff447 feat: Limit the maximum value of auto keywords to 30 #2687 (#2991)
### What problem does this PR solve?

feat: Limit the maximum value of auto keywords to 30 #2687

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-24 09:35:34 +08:00
b73fe0cc3c Integrating RAGFlow API as a Plugin into ChatGPT-on-WeChat (#2988)
### What problem does this PR solve?

This PR introduces the `ragflow_chat` plugin for the ChatGPT-on-WeChat
project, extending its functionality by integrating Retrieval-Augmented
Generation (RAG) capabilities. It allows users to have more contextually
relevant conversations by retrieving information from external knowledge
sources (via the RAGFlow API) and incorporating it into their chat
interactions.

The primary goal of this PR is to enable seamless communication between
ChatGPT-on-WeChat and the RAGFlow server, improving response accuracy by
embedding knowledge-based data into conversational flows. This is
particularly useful for users who need more complex, data-driven
responses.

This PR adds a new plugin that enhances ChatGPT-on-WeChat with Ragflow
capabilities, allowing for a more enriched conversational experience
driven by external knowledge.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-24 09:35:11 +08:00
2a614e0e23 Remove defaults to 'None' (#2996)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-23 22:58:37 +08:00
50b425cf89 Test Cases (#2993)
### What problem does this PR solve?

Test Cases

### Type of change

- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-23 22:58:27 +08:00
2174c350be Updated HTTP API Reference (document, chat assistant, session, chat) (#2994)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-23 20:07:47 +08:00
7f81fc8f9b refactor auto keywords and auto question (#2990)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-10-23 17:00:56 +08:00
f090075cb2 allowing docker container to access service on host (#2895)
### What problem does this PR solve?

1. services running (e.g., ollama) running on the host could not be
accessed from docker containers

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Zhichang Yu <yuzhichang@gmail.com>
2024-10-23 16:43:21 +08:00
ec6d942d83 feat: Added auto_keywords and auto_questions fields to the parsing configuration page #2687 (#2987)
### What problem does this PR solve?

feat: Added auto_keywords and auto_questions fields to the parsing
configuration page #2687

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-23 15:45:03 +08:00
8714754afc Fix some issues in API (#2982)
### What problem does this PR solve?

Fix some issues in API

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-23 12:02:18 +08:00
43b959fe58 minor (#2984)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-23 11:00:35 +08:00
320e8f6553 fix generate string join issue (#2983)
### What problem does this PR solve?

#2921

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-23 10:54:04 +08:00
89d5b2414e fix SILICONFLOW rerank error (#2980)
### What problem does this PR solve?

#2977

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-23 10:12:39 +08:00
91ea559f9e DRAFT: Updated python and http api references (#2973)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-10-22 17:10:23 +08:00
445dce4363 [Bug]: unnecessary auto-increment calculations in the tokens statistics of the chat model (#2969)
### What problem does this PR solve?

the details is shown in
https://github.com/infiniflow/ragflow/issues/2968

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-22 16:26:04 +08:00
1fce6caf80 make titles in markdown not be splited with following content (#2971)
### What problem does this PR solve?

#2970 
### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-10-22 15:25:23 +08:00
adb0a93d95 add component invoke (#2967)
### What problem does this PR solve?

#2908

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-22 14:16:44 +08:00
226bdd6e99 add auto keywords and auto-question (#2965)
### What problem does this PR solve?

#2687

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-22 13:12:49 +08:00
5aa9d7787e [Bug]: When use OpenAI chat model , raise ERROR: 'CompletionUsage' object has no attribute 'get' #2948 (#2949)
[Bug]: When use OpenAI chat model , raise ERROR: 'CompletionUsage'
object has no attribute 'get' #2948

### What problem does this PR solve?

the detail of this PR is shown at
https://github.com/infiniflow/ragflow/issues/2948

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-22 11:40:05 +08:00
b2524eec49 fix sequence2txt error and usage total token issue (#2961)
### What problem does this PR solve?

#1363

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-22 11:38:37 +08:00
6a4858a7ee Fix thumbnail_img NoneType error (#2941)
### What problem does this PR solve?

fix thumbnail_img NoneType error

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-22 09:21:05 +08:00
1a623df849 DRAFT: Miscellaneous updates to HTTP API reference (#2923)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-21 19:50:45 +08:00
bfc07fe4f9 bigger resolution for OCR (#2919)
### What problem does this PR solve?



### Type of change

- [x] Performance Improvement
2024-10-21 16:25:42 +08:00
3e702aa4ac add package crawl4ai (#2918)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-21 15:07:45 +08:00
2ced25c676 fix thumbnail issue (#2917)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-21 14:33:26 +08:00
1935c3be1a Fix some issues in API (#2902)
### What problem does this PR solve?

Fix some issues in API

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-21 14:29:06 +08:00
609cfa7b5f feat: Replace crawler icon #2915 (#2916)
### What problem does this PR solve?

feat: Replace crawler icon #2915

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-21 14:28:30 +08:00
ac26d09a59 Feature/feat1017 (#2872)
### What problem does this PR solve?

1. fix: mid map show error in knowledge graph, juse because
```@antv/g6```version changed
2. feat: concurrent threads configuration support in graph extractor
3. fix: used tokens update failed for tenant
4. feat: timeout configuration support for llm
5. fix: regex error in graph extractor
6. feat: qwen rerank(```gte-rerank```) support
7. fix: timeout deal in knowledge graph index process. Now chat by
stream output, also, it is configuratable.
8. feat: ```qwen-long``` model configuration

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: chongchuanbing <chongchuanbing@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-21 12:11:08 +08:00
4bdf3fd48e Add agent component for web crawler (#2878)
### What problem does this PR solve?

Add agent component for  web crawler

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-21 11:38:41 +08:00
c1d0473f49 add zhipu glm-4-9b (#2912)
### What problem does this PR solve?

#2910

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-21 10:30:35 +08:00
e5f7733b31 Resolves #2905 openai compatible model provider add llama.cpp rerank support (#2906)
### What problem does this PR solve?
Resolve #2905 



due to the in-consistent of token size, I make it safe to limit 500 in
code, since there is no config param to control

my llama.cpp run set -ub to 1024:

${llama_path}/bin/llama-server --host 0.0.0.0 --port 9901 -ub 1024 -ngl
99 -m $gguf_file --reranking "$@"





### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Here is my test Ragflow use llama.cpp

```
lot update_slots: id  0 | task 458 | prompt done, n_past = 416, n_tokens = 416
slot      release: id  0 | task 458 | stop processing: n_past = 416, truncated = 0
slot launch_slot_: id  0 | task 459 | processing task
slot update_slots: id  0 | task 459 | tokenizing prompt, len = 2
slot update_slots: id  0 | task 459 | prompt tokenized, n_ctx_slot = 8192, n_keep = 0, n_prompt_tokens = 111
slot update_slots: id  0 | task 459 | kv cache rm [0, end)
slot update_slots: id  0 | task 459 | prompt processing progress, n_past = 111, n_tokens = 111, progress = 1.000000
slot update_slots: id  0 | task 459 | prompt done, n_past = 111, n_tokens = 111
slot      release: id  0 | task 459 | stop processing: n_past = 111, truncated = 0
srv  update_slots: all slots are idle
request: POST /rerank 172.23.0.4 200

```
2024-10-21 10:06:29 +08:00
5aec1e3e17 DRAFT: Miscellaneous updates to HTTP API. Tried to finish off Python API ref… (#2909)
…erence but failed.

### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-21 09:47:59 +08:00
1d6bcf5aa2 add nginx path for sdk handlers (#2899) (#2900)
### What problem does this PR solve?

add the nginx path `/api` for sdk handlers 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-21 09:47:45 +08:00
1e6d44d6ef DRAFT: Miscellaneous proofedits on Python APIs (#2903)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-19 19:46:13 +08:00
cec208051f DRAFT: Updated chunk APIs (#2901)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-10-18 20:56:33 +08:00
526fcbbfde fix: Fixed the issue of error reporting when uploading files in the chat box #2897 (#2898)
### What problem does this PR solve?

fix: Fixed the issue of error reporting when uploading files in the chat
box #2897

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-18 17:21:12 +08:00
c760f058df add owner check for team work (#2892)
### What problem does this PR solve?

#2834

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-18 13:48:57 +08:00
8fdfa0f669 feat: Use Badge.Ribbon to distinguish the teams to which the knowledge base belongs #2846 (#2891)
### What problem does this PR solve?

feat: Use Badge.Ribbon to distinguish the teams to which the knowledge
base belongs #2846

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-18 12:50:06 +08:00
ceecac69e9 Delete useless files (#2889)
### What problem does this PR solve?

Delete useless files

### Type of change


- [x] Other (please describe):
Delete useless files

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-18 11:30:40 +08:00
e0c0bdeb0a add team tag to kb (#2890)
### What problem does this PR solve?
#2834

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-18 11:30:19 +08:00
cf3106040a feat: Bind data to TenantTable #2846 (#2883)
### What problem does this PR solve?

feat: Bind data to TenantTable #2846
feat: Add TenantTable

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-18 09:21:01 +08:00
791afbba15 Miscellaneous minor updates (#2885)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-17 19:52:35 +08:00
8358245f64 Draft: Updated file management-related APIs (#2882)
### What problem does this PR solve?

Updated file management-related APIs

### Type of change

- [x] Documentation Update
2024-10-17 18:19:17 +08:00
396bb4b688 Fixed docker build (#2881)
### What problem does this PR solve?

Fixed docker build

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-17 16:34:21 +08:00
167b4af52b feat: Load markdown file with "asset/source" #1739 (#2880)
### What problem does this PR solve?

feat: Load markdown file with "asset/source" #17339

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-17 16:03:13 +08:00
bedb05012d feat: Configure the root directory alias #1739 (#2875)
### What problem does this PR solve?

feat: Configure the root directory alias #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-17 11:36:01 +08:00
6a60e26020 update dashscope (#2871)
### What problem does this PR solve?
#2857
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-17 09:52:31 +08:00
6496055e23 Updated session APIs (#2868)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-10-16 20:38:19 +08:00
dab92ac1e8 Refactor Chunk API (#2855)
### What problem does this PR solve?

Refactor Chunk API
#2846
### Type of change


- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-16 18:41:24 +08:00
b9fa00f341 add API for tenant function (#2866)
### What problem does this PR solve?

feat: API access key management
https://github.com/infiniflow/ragflow/issues/2846
feat: Render markdown file with remark-loader
https://github.com/infiniflow/ragflow/issues/2846

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-16 16:10:24 +08:00
e5d3ab0332 feat: API access key management #2846 (#2865)
### What problem does this PR solve?

feat: API access key management #2846
feat: Render markdown file with remark-loader #2846

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-16 15:57:39 +08:00
4991107822 Fix keys of Xinference deployed models, especially has the same model name with public hosted models. (#2832)
### What problem does this PR solve?

Fix keys of Xinference deployed models, especially has the same model
name with public hosted models.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: 0000sir <0000sir@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-16 10:21:08 +08:00
51ecda0ff5 refactor (#2858)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-10-16 10:17:05 +08:00
6850fd69c6 Enhance email validation: Allow top-level domains with 5 letters (#2856)
### What problem does this PR solve?

Currently singing up to ragflow using a mail-adress with associated
top-level domains that have more than 4 chars will fail due to a regex
validation that enforces just this.

In our use case, we'd like to use e-mail addresses with `.swiss`
top-level domains, which is a valid TLD associated with the country
switzerland in the IANA root database.

This change makes the validation accept 5-letter TLDs.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Other (please describe): Making validation for lenient, accepting
more valid input.
2024-10-16 09:34:45 +08:00
e1e5711680 Feat:Compatible with Dify's External Knowledge API (#2848)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._
Fixes #2731 
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-15 17:47:24 +08:00
4463128436 add rm token (#2850)
### What problem does this PR solve?

#2846

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-15 16:48:38 +08:00
c8783672d7 refactor api util (#2849)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-10-15 16:11:26 +08:00
ce495e4e3e refine API token application (#2847)
### What problem does this PR solve?

#2846

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-15 15:47:40 +08:00
fcabdf7745 feat: Generate operator names in an auto-incremental manner #1739 (#2844)
### What problem does this PR solve?

feat: Generate operator names in an auto-incremental manner #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-15 15:36:09 +08:00
b540d41cdc let presentation do raptor (#2838)
### What problem does this PR solve?

#2837

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-15 10:11:09 +08:00
260d694bbc Updated chat APIs (#2831)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2024-10-14 20:48:23 +08:00
6329427ad5 Refactor Document API (#2833)
### What problem does this PR solve?

Refactor Document API

### Type of change


- [x] Refactoring

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-14 20:03:33 +08:00
df223eddf3 feat: Fix translation issue of message_history_window_size #1739 (#2828)
### What problem does this PR solve?

feat: Fix translation issue of message_history_window_size #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-14 15:30:20 +08:00
85b359556e feat: Add message_history_window_size to CategorizeForm #1739 (#2826)
### What problem does this PR solve?

feat: Add message_history_window_size to CategorizeForm #1739
### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-14 15:18:45 +08:00
b164116277 refine token similarity (#2824)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-10-14 13:33:18 +08:00
8e5efcc47f Updated dataset APIs (#2820)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-10-12 20:07:21 +08:00
6eed115723 Refactor API for document and session (#2819)
### What problem does this PR solve?

Refactor API for document and session.

### Type of change


- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-12 19:35:19 +08:00
7d80fc474c refine components retrieval and rewrite (#2818)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-10-12 18:47:25 +08:00
a20b82092f Refactor Chat API (#2804)
### What problem does this PR solve?

Refactor Chat API

### Type of change

- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-12 13:48:43 +08:00
2a86472b88 fix chat and thumbnail bug (#2803)
### What problem does this PR solve?

1. fix white screen issue when chat response
2. thumbnail bug when document not support

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: chongchuanbing <chongchuanbing@gmail.com>
2024-10-11 16:10:27 +08:00
190eea7097 trival (#2808)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-11 15:33:38 +08:00
2d1c83da59 fix LIGHTEN issue (#2806)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-11 15:01:27 +08:00
3f065c75da support chat model in huggingface (#2802)
### What problem does this PR solve?

#2794

### Type of change
- [x] New Feature (non-breaking change which adds functionality)
2024-10-11 14:45:48 +08:00
1bae479b37 Fixed broken links. (#2805)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-10-11 14:34:31 +08:00
5e7c1fb23a reduce rerank batch size (#2801)
### What problem does this PR solve?

### Type of change


- [x] Performance Improvement
2024-10-11 11:29:19 +08:00
bae30e5cc4 fix: document preview (#2795)
(cherry picked from commit 8d11a070b2fc88285a7cff1ab85ebefee84b6c64)

### What problem does this PR solve?

fix document preview error in file manager.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: chongchuanbing <chongchuanbing@gmail.com>
2024-10-11 11:26:59 +08:00
18f80743eb support api-version and change default-model in adding azure-openai and openai (#2799)
### What problem does this PR solve?
#2701 #2712 #2749

### Type of change
-[x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-11 11:26:42 +08:00
bfaef2cca6 feat: Arrange the form of generate, categorize, switch, retrieval operators vertically #1739 (#2800)
### What problem does this PR solve?

feat: Arrange the form of generate, categorize, switch, retrieval
operators vertically #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-11 11:06:14 +08:00
cbd7cd7c4d Refactor Dataset API (#2783)
### What problem does this PR solve?

Refactor Dataset API

### Type of change

- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-10-11 09:55:27 +08:00
a2f9c03a95 fix: Change document status with @tanstack/react-query #13306 (#2788)
### What problem does this PR solve?

fix: Change document status with @tanstack/react-query #13306

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-11 08:45:10 +08:00
2c56d274d8 Updated instructions on downloading RAGFlow Slim and RAGFlow all-in-one. (#2785)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-10-10 19:24:54 +08:00
7742f67481 refine agent (#2787)
### What problem does this PR solve?



### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [x] Performance Improvement
- [ ] Other (please describe):
2024-10-10 17:07:36 +08:00
6af9d4e5f9 Refactor README on different docker version. (#2775)
### What problem does this PR solve?

1. Use two env files for slim and full docker image.
2. Update README

### Type of change

- [x] Documentation Update
- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-10-10 15:30:32 +08:00
51efecf4b5 trival (#2779)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-10 11:05:03 +08:00
9dfcae2b5d Fix error commands (#2778)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-10 10:38:57 +08:00
66172cef3e fix: torch dependency start error (#2777)
### What problem does this PR solve?

when use slim image, remove ```torch``` denpendency.

### Type of change

- [✓] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: chongchuanbing <chongchuanbing@gmail.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-10 10:06:03 +08:00
29f022c91c fix bedrock issue (#2776)
### What problem does this PR solve?

#2722

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-10 09:13:35 +08:00
485bfd6c08 fix: Large document thumbnail display failed (#2763)
### What problem does this PR solve?

In MySQL, when the thumbnail base64 of a document is relatively large,
the display of the document's thumbnail fails.
Now, I put the document thumbnail into MiniIO storage.

### Type of change

- [✓] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: chongchuanbing <chongchuanbing@gmail.com>
2024-10-10 09:09:29 +08:00
f7a73c5149 Fix README and some comments (#2774)
### What problem does this PR solve?

1. Fix typo
2. Update comments.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-09 23:30:00 +08:00
5d966b1120 Fix README description (#2773)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-09 23:03:18 +08:00
ce79144e75 Use slim image as the default (#2772)
### What problem does this PR solve?

Use the slim docker image as the default.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-09 22:51:47 +08:00
d8566f0ddf HTTP API documents, part1 (#2713)
### What problem does this PR solve?

1. dataset: create/delete/list/get/update
2. files in dataset: upload/download/list/delete/get_info

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-10-09 20:26:51 +08:00
e904c134e7 feat: Add a note node to the agent canvas #2767 (#2768)
### What problem does this PR solve?

feat: Add a note node to the agent canvas #2767

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-09 19:39:04 +08:00
7fc3bb3241 Docs:fix user guide links (#2761)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-09 19:38:10 +08:00
20e63f8ec4 Fix docx images (#2756)
### What problem does this PR solve?

#2755 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-09 19:37:32 +08:00
2df15742fc fix xinference add rerank model bug (#2758)
### What problem does this PR solve?

Fix xinference add rerank model bug,
https://github.com/infiniflow/ragflow/issues/2294#issue-2510788135

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-09 19:37:11 +08:00
8f815a6c1e Fix component exesql (#2754)
### What problem does this PR solve?

#2700 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-09 17:53:36 +08:00
8f4bd10b19 Initial draft of Python APIs (#2719)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-10-09 15:30:22 +08:00
511d272d0d feat: The same query conditions on the search page should not request the interface every time the mind map drawer is opened. #2759 (#2760)
### What problem does this PR solve?

feat: The same query conditions on the search page should not request
the interface every time the mind map drawer is opened. #2759

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-09 15:28:28 +08:00
7f44cf543a move import positions (#2753)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-10-09 10:34:58 +08:00
16472eb3ea solve knowledgegraph issue when calling gemini model (#2738)
### What problem does this PR solve?
#2720

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-08 18:27:04 +08:00
d92acdcf1d Update azure_sas_conn.py - fixing container_url typo (#2740)
### What problem does this PR solve?

Fixes #2739

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-08 18:26:30 +08:00
2e33ed3ba0 Modified download_deps.py (#2747)
### What problem does this PR solve?

Modified download_deps.py

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-10-08 17:40:06 +08:00
04ff9cda7c expand rerank range (#2746)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-10-08 16:34:33 +08:00
5cc9981a4d Fix LIGHTEN. Close #2723 (#2744)
### What problem does this PR solve?

Fix LIGHTEN
#2726 
#2723

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-08 15:58:14 +08:00
5845b2b137 feat: Add component TuShare #1739 (#2745)
### What problem does this PR solve?

feat: Add component  TuShare  #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-08 15:35:30 +08:00
b3b54680e7 Add query parts to lamp (#2736)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-10-08 12:53:04 +08:00
a3ab5ba9ac support sequence2txt and tts model in Xinference (#2696)
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-10-08 10:43:18 +08:00
c552a02e7f chore: update operators.py (#2724)
### What problem does this PR solve?
substract -> subtract
### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-10-08 10:34:52 +08:00
a005be7c74 fix re.escape problem (#2735)
### What problem does this PR solve?

#2716

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-08 10:07:03 +08:00
6f7fcdc897 remove redeclared get_json_result func (#2675)
### What problem does this PR solve?

Redeclared 'get_json_result' defined above without usage
line 99 VS line 218

### Type of change

- [x] Other (please describe): remove redeclared func
2024-10-05 16:47:47 +08:00
34761fa4ca Fix/bedrock issues (#2718)
### What problem does this PR solve?

Adding a Bedrock API key for Claude Sonnet was broken. I find the issue
came up when trying to test the LLM configuration, the system is a
required parameter in boto3.

As well, there were problems in Bedrock implementation for embeddings
when trying to encode queries.

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)
2024-10-05 16:44:50 +08:00
abe9995a7c build multi-arch image (#2710)
### What problem does this PR solve?
build multi-arch image

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-10-03 21:00:26 +08:00
7f2ee3bbe9 docs: Migrate README to Compose V2 syntax (#2711)
### What problem does this PR solve?

This PR updates README to reflect the migration from Compose V1
(`docker-compose`) to Compose V2 (`docker compose`):

### Type of change

- [x] Documentation Update

### Source

The migration details and differences between Compose V1 and Compose V2
are based on the official Docker documentation:
[Docker Docs: Migrate to Compose
V2](https://docs.docker.com/compose/releases/migrate/#what-are-the-differences-between-compose-v1-and-compose-v2)
2024-10-03 15:31:04 +08:00
a1ffc7fa2c Fix poetry cache (#2709)
### What problem does this PR solve?

Fix poetry cache

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-10-02 21:15:30 +08:00
70c6b5a7f9 Fix Dockerfile.slim (#2708)
### What problem does this PR solve?
Fix Dockerfile.slim

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-10-02 20:02:53 +08:00
1b80a693ba Updated Build Docker Image (#2706)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-10-02 19:43:22 +08:00
e46a4d1875 Fix Dockerfile for arm64 (#2705)
### What problem does this PR solve?

Fix Dockerfile for arm64

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

---------

Co-authored-by: Ubuntu <ubuntu@arm-test.us-central1-f.c.ragflow-01.internal>
2024-10-02 19:41:56 +08:00
5f4d2dc4fe Updated Dockefile to use cache (#2703)
### What problem does this PR solve?

Updated Dockefile to use cache

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-10-01 17:41:38 +08:00
62202b7eff fix: Fixed the issue where no error message was displayed when uploading a file that was too large #2258 (#2697)
### What problem does this PR solve?

fix: Fixed the issue where no error message was displayed when uploading
a file that was too large #2258

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-10-01 16:37:46 +08:00
1518824b0c Updated Dockerfile (#2695)
### What problem does this PR solve?

Updated Dockerfile

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-30 18:13:06 +08:00
0a7654c747 fix error in exception (#2694)
### What problem does this PR solve?
#2670

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-30 17:54:27 +08:00
d6db805885 Refactoring entity_resolution (#2692)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-09-30 17:18:09 +08:00
570ad420a8 remove unused import (#2679)
### What problem does this PR solve?

### Type of change

- [x] Refactoring
2024-09-30 16:59:39 +08:00
ae5a877ed4 Simplify the usage of dict (#2681)
### What problem does this PR solve?
Simplify the usage of dictionaries

### Type of change

- [x] Refactoring

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-30 16:54:25 +08:00
9945988e44 format mind_map_extractor code (#2686)
### What problem does this PR solve?

format mind_map_extractor code

### Type of change

- [x] Refactoring
2024-09-30 16:29:15 +08:00
79b8210498 refine readme (#2689)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2024-09-30 16:21:56 +08:00
c80d311474 fix tests.yml (#2688)
### What problem does this PR solve?

fix tests.yml

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe):
CI
2024-09-30 16:05:54 +08:00
64429578da added tests.yml (#2685)
### What problem does this PR solve?

added tests.yml

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [x] Other (please describe): CI
2024-09-30 14:58:34 +08:00
92a4a095c9 fix: Fixed an issue where quotes in messages could not be displayed #2677 (#2683)
### What problem does this PR solve?

fix: Fixed an issue where quotes in messages could not be displayed
#2677

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-30 12:40:12 +08:00
2368d738ab fix: Search page search results are cleared after output #2677 (#2678)
### What problem does this PR solve?

fix: Search page search results are cleared after output #2677

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-30 11:00:03 +08:00
833e3a08cd update poetry lock (#2676)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-30 10:59:47 +08:00
7a73fec2e5 upgrade opencv-python-headless (#2674)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-30 09:28:38 +08:00
2f8e0e66ef change opencv version (#2673)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-30 09:13:11 +08:00
5b4b252895 Fixed huggingface url (#2667)
### What problem does this PR solve?
Fixed huggingface url. Close #2665

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 20:38:11 +08:00
9081150c2c Translated Korean README (#2666)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-29 20:03:25 +08:00
cb295ec106 Translated Japanese README (#2664)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-29 19:27:48 +08:00
4f5210352c added back oc9 (#2663)
### What problem does this PR solve?

added back oc9

### Type of change

- [x] Refactoring
2024-09-29 18:32:48 +08:00
f98ec9034f Fix docker file bugs (#2662)
### What problem does this PR solve?

Fix docker file bugs

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-29 18:24:24 +08:00
4b8ecba32b Updated CN readme (#2661)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-29 17:27:15 +08:00
892166ec24 document preparation for release (#2660)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-09-29 16:29:02 +08:00
a411330b09 Add build image and launch from source in README (#2658)
### What problem does this PR solve?

Move the build image and launch from source back to README.

### Type of change

- [x] Documentation Update

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-09-29 16:28:07 +08:00
5a8ae4a289 fix: Filter the timePeriod options based on the userType parameter #1739 (#2657)
### What problem does this PR solve?

fix: Filter the timePeriod options based on the userType parameter #1739

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-29 15:40:20 +08:00
3f16377412 change url of local llm deploy guide (#2659)
### What problem does this PR solve?


### Type of change

- [x] Other (please describe): I made a mistake with an URL and now I
need to change it
2024-09-29 15:39:05 +08:00
d3b37b0b70 fix: Fixed the issue where the error message was not displayed when uploading a file that was too large #1782 (#2654)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-29 15:22:05 +08:00
01db00b587 Updated component description (#2651)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-29 14:53:52 +08:00
25f07e8e29 fix template error (#2653)
### What problem does this PR solve?

#2478

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-29 14:47:06 +08:00
daa65199e8 trival (#2650)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 13:20:02 +08:00
fc867cb959 rename get_txt to get_text (#2649)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 12:47:09 +08:00
fb694143ee refine general purpose chat bot (#2648)
### What problem does this PR solve?

#2478

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-29 12:20:44 +08:00
a8280d9fd2 Add doc for dev image (#2641)
Add doc for dev image

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-09-29 10:51:46 +08:00
aea553c3a8 Add get_txt function (#2639)
### What problem does this PR solve?

Add get_txt function to reduce duplicate code

### Type of change

- [x] Refactoring

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-29 10:29:56 +08:00
57237634f1 Refactoring large integers to improve readability (#2636)
### What problem does this PR solve?

Refactoring large integers

### Type of change

- [x] Refactoring
2024-09-29 10:17:42 +08:00
604061c4a5 Fix mutable default argument (#2635)
### What problem does this PR solve?

The default value of Python function parameters cannot be mutable.
Modifying this parameter inside the function will permanently change the
default value

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 10:16:00 +08:00
c103dd2746 change chunk.status to chunk.available (#2646)
### What problem does this PR solve?

#1102

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-29 10:13:07 +08:00
e82e8fde13 Fix logger error (#2643)
### What problem does this PR solve?

Fix logger error: AttributeError: 'Logger' object has no attribute
'basicConfig'

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 09:49:59 +08:00
a44ed9626a handle nits in task_executor (#2637)
### What problem does this PR solve?

- fix typo
- fix string format
- format import

### Type of change

- [x] Refactoring
2024-09-29 09:49:45 +08:00
ff9c11c970 fix: Fixed the issue where the conversation list was not displayed on the conversation page #2625 (#2638)
### What problem does this PR solve?

fix: Fixed the issue where the conversation list was not displayed on
the conversation page #2625

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-29 09:43:23 +08:00
674d342761 refine get_input (#2630)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-27 20:20:36 +08:00
a246e5644b feat: Add top_n to DeepLForm #1739 (#2629)
### What problem does this PR solve?

feat: Add top_n to DeepLForm #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-27 19:22:33 +08:00
96f56a3c43 add huggingface model (#2624)
### What problem does this PR solve?

#2469

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-27 19:15:38 +08:00
1b2f66fc11 Added doc on dev-slim (#2627)
Added doc on dev-slim

### Type of change

- [x] Documentation Update
- [x] Refactoring

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-27 19:15:27 +08:00
ca2de896c7 fix: Fixed an issue where the first message would be displayed when sending the second message #2625 (#2626)
### What problem does this PR solve?

fix: Fixed an issue where the first message would be displayed when
sending the second message #2625

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-27 18:20:19 +08:00
34abcf7704 style: fix typo and format code (#2618)
### What problem does this PR solve?

- Fix typo
- Remove unused import
- Format code

### Type of change

- [x] Other (please describe): typo and format
2024-09-27 13:17:25 +08:00
4c0b79c4f6 remove repeat func (#2619)
### What problem does this PR solve?

- remove repeat func

### Type of change

- [x] Other (please describe): remove repeat func
2024-09-27 13:15:26 +08:00
e11a74eed5 Update Yichat base_url (#2620)
### What problem does this PR solve?

Update Yichat base_url

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-09-27 12:55:58 +08:00
297b2d0ac9 force eml file to be parsed by EMAIL (#2615)
### What problem does this PR solve?
#2613
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-27 10:29:30 +08:00
b16f16e19e Bug fix - email processing could be run now from API (#2613)
### What problem does this PR solve?

If .eml file is uploaded, there is always General method chosen for
email processing, even if parsing_method is defined in the request. This
change solves this issue.

### Type of change

- [X] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Adam Kobus <adam.kobus@gitlab.eleader.biz>
2024-09-27 10:24:46 +08:00
35598c04ce fix generate bug (#2614)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-27 10:22:13 +08:00
09d1f7f333 Support agent for aibot (#2609)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-26 18:06:56 +08:00
240450ea52 Remove WenCai imageurl and update investment_advisor prompt (#2606)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-09-26 17:27:53 +08:00
1de3032650 fix AzureOpenAI issue` (#2608)
### What problem does this PR solve?

#1599

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-26 17:25:16 +08:00
41548bf019 Added two developer guide and removed from README ' builder docker image' and 'launch service from source' (#2590)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-09-26 16:15:57 +08:00
b68d349bd6 Fix: renrank_model and pdf_parser bugs | Update: session API (#2601)
### What problem does this PR solve?

Fix: renrank_model and pdf_parser bugs | Update: session API
#2575
#2559
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] Refactoring

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-09-26 16:05:25 +08:00
f6bfe4d970 feat: Add component Concentrator #1739 (#2604)
### What problem does this PR solve?

feat: Add component Concentrator #1739
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-26 14:47:28 +08:00
cb2ae708f3 Fix soft link. Close #2587 (#2602)
Fix soft link

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-26 14:33:38 +08:00
d7f26786d4 Update dsl_examples and Fix component concentrator (#2597)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-26 11:58:50 +08:00
b05fab14f7 Add component Concentrator (#2586)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-25 18:44:31 +08:00
e6da0c7c7b deprecate init a super user (#2589)
### What problem does this PR solve?
#2295

### Type of change

- [x] Refactoring
2024-09-25 18:30:27 +08:00
ef89e3ebea remove onnx copy command from dockerfile (#2584)
### What problem does this PR solve?

#2564

### Type of change

- [x] Refactoring
2024-09-25 17:14:59 +08:00
8ede1c7bf5 trival (#2582)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-25 16:26:44 +08:00
6363d58e98 Add template investment_advisor (#2580)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-25 16:22:06 +08:00
c262011393 revert error in Dockerfile (#2581)
### What problem does this PR solve?
#2295

### Type of change


- [x] Refactoring
2024-09-25 16:10:29 +08:00
dda1367ab2 make it lighten (#2577)
### What problem does this PR solve?

#2295

### Type of change

- [x] Refactoring
2024-09-25 13:38:40 +08:00
e4c9cf2264 feat: If the model is not set, a pop-up window will remind the user #2295 (#2574)
### What problem does this PR solve?

feat: If the model is not set, a pop-up window will remind the user
#2295

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-25 11:16:00 +08:00
e3b3ec3f79 multi-arch-build (#2571)
### What problem does this PR solve?

Build multi-arch docker image `infiniflow/ragflow:poetry` on
`linux/amd64` and `linux/arm64`.

### Type of change

- [x] Refactoring
2024-09-25 10:37:20 +08:00
08d5637770 Fix tokenizer bug (#2573)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-25 10:30:49 +08:00
7bb28ca2bd add lighten control (#2567)
### What problem does this PR solve?

#2295

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-24 19:22:01 +08:00
9251fb39af feat: Delete Model Provider #2376 (#2565)
### What problem does this PR solve?

feat: Delete Model Provider #2376

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-24 19:10:06 +08:00
91dbce30bd feat: Add component Jin10 #1739 (#2563)
### What problem does this PR solve?

feat: Add component Jin10  #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-24 18:54:09 +08:00
949a999478 feat: Add component YahooFinance #1739 (#2561)
### What problem does this PR solve?

feat: Add component YahooFinance #1739

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-24 16:46:41 +08:00
d40041cc82 refine multi-turn chat in agent (#2560)
### What problem does this PR solve?

#2484

### Type of change

- [x] Performance Improvement
- [ ] Other (please describe):
2024-09-24 16:20:19 +08:00
832c90ac3e fix: Web code build fails on ARM machines #2554 (#2557)
### What problem does this PR solve?

fix: Web code build fails on ARM machines #2554

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-24 15:27:26 +08:00
7b3099b1a1 add an API of delete llm supplier (#2556)
### What problem does this PR solve?

#1853

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-24 15:24:15 +08:00
4681638974 Streaming output is supported, dialogue share is not (#2555)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-24 15:14:44 +08:00
ecf441c830 refine using rerank model (#2553)
### What problem does this PR solve?

#2552

### Type of change

- [x] Performance Improvement
2024-09-24 12:38:18 +08:00
d9c2a128a5 SparkTTS (#2535)
### What problem does this PR solve?

SparkTTS

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-09-24 12:15:12 +08:00
38e3475714 refine markdown prompt (#2551)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-09-24 12:04:16 +08:00
90644246d6 Updated README on debugging web and python (#2544)
### What problem does this PR solve?

Updated README on debugging web and python

### Type of change

- [x] Documentation Update
2024-09-24 11:46:03 +08:00
100c60017f fix component rewrite bug (#2549)
### What problem does this PR solve?

#2545

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-24 11:31:42 +08:00
51dd6d1f90 fix: Initial language is English, but the UI is in Chinese #2514 (#2541)
### What problem does this PR solve?

fix: Initial language is English, but the UI is in Chinese #2514

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-23 16:28:27 +08:00
521ea6afcb feat: Refine reteival of multi-turn conversation #2362 (#2539)
### What problem does this PR solve?

feat: Refine reteival of multi-turn conversation #2362

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-23 15:26:11 +08:00
dd019e7ba1 feat: Configurable for excel, html table or row based text #2516 (#2538)
### What problem does this PR solve?

feat: Configurable for excel, html table or row based text #2516

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-23 14:58:51 +08:00
db1be22a2f fix: Merge models of the same category #2479 (#2536)
### What problem does this PR solve?

fix: Merge models of the same category #2479

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-23 14:07:00 +08:00
139268de6f Reverted replacing npm with yarn (#2531)
Reverted replacing npm with yarn

### Type of change

- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-23 11:08:31 +08:00
f6ceb43e36 fix: Add model by ollama in model provider page, user can't choose the model in chat window. #2479 (#2529)
### What problem does this PR solve?

fix: Add model by ollama in model provider page, user can't choose the
model in chat window. #2479

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-23 10:53:18 +08:00
d8a43416f5 Rework Dockerfile.scratch (#2525)
### What problem does this PR solve?

Rework Dockerfile.scratch
- Multiple stage Dockerfile
- Removed conda
- Replaced pip with poetry
- Added missing dependencies and fixed package version conflicts
- Added deepdoc models

### Type of change

- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-23 10:00:44 +08:00
4a6a2a0f1b refine xinference (#2521)
### What problem does this PR solve?

#1588

### Type of change

- [x] Refactoring
2024-09-20 18:37:01 +08:00
9bbef8216d refine reteival of multi-turn conversation (#2520)
### What problem does this PR solve?

#2362 #2484

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Performance Improvement
2024-09-20 17:25:55 +08:00
78856703c4 make excel parsing configurable (#2517)
### What problem does this PR solve?

#2516

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-20 15:33:38 +08:00
099c37ba95 rm key set in xinference (#2511)
### What problem does this PR solve?

#2492

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-20 10:55:52 +08:00
a44f1f735d fix self deployed llm lost (#2510)
### What problem does this PR solve?

#2509 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-20 10:41:25 +08:00
ae6f68e625 Update README_zh.md (#2491)
核心镜像swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:dev 大小为 19.1G,
不是9G

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-20 10:22:47 +08:00
5dd19c6a57 remove setting-system/index.tsx error import (#2507)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

Regarding the code merge #ca0c22f3184b9229e7e86de699842bb3b0e502c2, the
ragflow/web code will not run. This commit solves this problem.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-20 10:21:48 +08:00
5968f148bc refactor add LLM (#2508)
### What problem does this PR solve?

#2487

### Type of change

- [x] Refactoring
2024-09-20 10:20:35 +08:00
4f962d6bff BugFix: Fixed api_key generation error for VolcEngine (#2502)
BugFix: Fixed api_key generation error for VolcEngine with python's
f-string syntax

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: 海贼宅 <stu_xyx@163.com>
2024-09-20 10:03:43 +08:00
ddb8be9219 Web: Display the icon of the currently used storage. (#2504)
https://github.com/infiniflow/ragflow/issues/2503


### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Before:

<img width="611" alt="image"
src="https://github.com/user-attachments/assets/02a3a1ee-7bfb-4fe0-9b15-11ced69cc8a3">

After:

<img width="796" alt="image"
src="https://github.com/user-attachments/assets/371136af-8d16-47aa-909b-26609d3ad60e">

<img width="557" alt="image"
src="https://github.com/user-attachments/assets/9268362f-2b6a-4ea1-9fe7-659f7292e5e1">
2024-09-20 09:49:16 +08:00
422c229e52 Storage: Rename all the variables about get file to storage from minio. (#2497)
https://github.com/infiniflow/ragflow/issues/2496

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [x] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-19 19:19:27 +08:00
b5d1d2fec4 refine TTS (#2500)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-19 19:15:16 +08:00
d545633a6c OpenAITTS (#2493)
### What problem does this PR solve?

OpenAITTS

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-19 16:55:18 +08:00
af0b4b0828 fix(Add model api): Add VolcEngine to create api_key format error (#2490)
### What problem does this PR solve?


Add VolcEngine to create api_key format error
When constructing the json string, there was an extra "," at the end,
which caused a formatting error. This commit fixed the problem.


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-19 15:10:49 +08:00
6c6380d27a update document sdk (#2485)
### Type of change
#2485
- [x] Performance Improvement
2024-09-19 12:52:35 +08:00
2324b88579 fix parser for pptx of which files are from filemanager (#2482)
### What problem does this PR solve?

#2467

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-18 19:13:37 +08:00
2b0dc01a88 rename some attributes in document sdk (#2481)
### What problem does this PR solve?

#1102

### Type of change

- [x] Performance Improvement

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-18 18:46:37 +08:00
01acc3fd5a fix duplicated llm name betweeen different suppliers (#2477)
### What problem does this PR solve?

#2465

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-18 16:09:22 +08:00
2484e26cb5 fix superuser password not base64 encoded (#2475)
### What problem does this PR solve?

Fixes the _superuser_ `admin@ragflow.io` not being accessible due to how
entered passwords are used. Unless this is expected behavior?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-18 14:30:45 +08:00
7195742ca5 rename create_timestamp_flt to create_timestamp_float (#2473)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-09-18 12:50:05 +08:00
62cb5f1bac update document sdk (#2445)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-18 11:08:19 +08:00
e7dd487779 fix ppt file from filemanager error (#2470)
### What problem does this PR solve?

#2467

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-18 09:22:14 +08:00
e41268efc6 Add Multi-Language Descriptions for 'Switch' Component and Update Message Assistant Placeholder (#2450)
### What problem does this PR solve?

_This PR addresses the need to describe the "Switch" component across
different languages and corrects a misleading description for a
placeholder message not exclusively tied to a specific assistant type.
By providing clearer and more accurate descriptions, this PR aims to
improve user understanding and usability of the Switch component and the
"Message Resume Assistant..." placeholder in a multilingual context._

### Explanation of Changes

1. **Added Descriptions for "Switch" Component**: 
- Descriptions were added for the "Switch" component in three different
locales:
- **English (EN)**: Provides a concise description of what the "Switch"
component does, focusing on its ability to evaluate conditions and
direct the flow of execution.
- **Simplified Chinese (ZH)**: Translated the English description into
Simplified Chinese to cater to users who prefer this locale.
- **Traditional Chinese (ZH-Traditional)**: Added a Traditional Chinese
version of the description to support users in regions that use
Traditional Chinese.
   
2. **Corrected "Message Resume Assistant..." to "Message the
Assistant..."**:
- Updated the description from "Message Resume Assistant..." to "Message
the Assistant..." in the English locale. This correction makes the
description more generic and accurate, reflecting the placeholder's
broader functionality, which is not limited to Resume Assistants. It now
clearly communicates that the placeholder can be used with various types
of assistants, not just those related to resumes.

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-15 16:16:10 +08:00
2f33ec7ad0 feat: When voice is turned on, the page will not display an empty reply message when the answer is empty #1877 (#2447)
### What problem does this PR solve?

feat: When voice is turned on, the page will not display an empty reply
message when the answer is empty #1877

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 18:39:13 +08:00
3b1375ef99 feat: If the tts model is not set, the Text to Speech switch is not allowed to be turned on #1877 (#2446)
### What problem does this PR solve?

feat: If the tts model is not set, the Text to Speech switch is not
allowed to be turned on #1877

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 17:45:29 +08:00
2c05e6e6bd Update and rename agentic_rag_introduction.md to agent_introduction.md (#2443)
### What problem does this PR solve?

#2441 

### Type of change


- [x] Documentation Update
2024-09-14 17:36:57 +08:00
8ccc696723 Update _category_.json (#2442)
### What problem does this PR solve?

#2441 

### Type of change

- [x] Documentation Update
2024-09-14 17:36:35 +08:00
1621313c0f feat: After the voice in the new conversation window is played, jump to the tab of the conversation #1877 (#2440)
### What problem does this PR solve?

feat: After the voice in the new conversation window is played, jump to
the tab of the conversation #1877

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 17:19:04 +08:00
b94c15ef1e prepare document for release (#2438)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-09-14 16:09:42 +08:00
8a16c8cc44 fix duplicate function name (#2437)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-14 16:04:02 +08:00
b12a437a30 feat: Supports text output and sound output #1877 (#2436)
### What problem does this PR solve?

feat: Supports text output and sound output #1877

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 15:58:02 +08:00
deeb950e1c feat: Add html to the description text of the parsing method general #336 (#2432)
### What problem does this PR solve?

feat: Add html to the description text of the parsing method general
#336

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 15:18:34 +08:00
6a0702f55f feat: Display mindmap in drawer #2247 (#2430)
### What problem does this PR solve?

feat: Display mindmap in drawer #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-14 14:42:36 +08:00
3044cb85fd fix batch size error for qianwen embedding (#2431)
### What problem does this PR solve?

#2402

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-14 14:40:57 +08:00
d3262ca378 refine the warning message for rewrite component (#2429)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-09-14 14:17:03 +08:00
99a7c0fb97 update sdk document and chunk (#2421)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-14 13:24:21 +08:00
7e75b9d778 fix parsing spaces in russian language PDFs (#1987) (#2427)
### What problem does this PR solve?

[#1987](https://github.com/infiniflow/ragflow/issues/1987)

When scanning PDF files character by character, the parser excluded
spaces if the string did not match regex. Text from [Russian
documents](https://github.com/user-attachments/files/16659706/dogovor_oferta.pdf)
needs spaces, but it does not match the regex because it uses different
alphabet. That's why PDFs were parsed incorrectly and were almost
unusable as source. Fixed that by adding Russian alphabet to regex.

There might be problems with other languages that use different
alphabets. I additionally tested [PDF in
Spanish](https://www.scusd.edu/sites/main/files/file-attachments/howtohelpyourchildsucceedinschoolspanish.pdf?1338307816)
and old [a-zA-Z...] regex parses it correctly with spaces.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-14 13:14:39 +08:00
a467f31238 minor (#2422)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-09-14 09:34:35 +08:00
54342ae0a2 boost highlight performace (#2419)
### What problem does this PR solve?

#2415

### Type of change

- [x] Performance Improvement
2024-09-13 18:10:32 +08:00
bdcf195b20 Initial draft of Create a General-purpose chatbot (#2411)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-09-13 17:21:03 +08:00
3f571a13c2 fix empty children in mindmap (#2418)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-13 17:19:47 +08:00
9d4bb5767c make highlight friendly to English (#2417)
### What problem does this PR solve?

#2415

### Type of change

- [x] Performance Improvement
2024-09-13 17:03:51 +08:00
5e7b93e802 add updates for README (#2413)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-09-13 14:31:04 +08:00
ec4def9a44 feat: When the mindmap data is empty, it will not be displayed on the search page #2247 (#2414)
### What problem does this PR solve?

feat: When the mindmap data is empty, it will not be displayed on the
search page #2247
### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-13 14:30:51 +08:00
2bd71d722b feat: Modify the style of the answer card on the search page #2247 (#2412)
### What problem does this PR solve?

feat: Modify the style of the answer card on the search page #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-13 12:31:31 +08:00
8f2c0176b4 feat: Use Spin to wrap the chunk list on the search page #2247 (#2409)
### What problem does this PR solve?

feat: Use Spin to wrap the chunk list on the search page #2247
### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-09-13 11:38:09 +08:00
b261b6aac0 fix pip install error (#2407)
### What problem does this PR solve?

#2356

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-13 10:06:54 +08:00
cbdf54cf36 feat: Click on the chunk on the search page to locate the corresponding file location #2247 (#2399)
### What problem does this PR solve?

feat: Click on the chunk on the search page to locate the corresponding
file location #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-13 08:54:26 +08:00
db0606e064 feat: Wrap the searched chunk with a Popover #2247 (#2398)
### What problem does this PR solve?

feat: Wrap the searched chunk with a Popover #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 19:15:44 +08:00
cfae63d107 Add RAGFlow benchmark (#2387)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 19:01:00 +08:00
88f8c8ed86 Fix volcengine yfinance confliction (#2386)
### What problem does this PR solve?

#2379 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-12 19:00:35 +08:00
4158697fe6 feat: Add component AkShare #1739 (#2390)
### What problem does this PR solve?

 feat: Add component AkShare #1739

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 17:58:05 +08:00
5f9cb16a3c feat: Add component WenCai #1739 (#2388)
### What problem does this PR solve?

feat: Add component WenCai #1739

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 17:51:43 +08:00
4730145696 debug backend API for TAB 'search' (#2389)
### What problem does this PR solve?
#2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 17:51:20 +08:00
68d0210e92 feat: Use Tree to display the knowledge base list on the search page #2247 (#2385)
### What problem does this PR solve?

feat: Use Tree to display the knowledge base list on the search page
#2247
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 17:23:32 +08:00
f8e9a0590f Common: Support postgreSQL database as the metadata db. (#2357)
https://github.com/infiniflow/ragflow/issues/2356

### What problem does this PR solve?

As title

### Type of change

- [X] New Feature (non-breaking change which adds functionality)
2024-09-12 15:12:39 +08:00
ba834aee26 Add a default value for do_refer in Dialog (#2383)
### What problem does this PR solve?

Add a default value for do_refer in Dialog

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-09-12 15:11:57 +08:00
983540614e feat: Cover the entire search page with a background image #2247 (#2381)
### What problem does this PR solve?

feat: Cover the entire search page with a background image #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 14:20:04 +08:00
6722b3d558 update sdk document (#2374)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-12 14:19:45 +08:00
6000c3e304 feat: Catching errors with IndentedTree #2247 (#2380)
### What problem does this PR solve?

feat: Catching errors with IndentedTree #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-12 13:34:33 +08:00
333608a1d4 add search TAB backend api (#2375)
### What problem does this PR solve?
 #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-11 19:49:18 +08:00
8052cbc70e feat: Retrieval chunks by page #2247 (#2373)
### What problem does this PR solve?

feat: Retrieval chunks by page #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-11 19:48:11 +08:00
b0e0e1fdd0 fix json error (#2372)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-11 19:10:49 +08:00
8e3228d461 feat: Catch errors in getting mindmap #2247 (#2368)
### What problem does this PR solve?

feat: Catch errors in getting mindmap #2247

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-11 16:19:14 +08:00
f789098e9f feat: Proxy the api address to the local nginx address #2350 (#2366)
### What problem does this PR solve?

feat: Proxy the api address to the local nginx address #2350

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-11 15:17:52 +08:00
d6e6c530d7 fix OpenRouter add bug and the way to add OpenRouter model (#2364)
### What problem does this PR solve?

#2359  fix OpenRouter add bug and the way to add OpenRouter model

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-11 15:10:25 +08:00
22c5affacc Update templates:Text2sql and DB Description (#2361)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-09-11 12:25:57 +08:00
35b7d17d97 fix SILICONFLOW embedding error (#2363)
### What problem does this PR solve?

#2335  fix SILICONFLOW embedding error

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-11 12:17:44 +08:00
1fc14ff6d4 SDK for session (#2354)
### What problem does this PR solve?

Includes SDK for creating, updating sessions, getting sessions, listing
sessions, and dialogues
#1102 
### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
2024-09-11 12:03:55 +08:00
7fad48f42c fix: empty or contains only empty strings. (#2347)
### What problem does this PR solve?
the setting was kept empty for Empty_response. In expectation, this case
should get a response from the LLM if can't find the references from the
knowledgebase.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)


![image](https://github.com/user-attachments/assets/9c382b1d-40f6-43b0-848c-fa6863f9a253)

![image](https://github.com/user-attachments/assets/032d2001-97a2-4faa-91bf-c9c57caf2070)

Co-authored-by: Theta Wang (ncu) <chunshan.connect@gmail.com>
2024-09-11 09:32:12 +08:00
77988fe3c2 fix: 123.60.95.134 redirect attack #2350 (#2352)
### What problem does this PR solve?
fix: 123.60.95.134 redirect attack #2350


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-10 17:25:15 +08:00
cb00f36f62 fix categorize error (#2348)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-10 16:03:30 +08:00
7edb4ad7dc fix: Make markdown support line breaks #2315 (#2343)
### What problem does this PR solve?

fix: Make markdown support line breaks #2315

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-10 12:15:02 +08:00
66c54e75f3 add default model types (#2342)
### What problem does this PR solve?


### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-10 11:39:44 +08:00
f60dfffb4b add model types to factories API (#2341)
### What problem does this PR solve?

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-10 11:26:01 +08:00
f1ad778250 feat: Dynamically change the background image on the search homepage every day #2247 (#2338)
### What problem does this PR solve?

feat: Dynamically change the background image on the search homepage
every day #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-10 11:25:12 +08:00
7c8f159751 Fixed a docusaurus display issue (#2340)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update
2024-09-10 11:24:59 +08:00
c57cc0769b Added a brief introduction to Agentic RAG (#2331)
### What problem does this PR solve?



### Type of change


- [x] Documentation Update
2024-09-09 20:16:28 +08:00
869df1f704 minor (#2328)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-09-09 19:30:17 +08:00
42eeb38247 feat: Add RetrievalDocuments to SearchPage #2247 (#2327)
### What problem does this PR solve?
feat: Add RetrievalDocuments to SearchPage #2247
feat: Click on the link in the reference to display the pdf drawer #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 19:20:16 +08:00
7241c73c7a Add benchmark ndcg@10 (#2326)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 19:20:00 +08:00
336a639164 SDK for session (#2312)
### What problem does this PR solve?

SDK for session
#1102 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-09 17:18:08 +08:00
ceae4df889 feat: The search box is displayed globally when the page is loaded for the first time #2247 (#2325)
### What problem does this PR solve?

feat: The search box is displayed globally when the page is loaded for
the first time #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 16:37:04 +08:00
884dcbcb7e updates dead link (#2324)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update
2024-09-09 16:36:52 +08:00
4b57177523 fix error for files from filemanager (#2323)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-09 14:27:22 +08:00
4130519599 feat: Hide search tab #2247 (#2322)
### What problem does this PR solve?

feat: Hide search tab #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 14:06:27 +08:00
0c73f77c4d Update .env (#2319)
### What problem does this PR solve?


### Type of change

- [x] Refactoring
2024-09-09 14:02:48 +08:00
fbe68034aa feat: Click on the relevant question tag to continue searching for answers #2247 (#2320)
### What problem does this PR solve?

feat: Click on the relevant question tag to continue searching for
answers #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 14:02:08 +08:00
22acd0ac67 fix minio error (#2321)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-09 14:01:25 +08:00
4cf122c6db Doc updates for newly updates (#2317)
### What problem does this PR solve?

### Type of change

- [x] Documentation Update

---------

Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-09-09 13:35:50 +08:00
6a77c94365 Update .env For CVE-2024-37288 (#2318)
fix: es CVE-2024-37288

https://discuss.elastic.co/t/kibana-8-15-1-security-update-esa-2024-27-esa-2024-28/366119

### What problem does this PR solve?

### Type of change
- [x] Performance Improvement
2024-09-09 13:34:08 +08:00
80656309f7 fix azure-openai add bug (#2314)
### What problem does this PR solve?

#2236  fix azure-openai add bug

### Type of change


- [x] Bug Fix

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-09 12:10:45 +08:00
9f7d187ab3 add elapsed time of conversation (#2316)
### What problem does this PR solve?

#2315

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 12:08:50 +08:00
63da2cb7d5 fix SILICONFLOW rerank error (#2313)
### What problem does this PR solve?

#2231  fix SILICONFLOW rerank error

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-09 11:41:37 +08:00
cb69c742b0 add support for TongyiQwen tts (#2311)
### What problem does this PR solve?

add support for TongyiQwen tts
#1853

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-09 11:01:43 +08:00
2ac72899ef reduce interval of task executor heart beat (#2308)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
- [ ] Other (please describe):
2024-09-09 10:19:10 +08:00
473f9892fb Updated component descriptions (#2293)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-09-09 10:16:16 +08:00
fe4b2bf969 feat: Show chat tab #2247 (#2307)
### What problem does this PR solve?

feat: Show chat tab #2247
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-09 10:04:22 +08:00
c18b78b261 add a lib (#2306)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-09 09:48:12 +08:00
8dd3adc443 Storage: Support the s3, azure blob as the object storage of ragflow. (#2278)
### What problem does this PR solve?

issue: https://github.com/infiniflow/ragflow/issues/2277

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-09 09:41:14 +08:00
e85fea31a8 feat: Fetch mind map in search page #2247 (#2292)
### What problem does this PR solve?
feat: Fetch mind map in search page #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 19:56:17 +08:00
H
1aba978de2 Add component AkShare (#2290)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 19:09:41 +08:00
H
7e0b3d19d6 Add component TuShare (#2288)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 18:33:35 +08:00
788ca41d9e feat: Added md.svg #345 (#2289)
### What problem does this PR solve?

feat: Added md.svg #345

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 18:32:06 +08:00
6b23308f26 Added kibana (#2286)
Added kibana to make elastic management easier.
PR #1710 did this. 
PR #1714 revert this.
This PR did again and fix some bugs.

- [x] Bug Fix (non-breaking change which fixes an issue)
- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 16:02:44 +08:00
925dd2aa85 feat: Search for the answers you want based on the selected knowledge base #2247 (#2287)
### What problem does this PR solve?

feat: Search for the answers you want based on the selected knowledge
base #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-06 15:42:55 +08:00
b5a2711c05 Fix agent retrieval nothing (#2283)
### What problem does this PR solve?

Fix agent retrieval nothing

### Type of change

- [✓] Bug Fix (non-breaking change which fixes an issue)
2024-09-06 15:02:41 +08:00
H
c6e723f2ee Fix graphrag : "role" user (#2273)
### What problem does this PR solve?

#2270 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-06 10:04:01 +08:00
H
fd3e55cfcf Add component Jin10 (#2271)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 19:45:05 +08:00
6ae0da92cb feat: send question with retrieval api #2247 (#2272)
### What problem does this PR solve?
feat: send question with retrieval api #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 19:32:55 +08:00
H
9377192859 Add component WenCai (#2269)
### What problem does this PR solve?

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 17:50:21 +08:00
42671e08f1 Fine tweaks to template descriptions (#2264)
### What problem does this PR solve?


### Type of change


- [x] Documentation Update
2024-09-05 16:16:03 +08:00
b2f87a9f8f feat: Add sidebar to SearchPage #2247 (#2267)
### What problem does this PR solve?

feat: Add sidebar to SearchPage #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 16:04:04 +08:00
878dca26bb SDK for Assistant (#2266)
### What problem does this PR solve?

SDK for Assistant
#1102 

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
2024-09-05 15:08:02 +08:00
445576ec88 feat: Set the global scroll bar style #2247 (#2265)
### What problem does this PR solve?

feat: Set the global scroll bar style #2247
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 14:47:48 +08:00
04de0c4cef update agent\templates\medical_consultation.json (#2260)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-09-05 12:15:12 +08:00
7e65df87dd feat: Add Sider to SearchPage #2247 (#2262)
### What problem does this PR solve?

feat: Add Sider to SearchPage #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 12:12:44 +08:00
7c98cb5075 feat: Make agent template support HTML #1842 (#2259)
### What problem does this PR solve?

feat: Make agent template support HTML #1842
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 10:49:52 +08:00
6df0f44e71 Bump flask-cors from 4.0.1 to 5.0.0 (#2251)
Bumps [flask-cors](https://github.com/corydolphin/flask-cors) from 4.0.1
to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/corydolphin/flask-cors/releases">flask-cors's
releases</a>.</em></p>
<blockquote>
<h2>5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Breaking: Change default to disable private network access by <a
href="https://github.com/corydolphin"><code>@​corydolphin</code></a> in
<a
href="https://redirect.github.com/corydolphin/flask-cors/pull/368">corydolphin/flask-cors#368</a>
This effectively resolves <a
href="https://github.com/advisories/GHSA-hxwh-jpp2-84pm">https://github.com/advisories/GHSA-hxwh-jpp2-84pm</a>
<a
href="https://osv.dev/vulnerability/PYSEC-2024-71">https://osv.dev/vulnerability/PYSEC-2024-71</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/corydolphin/flask-cors/compare/4.0.2...5.0.0">https://github.com/corydolphin/flask-cors/compare/4.0.2...5.0.0</a></p>
<h2>4.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump requests from 2.31.0 to 2.32.0 in /docs by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/corydolphin/flask-cors/pull/358">corydolphin/flask-cors#358</a></li>
<li>Backwards Compatible Fix for CVE-2024-6221 by <a
href="https://github.com/adrianosela"><code>@​adrianosela</code></a> in
<a
href="https://redirect.github.com/corydolphin/flask-cors/pull/363">corydolphin/flask-cors#363</a></li>
<li>Add unit tests for Private-Network by <a
href="https://github.com/corydolphin"><code>@​corydolphin</code></a> in
<a
href="https://redirect.github.com/corydolphin/flask-cors/pull/367">corydolphin/flask-cors#367</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/dependabot"><code>@​dependabot</code></a> made
their first contribution in <a
href="https://redirect.github.com/corydolphin/flask-cors/pull/358">corydolphin/flask-cors#358</a></li>
<li><a
href="https://github.com/adrianosela"><code>@​adrianosela</code></a>
made their first contribution in <a
href="https://redirect.github.com/corydolphin/flask-cors/pull/363">corydolphin/flask-cors#363</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/corydolphin/flask-cors/compare/4.0.1...4.0.2">https://github.com/corydolphin/flask-cors/compare/4.0.1...4.0.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/corydolphin/flask-cors/blob/main/CHANGELOG.md">flask-cors's
changelog</a>.</em></p>
<blockquote>
<h1>Change Log</h1>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c8514760cf"><code>c851476</code></a>
V5: Breaking: Change default to disable private network access (<a
href="https://redirect.github.com/corydolphin/flask-cors/issues/368">#368</a>)</li>
<li><a
href="561ed263e6"><code>561ed26</code></a>
Add unit tests for Private-Network (<a
href="https://redirect.github.com/corydolphin/flask-cors/issues/367">#367</a>)</li>
<li><a
href="7ae310c56a"><code>7ae310c</code></a>
Backwards Compatible Fix for CVE-2024-6221 (<a
href="https://redirect.github.com/corydolphin/flask-cors/issues/363">#363</a>)</li>
<li><a
href="f25c6b2ed2"><code>f25c6b2</code></a>
--- (<a
href="https://redirect.github.com/corydolphin/flask-cors/issues/358">#358</a>)</li>
<li>See full diff in <a
href="https://github.com/corydolphin/flask-cors/compare/4.0.1...5.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flask-cors&package-manager=pip&previous-version=4.0.1&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 09:34:22 +08:00
c998ad7a18 Bump nltk from 3.8.1 to 3.9 (#2250)
Bumps [nltk](https://github.com/nltk/nltk) from 3.8.1 to 3.9.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/nltk/nltk/blob/develop/ChangeLog">nltk's
changelog</a>.</em></p>
<blockquote>
<p>Version 3.9.1 2024-08-19</p>
<ul>
<li>Fixed bug that prevented wordnet from loading</li>
</ul>
<p>Version 3.9 2024-08-18</p>
<ul>
<li>Fix security vulnerability CVE-2024-39705 (breaking change)</li>
<li>Replace pickled models (punkt, chunker, taggers) by new pickle-free
&quot;_tab&quot; packages</li>
<li>No longer sort WordNet synsets and relations (sort in calling
function when required)</li>
<li>Add Python 3.12 support</li>
<li>Many other minor fixes</li>
</ul>
<p>Thanks to the following contributors to 3.8.2:
Tom Aarsen, Cat Lee Ball, Veralara Bernhard, Carlos Brandt, Konstantin
Chernyshev, Michael Higgins,
Eric Kafe, Vivek Kalyan, David Lukes, Rob Malouf, purificant, Alex
Rudnick, Liling Tan, Akihiro Yamazaki.</p>
<p>Version 3.8.1 2023-01-02</p>
<ul>
<li>Resolve RCE vulnerability in localhost WordNet Browser (<a
href="https://redirect.github.com/nltk/nltk/issues/3100">#3100</a>)</li>
<li>Remove unused tool scripts (<a
href="https://redirect.github.com/nltk/nltk/issues/3099">#3099</a>)</li>
<li>Resolve XSS vulnerability in localhost WordNet Browser (<a
href="https://redirect.github.com/nltk/nltk/issues/3096">#3096</a>)</li>
<li>Add Python 3.11 support (<a
href="https://redirect.github.com/nltk/nltk/issues/3090">#3090</a>)</li>
</ul>
<p>Thanks to the following contributors to 3.8.1:
Francis Bond, John Vandenberg, Tom Aarsen</p>
<p>Version 3.8 2022-12-12</p>
<ul>
<li>Refactor dispersion plot (<a
href="https://redirect.github.com/nltk/nltk/issues/3082">#3082</a>)</li>
<li>Provide type hints for LazyCorpusLoader variables (<a
href="https://redirect.github.com/nltk/nltk/issues/3081">#3081</a>)</li>
<li>Throw warning when LanguageModel is initialized with incorrect
vocabulary (<a
href="https://redirect.github.com/nltk/nltk/issues/3080">#3080</a>)</li>
<li>Fix WordNet's all_synsets() function (<a
href="https://redirect.github.com/nltk/nltk/issues/3078">#3078</a>)</li>
<li>Resolve TreebankWordDetokenizer inconsistency with end-of-string
contractions (<a
href="https://redirect.github.com/nltk/nltk/issues/3070">#3070</a>)</li>
<li>Support both iso639-3 codes and BCP-47 language tags (<a
href="https://redirect.github.com/nltk/nltk/issues/3060">#3060</a>)</li>
<li>Avoid DeprecationWarning in Regexp tokenizer (<a
href="https://redirect.github.com/nltk/nltk/issues/3055">#3055</a>)</li>
<li>Fix many doctests, add doctests to CI (<a
href="https://redirect.github.com/nltk/nltk/issues/3054">#3054</a>, <a
href="https://redirect.github.com/nltk/nltk/issues/3050">#3050</a>, <a
href="https://redirect.github.com/nltk/nltk/issues/3048">#3048</a>)</li>
<li>Fix bool field not being read in VerbNet (<a
href="https://redirect.github.com/nltk/nltk/issues/3044">#3044</a>)</li>
<li>Greatly improve time efficiency of SyllableTokenizer when tokenizing
numbers (<a
href="https://redirect.github.com/nltk/nltk/issues/3042">#3042</a>)</li>
<li>Fix encodings of Polish udhr corpus reader (<a
href="https://redirect.github.com/nltk/nltk/issues/3038">#3038</a>)</li>
<li>Allow TweetTokenizer to tokenize emoji flag sequences (<a
href="https://redirect.github.com/nltk/nltk/issues/3034">#3034</a>)</li>
<li>Prevent LazyModule from increasing the size of
nltk.<strong>dict</strong> (<a
href="https://redirect.github.com/nltk/nltk/issues/3033">#3033</a>)</li>
<li>Fix CoreNLPServer non-default port issue (<a
href="https://redirect.github.com/nltk/nltk/issues/3031">#3031</a>)</li>
<li>Add &quot;acion&quot; suffix to the Spanish SnowballStemmer (<a
href="https://redirect.github.com/nltk/nltk/issues/3030">#3030</a>)</li>
<li>Allow loading WordNet without OMW (<a
href="https://redirect.github.com/nltk/nltk/issues/3026">#3026</a>)</li>
<li>Use input() in nltk.chat.chatbot() for Jupyter support (<a
href="https://redirect.github.com/nltk/nltk/issues/3022">#3022</a>)</li>
<li>Fix edit_distance_align() in distance.py (<a
href="https://redirect.github.com/nltk/nltk/issues/3017">#3017</a>)</li>
<li>Tackle performance and accuracy regression of sentence tokenizer
since NLTK 3.6.6 (<a
href="https://redirect.github.com/nltk/nltk/issues/3014">#3014</a>)</li>
<li>Add the Iota operator to semantic logic (<a
href="https://redirect.github.com/nltk/nltk/issues/3010">#3010</a>)</li>
<li>Resolve critical errors in WordNet app (<a
href="https://redirect.github.com/nltk/nltk/issues/3008">#3008</a>)</li>
<li>Resolve critical error in CHILDES Corpus (<a
href="https://redirect.github.com/nltk/nltk/issues/2998">#2998</a>)</li>
<li>Make WordNet information_content() accept adjective satellites (<a
href="https://redirect.github.com/nltk/nltk/issues/2995">#2995</a>)</li>
<li>Add &quot;strict=True&quot; parameter to CoreNLP (<a
href="https://redirect.github.com/nltk/nltk/issues/2993">#2993</a>, <a
href="https://redirect.github.com/nltk/nltk/issues/3043">#3043</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="24936a2d0c"><code>24936a2</code></a>
Bump version to 3.9</li>
<li><a
href="c222897403"><code>c222897</code></a>
Merge branch 'develop' of <a
href="https://github.com/nltk/nltk">https://github.com/nltk/nltk</a>
into develop</li>
<li><a
href="34c3a4ad4e"><code>34c3a4a</code></a>
Merge branch 'develop' of <a
href="https://github.com/nltk/nltk">https://github.com/nltk/nltk</a>
into develop</li>
<li><a
href="253dd3acd1"><code>253dd3a</code></a>
add black</li>
<li><a
href="c43727fad6"><code>c43727f</code></a>
Update version</li>
<li><a
href="7137405da3"><code>7137405</code></a>
Merge pull request <a
href="https://redirect.github.com/nltk/nltk/issues/3066">#3066</a> from
asishm/bugfix-lambda-closure-leak</li>
<li><a
href="369cb9f85d"><code>369cb9f</code></a>
Merge pull request <a
href="https://redirect.github.com/nltk/nltk/issues/3245">#3245</a> from
ekaf/hotfix-closuredup</li>
<li><a
href="501c70e20a"><code>501c70e</code></a>
Merge branch 'develop' into hotfix-closuredup</li>
<li><a
href="bf05dc4cf2"><code>bf05dc4</code></a>
Merge pull request <a
href="https://redirect.github.com/nltk/nltk/issues/3306">#3306</a> from
ekaf/py3_compat</li>
<li><a
href="66539c7cc7"><code>66539c7</code></a>
Sorted output in unit/test_wordnet.py</li>
<li>Additional commits viewable in <a
href="https://github.com/nltk/nltk/compare/3.8.1...3.9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nltk&package-manager=pip&previous-version=3.8.1&new-version=3.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 09:34:11 +08:00
1dcc416c70 Bump cryptography from 42.0.5 to 43.0.1 (#2253)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.5
to 43.0.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's
changelog</a>.</em></p>
<blockquote>
<p>43.0.1 - 2024-09-03</p>
<pre><code>
* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL
3.3.2.
<p>.. _v43-0-0:</p>
<p>43.0.0 - 2024-07-20<br />
</code></pre></p>
<ul>
<li><strong>BACKWARDS INCOMPATIBLE:</strong> Support for OpenSSL less
than 1.1.1e has been
removed.  Users on older version of OpenSSL will need to upgrade.</li>
<li><strong>BACKWARDS INCOMPATIBLE:</strong> Dropped support for
LibreSSL &lt; 3.8.</li>
<li>Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL
3.3.1.</li>
<li>Updated the minimum supported Rust version (MSRV) to 1.65.0, from
1.63.0.</li>

<li>:func:<code>~cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key</code>
now enforces a minimum RSA key size of 1024-bit. Note that 1024-bit is
still
considered insecure, users should generally use a key size of
2048-bits.</li>

<li>:func:<code>~cryptography.hazmat.primitives.serialization.pkcs7.serialize_certificates</code>
now emits ASN.1 that more closely follows the recommendations in
:rfc:<code>2315</code>.</li>
<li>Added new :doc:<code>/hazmat/decrepit/index</code> module which
contains outdated and
insecure cryptographic primitives.

:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.CAST5</code>,

:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.SEED</code>,

:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.IDEA</code>,
and

:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.Blowfish</code>,
which were
deprecated in 37.0.0, have been added to this module. They will be
removed
from the <code>cipher</code> module in 45.0.0.</li>
<li>Moved
:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.TripleDES</code>
and
:class:<code>~cryptography.hazmat.primitives.ciphers.algorithms.ARC4</code>
into
:doc:<code>/hazmat/decrepit/index</code> and deprecated them in the
<code>cipher</code> module.
They will be removed from the <code>cipher</code> module in 48.0.0.</li>
<li>Added support for deterministic
:class:<code>~cryptography.hazmat.primitives.asymmetric.ec.ECDSA</code>
(:rfc:<code>6979</code>)</li>
<li>Added support for client certificate verification to the
:mod:<code>X.509 path validation
&lt;cryptography.x509.verification&gt;</code> APIs in the
form of
:class:<code>~cryptography.x509.verification.ClientVerifier</code>,
:class:<code>~cryptography.x509.verification.VerifiedClient</code>, and
<code>PolicyBuilder</code>

:meth:<code>~cryptography.x509.verification.PolicyBuilder.build_client_verifier</code>.</li>
<li>Added Certificate

:attr:<code>~cryptography.x509.Certificate.public_key_algorithm_oid</code>
and Certificate Signing Request

:attr:<code>~cryptography.x509.CertificateSigningRequest.public_key_algorithm_oid</code>
to determine the
:class:<code>~cryptography.hazmat._oid.PublicKeyAlgorithmOID</code>
Object Identifier of the public key found inside the certificate.</li>
<li>Added
:attr:<code>~cryptography.x509.InvalidityDate.invalidity_date_utc</code>,
a
timezone-aware alternative to the naïve <code>datetime</code> attribute

:attr:<code>~cryptography.x509.InvalidityDate.invalidity_date</code>.</li>
<li>Added support for parsing empty DN string in</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a773387828"><code>a773387</code></a>
bump for 43.0.1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/11533">#11533</a>)</li>
<li><a
href="0393fef575"><code>0393fef</code></a>
Backport setuptools version ban (<a
href="https://redirect.github.com/pyca/cryptography/issues/11526">#11526</a>)</li>
<li><a
href="6687bab97a"><code>6687bab</code></a>
Bump openssl from 0.10.65 to 0.10.66 in /src/rust (<a
href="https://redirect.github.com/pyca/cryptography/issues/11320">#11320</a>)
(<a
href="https://redirect.github.com/pyca/cryptography/issues/11324">#11324</a>)</li>
<li><a
href="ebf14f2edc"><code>ebf14f2</code></a>
bump for 43.0.0 and update changelog (<a
href="https://redirect.github.com/pyca/cryptography/issues/11311">#11311</a>)</li>
<li><a
href="42788a0353"><code>42788a0</code></a>
Fix exchange with keys that had Q automatically computed (<a
href="https://redirect.github.com/pyca/cryptography/issues/11309">#11309</a>)</li>
<li><a
href="2dbdfb8f39"><code>2dbdfb8</code></a>
don't assign unused name (<a
href="https://redirect.github.com/pyca/cryptography/issues/11310">#11310</a>)</li>
<li><a
href="ccc66e6cdf"><code>ccc66e6</code></a>
Bump openssl from 0.10.64 to 0.10.65 in /src/rust (<a
href="https://redirect.github.com/pyca/cryptography/issues/11308">#11308</a>)</li>
<li><a
href="4310c8727b"><code>4310c87</code></a>
Bump sphinxcontrib-qthelp from 1.0.7 to 1.0.8 (<a
href="https://redirect.github.com/pyca/cryptography/issues/11307">#11307</a>)</li>
<li><a
href="f66a9c4b4f"><code>f66a9c4</code></a>
Bump sphinxcontrib-htmlhelp from 2.0.5 to 2.0.6 (<a
href="https://redirect.github.com/pyca/cryptography/issues/11306">#11306</a>)</li>
<li><a
href="a8fcf18ee0"><code>a8fcf18</code></a>
Bump openssl-sys from 0.9.102 to 0.9.103 in /src/rust (<a
href="https://redirect.github.com/pyca/cryptography/issues/11305">#11305</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pyca/cryptography/compare/42.0.5...43.0.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cryptography&package-manager=pip&previous-version=42.0.5&new-version=43.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 09:34:01 +08:00
8c075f8287 Bump aiohttp from 3.9.4 to 3.10.2 (#2254)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.4 to
3.10.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/aio-libs/aiohttp/releases">aiohttp's
releases</a>.</em></p>
<blockquote>
<h2>3.10.2</h2>
<h2>Bug fixes</h2>
<ul>
<li>
<p>Fixed server checks for circular symbolic links to be compatible with
Python 3.13 -- by :user:<code>steverep</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8565">#8565</a>.</p>
</li>
<li>
<p>Fixed request body not being read when ignoring an Upgrade request --
by :user:<code>Dreamsorcerer</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8597">#8597</a>.</p>
</li>
<li>
<p>Fixed an edge case where shutdown would wait for timeout when the
handler was already completed -- by
:user:<code>Dreamsorcerer</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8611">#8611</a>.</p>
</li>
<li>
<p>Fixed connecting to <code>npipe://</code>, <code>tcp://</code>, and
<code>unix://</code> urls -- by :user:<code>bdraco</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8632">#8632</a>.</p>
</li>
<li>
<p>Fixed WebSocket ping tasks being prematurely garbage collected -- by
:user:<code>bdraco</code>.</p>
<p>There was a small risk that WebSocket ping tasks would be prematurely
garbage collected because the event loop only holds a weak reference to
the task. The garbage collection risk has been fixed by holding a strong
reference to the task. Additionally, the task is now scheduled eagerly
with Python 3.12+ to increase the chance it can be completed immediately
and avoid having to hold any references to the task.</p>
<p><em>Related issues and pull requests on GitHub:</em>
<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8641">#8641</a>.</p>
</li>
<li>
<p>Fixed incorrectly following symlinks for compressed file variants --
by :user:<code>steverep</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst">aiohttp's
changelog</a>.</em></p>
<blockquote>
<h1>3.10.2 (2024-08-08)</h1>
<h2>Bug fixes</h2>
<ul>
<li>
<p>Fixed server checks for circular symbolic links to be compatible with
Python 3.13 -- by :user:<code>steverep</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>8565</code>.</p>
</li>
<li>
<p>Fixed request body not being read when ignoring an Upgrade request --
by :user:<code>Dreamsorcerer</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>8597</code>.</p>
</li>
<li>
<p>Fixed an edge case where shutdown would wait for timeout when the
handler was already completed -- by
:user:<code>Dreamsorcerer</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>8611</code>.</p>
</li>
<li>
<p>Fixed connecting to <code>npipe://</code>, <code>tcp://</code>, and
<code>unix://</code> urls -- by :user:<code>bdraco</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>8632</code>.</p>
</li>
<li>
<p>Fixed WebSocket ping tasks being prematurely garbage collected -- by
:user:<code>bdraco</code>.</p>
<p>There was a small risk that WebSocket ping tasks would be prematurely
garbage collected because the event loop only holds a weak reference to
the task. The garbage collection risk has been fixed by holding a strong
reference to the task. Additionally, the task is now scheduled eagerly
with Python 3.12+ to increase the chance it can be completed immediately
and avoid having to hold any references to the task.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>8641</code>.</p>
</li>
<li>
<p>Fixed incorrectly following symlinks for compressed file variants --
by :user:<code>steverep</code>.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="491106e65a"><code>491106e</code></a>
Release 3.10.2 (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8655">#8655</a>)</li>
<li><a
href="ce2e975881"><code>ce2e975</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8652">#8652</a>/b0536ae6
backport][3.10] Do not follow symlinks for compressed file...</li>
<li><a
href="6a778061eb"><code>6a77806</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8636">#8636</a>/51d872e
backport][3.10] Remove Request.wait_for_disconnection() met...</li>
<li><a
href="1f92213c3e"><code>1f92213</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8642">#8642</a>/e4942771
backport][3.10] Fix response to circular symlinks with Pyt...</li>
<li><a
href="2ef14a6631"><code>2ef14a6</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8641">#8641</a>/0a88bab
backport][3.10] Fix WebSocket ping tasks being prematurely ...</li>
<li><a
href="68e84968de"><code>68e8496</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8608">#8608</a>/c4acabc
backport][3.10] Fix timer handle churn in websocket heartbe...</li>
<li><a
href="72f41aab59"><code>72f41aa</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8632">#8632</a>/b2691f2
backport][3.10] Fix connecting to npipe://, tcp://, and uni...</li>
<li><a
href="bf83dbe19e"><code>bf83dbe</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8634">#8634</a>/c7293e19
backport][3.10] Backport <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8620">#8620</a>
as improvements to various ...</li>
<li><a
href="4815765a6b"><code>4815765</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8597">#8597</a>/c99a1e27
backport][3.10] Fix reading of body when ignoring an upgra...</li>
<li><a
href="266608d2e4"><code>266608d</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8611">#8611</a>/1fcef940
backport][3.10] Fix handler waiting on shutdown (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/8627">#8627</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/aio-libs/aiohttp/compare/v3.9.4...v3.10.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aiohttp&package-manager=pip&previous-version=3.9.4&new-version=3.10.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/infiniflow/ragflow/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 09:33:47 +08:00
9b90a44323 feat: Add SearchPage #2247 (#2248)
### What problem does this PR solve?

feat: Add SearchPage #2247

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-05 09:33:05 +08:00
H
426fdafb66 Add component yahoo finance (#2244)
### What problem does this PR solve?


### Type of change

- [ ] New Feature (non-breaking change which adds functionality)
2024-09-04 19:51:07 +08:00
02fb7a88e3 fix issue wrong agent prologue for api (#2246)
### What problem does this PR solve?

#2242
### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-04 19:11:55 +08:00
0fe19f3fbc fix QWenSeq2txt bug (#2245)
### What problem does this PR solve?

#2243

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-04 18:25:43 +08:00
H
9b4cceb3f7 Fix component qweather (#2240)
### What problem does this PR solve?

#2239 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-04 17:53:11 +08:00
65255f2a8e Add Authorization checks (#2235)
### What problem does this PR solve?

Add Authorization checks

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
2024-09-04 11:53:45 +08:00
9dd380d474 feat: Comment out tts item #2088 (#2232)
### What problem does this PR solve?

feat: Comment out tts item #2088
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-04 11:11:52 +08:00
0164856343 Add Authorization checks (#2221)
### What problem does this PR solve?

Add Authorization checks
#2203

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-04 10:36:15 +08:00
H
4f05803690 Fix bug : bad escape \x at position xxx (line xx, column xx) in agent (#2226)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-03 19:56:06 +08:00
abc32803cc add stream chat with TTS (#2228)
### What problem does this PR solve?



### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-03 19:49:14 +08:00
07de36ec86 feat: Supports pronunciation while outputting text #2088 (#2227)
### What problem does this PR solve?

feat: Supports pronunciation while outputting text #2088

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-03 19:47:50 +08:00
87a998e9e5 fix tts add bug (#2224)
### What problem does this PR solve?

fix tts add bug

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-03 18:40:20 +08:00
0aafa281a5 Add Authorization checks (#2218)
### What problem does this PR solve?

Add Authorization checks
#2203

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
2024-09-03 16:28:46 +08:00
2871455e4e fix zhipuCV bug (#2215)
### What problem does this PR solve?

#2198  fix zhipuCV bug

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-03 15:11:53 +08:00
f09b204ae4 fix error response disformat usage (#2213)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-03 14:57:58 +08:00
5a2c542ce2 make term similarity robust (#2212)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-09-03 14:30:07 +08:00
4d9e9f0dbb Add Authorization checks (#2209)
### What problem does this PR solve?

Add Authorization checks 
#2203

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-03 13:45:02 +08:00
6d232f1bdb enable 3 char words to finegrind tokenize (#2210)
### What problem does this PR solve?


### Type of change


- [x] Performance Improvement
2024-09-03 13:37:32 +08:00
21179a9be9 Minor editorial updates (#2207)
### What problem does this PR solve?



### Type of change

- [x] Documentation Update
2024-09-03 11:18:10 +08:00
9081bc969a feat: Add tts Switch to chat configuration modal #2088 (#2206)
### What problem does this PR solve?

feat: Add tts Switch to chat configuration modal  #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-03 10:36:49 +08:00
e949594579 feat: add tenant api of create & delete user (#2204)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-09-03 10:36:22 +08:00
1a1888ed22 feat: Play audio #2088 (#2200)
### What problem does this PR solve?
feat: Play audio #2088


### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-09-03 09:55:19 +08:00
97e4eccf03 Update api.md (#2196)
### What problem does this PR solve?


### Type of change

- [x] Documentation Update

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>
2024-09-02 18:54:33 +08:00
b10eb8d085 fix re sub bug (#2199)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 18:53:30 +08:00
H
1d2c081710 Fix component PubMed (#2195)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 18:49:09 +08:00
ad09d4bb24 fix tts interface error (#2197)
### What problem does this PR solve?

fix tts interface error

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-09-02 18:40:57 +08:00
b9c383612d fix folder name suffix checking` (#2194)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 16:21:57 +08:00
H
ab9efb3c23 Fix component PubMed (#2192)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 16:19:41 +08:00
922f79e757 Fixed a broken link (#2190)
To fix a broken link

### Type of change

- [x] Documentation Update
2024-09-02 14:31:31 +08:00
c04686d426 fix: After sending the message for the first time, the returned content is not streamed out #2067 #1832 (#2191)
### What problem does this PR solve?

fix: After sending the message for the first time, the returned content
is not streamed out #2067 #1832

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 14:31:00 +08:00
9a85f83569 feat: add api of tenant app (#2177)
### What problem does this PR solve?

add api of tenant app

### Type of change
- [x] New Feature (non-breaking change which adds functionality)
2024-09-02 12:08:16 +08:00
5decdde182 add support for Google Cloud (#2175)
### What problem does this PR solve?

#1853 add support for Google Cloud

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-09-02 12:06:41 +08:00
def18308d0 fix: Copied API link error #2188 (#2189)
### What problem does this PR solve?

fix: Copied API link error #2188

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-09-02 11:00:27 +08:00
fc6d8ee77f ignore when save image fail (#2178)
### What problem does this PR solve?


### Type of change
- [x] Performance Improvement
2024-08-30 18:41:31 +08:00
5400467da1 feat: Select derived messages from backend #2088 (#2176)
### What problem does this PR solve?

feat: Select derived messages from backend #2088

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-08-30 17:53:30 +08:00
2c771fb0b4 Complete DataSet SDK implementation (#2171)
### What problem does this PR solve?

Complete DataSet SDK implementation
#1102

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
2024-08-30 16:54:22 +08:00
667632ba00 feat: Hide the delete button on the agent page #2088 (#2167)
### What problem does this PR solve?

feat: Hide the delete button on the agent page #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-29 19:06:18 +08:00
a82f092dac feat: Regenerate chat message #2088 (#2166)
### What problem does this PR solve?

feat: Regenerate chat message #2088
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-08-29 18:37:18 +08:00
742d0f0ea9 re-generate for conversation (#2165)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-29 18:32:58 +08:00
69bbf8e9c5 fix anthropic bug (#2161)
### What problem does this PR solve?

#2159  fix anthropic bug

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-08-29 17:13:58 +08:00
12975cf128 Fix some security vulnerabilities. (#2160)
### What problem does this PR solve?

Fix some security vulnerabilities

### Type of change

- [x] Performance Improvement

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-08-29 16:21:32 +08:00
99993e5026 add support for Voyage AI (#2159)
### What problem does this PR solve?

#1853  #2138 add support for Voyage AI

### Type of change
- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-29 16:14:49 +08:00
15b78bd894 Fix the issue about No module named 'graspologic' #2157 (#2158)
### What problem does this PR solve?

Fix the issue #2157 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-29 15:54:25 +08:00
f8a479bf88 feat: Delete message by id #2088 (#2155)
### What problem does this PR solve?

feat: Delete message by id #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-29 14:32:04 +08:00
f87e7242cd complete implementation of dataset SDK (#2147)
### What problem does this PR solve?

Complete implementation of dataset SDK.
#1102

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Feiue <10215101452@stu.ecun.edu.cn>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-29 14:31:31 +08:00
fc1ac3a962 fix delete message error (#2153)
### What problem does this PR solve?



### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-29 14:07:14 +08:00
212bb8e601 add retry count to task (#2152)
### What problem does this PR solve?


### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-08-29 13:31:41 +08:00
06abef66ef add support for Anthropic (#2148)
### What problem does this PR solve?

#1853  add support for Anthropic

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-29 13:30:06 +08:00
0abc01311b Update Dockerfile.arm (#2150)
added NLTK lib  install

### What problem does this PR solve?


### Type of change
- [x] Performance Improvement
2024-08-29 13:03:43 +08:00
1eb6286339 feat: Send message with uuid #2088 (#2149)
### What problem does this PR solve?

feat: Send message with uuid #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-29 11:24:27 +08:00
4bd6c3145c alter message id (#2146)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-28 19:23:53 +08:00
190e144a70 feat: Show prompt send to LLM for assistant answer #2098 (#2142)
### What problem does this PR solve?

feat: Show prompt send to LLM for assistant answer #2098
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-28 19:05:15 +08:00
H
527ebec2f5 Fix Logical operator (#2143)
### What problem does this PR solve?

#2120 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-28 19:04:48 +08:00
a0b7c78dca optimize text parser (#2144)
### What problem does this PR solve?


### Type of change

- [x] Performance Improvement
2024-08-28 18:11:19 +08:00
54f7c6ea8e feat: Submit Feedback #2088 (#2134)
### What problem does this PR solve?

feat: Submit Feedback #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-28 16:39:21 +08:00
H
f843dd05e5 Fix exeSQL component output (#2141)
### What problem does this PR solve?

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-28 16:39:10 +08:00
3abc9be1c2 fix(graphrag): variable refernence error (#2136)
### What problem does this PR solve?

fix: Use wrong variable in graph rag step.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)


Co-authored-by: 陈晓强 <chenxiaoqiang@cvte.com>
2024-08-28 16:35:42 +08:00
e627ee9ea4 fix: build on ARM #2137 (#2139)
Fix building on ARM architecture.

### What problem does this PR solve?

Fix building on ARM architecture.

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)


### Related issues

- https://github.com/infiniflow/ragflow/issues/2137
- https://github.com/infiniflow/ragflow/issues/610
- https://github.com/infiniflow/ragflow/issues/434
- https://github.com/infiniflow/ragflow/issues/253
2024-08-28 16:29:56 +08:00
6c1f1a9f53 remove alter log (#2140)
### What problem does this PR solve?


### Type of change
- [x] Refactoring
2024-08-28 16:29:23 +08:00
H
b51237be17 Fix Text2SQL (#2131)
### What problem does this PR solve?

Fix exeSQL component 
Update DB Assistant template 
Fix canvas Message window size

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-28 14:14:13 +08:00
5daed10136 make task resumable (#2132)
### What problem does this PR solve?

### Type of change


- [x] Performance Improvement
2024-08-28 14:06:27 +08:00
074d4f5031 fix: Delete the model.ts file of chat #1306 (#2129)
### What problem does this PR solve?
fix:  Delete the model.ts file of chat #1306

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-28 11:56:35 +08:00
e9f5468a49 fix the max token of Tongyi-Qianwen text-embedding-v3 model to 8k (#2118)
### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

fix the max token of Tongyi-Qianwen text-embedding-v3 model to 8k

close #2117 

### Type of change

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):
2024-08-28 10:14:19 +08:00
a2b4d0190c feat: Align the cards on the Model Providers page #2111 (#2125)
### What problem does this PR solve?

feat: Align the cards on the Model Providers page #2111

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-27 19:27:58 +08:00
c8097e97cb feat: Modify the modal style of creating an agent so that there are more templates in the field of view #2122 (#2123)
### What problem does this PR solve?

feat: Modify the modal style of creating an agent so that there are more
templates in the field of view #2122

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-27 18:49:08 +08:00
fc172b4a79 feat: Pop-up prompt message after modifying the dialog settings #2088 (#2114)
### What problem does this PR solve?

feat: Pop-up prompt message after modifying the dialog settings #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-27 15:24:28 +08:00
0bea7f21ae create and update dataset (#2110)
### What problem does this PR solve?

Added the ability to create and update dataset for SDK

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: root <root@xwg>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-27 15:23:50 +08:00
61d2a74b25 feat: Fetch conversation list by @tanstack/react-query and displays error message that task_executor does not exist #2088 (#2112)
### What problem does this PR solve?

feat: Fetch conversation list by @tanstack/react-query
feat: Displays error message that task_executor does not exist

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-27 14:45:17 +08:00
1d88b197fb add fish audio zh and zh-traditional (#2109)
### What problem does this PR solve?

add fish audio zh and zh-traditional

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-08-27 14:44:50 +08:00
b88c3897b9 add tts api (#2107)
### What problem does this PR solve?

add tts api 


- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-27 13:15:54 +08:00
2da4e7aa46 add support for Tencent Cloud ASR (#2102)
### What problem does this PR solve?

add support for Tencent Cloud ASR

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-27 11:47:11 +08:00
cf038e099f update groq llm (#2103)
### What problem does this PR solve?

#2076   update groq llm.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
2024-08-27 11:42:00 +08:00
88d52e335c fix no tts issue (#2101)
### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-26 18:06:50 +08:00
H
13785edaae Fix API key validation api/conversation (#2100)
### What problem does this PR solve?

#2081 

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-26 17:29:44 +08:00
6d3e3e4e3c add prompt to message (#2099)
### What problem does this PR solve?

#2098

### Type of change
 
- [x] New Feature (non-breaking change which adds functionality)
2024-08-26 16:14:15 +08:00
6b7c028578 add support for TTS model (#2095)
### What problem does this PR solve?

add support for TTS model
#1853

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <cenzhedong2@126.com>
Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
2024-08-26 15:19:43 +08:00
c3e344b0f1 fix callback function error (#2096)
### What problem does this PR solve?

#2085

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-26 14:12:52 +08:00
e9202999cb alter way of alerting info of empty task (#2094)
### What problem does this PR solve?

#2043

### Type of change

- [x] Refactoring
2024-08-26 13:45:26 +08:00
a6d85c6c2f Provide detailed error information. (#2093)
### What problem does this PR solve?

Most 'index failure' error is caused by ES.

### Type of change

- [x] Refactoring

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-08-26 13:36:00 +08:00
7539d142a9 VolcEngine SDK V3 adaptation (#2082)
1) Configuration interface update
2) Back-end adaptation API update
Note: The official no longer supports the Skylark1/2 series, and all
have been switched to the Doubao series


![image](https://github.com/user-attachments/assets/f6fd8782-0cdf-4c0b-ac8f-9eb130f667a5)

### What problem does this PR solve?

_Briefly describe what this PR aims to solve. Include background context
that will help reviewers understand the purpose of the PR._

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Documentation Update
- [ ] Refactoring
- [ ] Performance Improvement
- [ ] Other (please describe):

Co-authored-by: 海贼宅 <stu_xyx@163.com>
2024-08-26 13:34:29 +08:00
e953f01951 add thumb up api (#2092)
### What problem does this PR solve?

#2088

### Type of change
 
- [x] New Feature (non-breaking change which adds functionality)
2024-08-26 13:27:41 +08:00
eb20b60b13 add inferface for message thumbup (#2091)
### What problem does this PR solve?

#2088

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-08-26 12:58:19 +08:00
d48731ac8c add message id to conversions (#2090)
### What problem does this PR solve?

#2088 
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
2024-08-26 12:05:15 +08:00
b4a5d83b44 feat: Add FeedbackModal #2088 (#2089)
### What problem does this PR solve?

feat: Add FeedbackModal #2088

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-26 11:53:56 +08:00
99af1cbeac Update license (#2086)
Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2024-08-25 18:58:20 +08:00
63d0b39c5c Update quickstart.mdx (#2084)
### What problem does this PR solve?

[minor] Fixed a docusaurus display issue.

### Type of change

- [x] Documentation Update
2024-08-25 09:12:44 +08:00
863cec1bad prepare for sdk http api (#2075)
### What problem does this PR solve?

#1605

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
2024-08-23 19:36:17 +08:00
e14e0ec695 create dataset (#2074)
### What problem does this PR solve?

You can use sdk to create a dataset

### Type of change

- [x] New Feature

---------

Co-authored-by: root <root@xwg>
2024-08-23 18:38:20 +08:00
6228b1bd53 fix: Filter out disabled values ​​from the llm options #2072 (#2073)
### What problem does this PR solve?

fix: Filter out disabled values ​​from the llm options #2072

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
2024-08-23 17:01:35 +08:00
1201 changed files with 134331 additions and 35474 deletions

View File

@ -1,30 +1,36 @@
name: Bug Report
name: "🐞 Bug Report"
description: Create a bug issue for RAGFlow
title: "[Bug]: "
labels: [bug]
labels: ["🐞 bug"]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for the same bug?
description: Please check if an issue already exists for the bug you encountered.
label: Self Checks
description: "Please check the following in order to be responded in time :)"
options:
- label: I have checked the existing issues.
required: true
- label: I have searched for existing issues [search for existing issues](https://github.com/infiniflow/ragflow/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: Non-english title submitions will be closed directly ( 非英文标题的提交将会被直接关闭 ) ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
required: true
- type: markdown
attributes:
value: "Please provide the following information to help us understand the issue."
- type: input
attributes:
label: Branch name
description: Enter the name of the branch where you encountered the issue.
placeholder: e.g., main
label: RAGFlow workspace code commit ID
description: Enter the commit ID associated with the issue.
placeholder: e.g., 26d3480e
validations:
required: true
- type: input
attributes:
label: Commit ID
description: Enter the commit ID associated with the issue.
placeholder: e.g., c3b2a1
label: RAGFlow image version
description: Enter the image version(shown in RAGFlow UI, `System` page) associated with the issue.
placeholder: e.g., 26d3480e(v0.13.0~174)
validations:
required: true
- type: textarea

View File

@ -1,10 +0,0 @@
---
name: Feature request
title: '[Feature Request]: '
about: Suggest an idea for RAGFlow
labels: ''
---
**Summary**
Description for this feature.

View File

@ -1,14 +1,20 @@
name: Feature request
name: "💞 Feature request"
description: Propose a feature request for RAGFlow.
title: "[Feature Request]: "
labels: [feature request]
labels: ["💞 feature"]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for the same feature request?
description: Please check if an issue already exists for the feature you request.
label: Self Checks
description: "Please check the following in order to be responded in time :)"
options:
- label: I have checked the existing issues.
- label: I have searched for existing issues [search for existing issues](https://github.com/infiniflow/ragflow/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: Non-english title submitions will be closed directly ( 非英文标题的提交将会被直接关闭 ) ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
required: true
- type: textarea
attributes:

View File

@ -1,8 +1,21 @@
name: Question
name: "🙋‍♀️ Question"
description: Ask questions on RAGFlow
title: "[Question]: "
labels: [question]
labels: ["🙋‍♀️ question"]
body:
- type: checkboxes
attributes:
label: Self Checks
description: "Please check the following in order to be responded in time :)"
options:
- label: I have searched for existing issues [search for existing issues](https://github.com/infiniflow/ragflow/issues), including closed ones.
required: true
- label: I confirm that I am using English to submit this report ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: Non-english title submitions will be closed directly ( 非英文标题的提交将会被直接关闭 ) ([Language Policy](https://github.com/infiniflow/ragflow/issues/5910)).
required: true
- label: "Please do not modify this template :) and fill in all the required fields."
required: true
- type: markdown
attributes:
value: |

118
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,118 @@
name: release
on:
schedule:
- cron: '0 13 * * *' # This schedule runs every 13:00:00Z(21:00:00+08:00)
# The "create tags" trigger is specifically focused on the creation of new tags, while the "push tags" trigger is activated when tags are pushed, including both new tag creations and updates to existing tags.
create:
tags:
- "v*.*.*" # normal release
- "nightly" # the only one mutable tag
# https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
release:
runs-on: [ "self-hosted", "overseas" ]
steps:
- name: Ensure workspace ownership
run: echo "chown -R $USER $GITHUB_WORKSPACE" && sudo chown -R $USER $GITHUB_WORKSPACE
# https://github.com/actions/checkout/blob/v3/README.md
- name: Check out code
uses: actions/checkout@v4
with:
token: ${{ secrets.MY_GITHUB_TOKEN }} # Use the secret as an environment variable
fetch-depth: 0
fetch-tags: true
- name: Prepare release body
run: |
if [[ $GITHUB_EVENT_NAME == 'create' ]]; then
RELEASE_TAG=${GITHUB_REF#refs/tags/}
if [[ $RELEASE_TAG == 'nightly' ]]; then
PRERELEASE=true
else
PRERELEASE=false
fi
echo "Workflow triggered by create tag: $RELEASE_TAG"
else
RELEASE_TAG=nightly
PRERELEASE=true
echo "Workflow triggered by schedule"
fi
echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV
echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV
RELEASE_DATETIME=$(date --rfc-3339=seconds)
echo Release $RELEASE_TAG created from $GITHUB_SHA at $RELEASE_DATETIME > release_body.md
- name: Move the existing mutable tag
# https://github.com/softprops/action-gh-release/issues/171
run: |
git fetch --tags
if [[ $GITHUB_EVENT_NAME == 'schedule' ]]; then
# Determine if a given tag exists and matches a specific Git commit.
# actions/checkout@v4 fetch-tags doesn't work when triggered by schedule
if [ "$(git rev-parse -q --verify "refs/tags/$RELEASE_TAG")" = "$GITHUB_SHA" ]; then
echo "mutable tag $RELEASE_TAG exists and matches $GITHUB_SHA"
else
git tag -f $RELEASE_TAG $GITHUB_SHA
git push -f origin $RELEASE_TAG:refs/tags/$RELEASE_TAG
echo "created/moved mutable tag $RELEASE_TAG to $GITHUB_SHA"
fi
fi
- name: Create or overwrite a release
# https://github.com/actions/upload-release-asset has been replaced by https://github.com/softprops/action-gh-release
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.MY_GITHUB_TOKEN }} # Use the secret as an environment variable
prerelease: ${{ env.PRERELEASE }}
tag_name: ${{ env.RELEASE_TAG }}
# The body field does not support environment variable substitution directly.
body_path: release_body.md
# https://github.com/marketplace/actions/docker-login
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: infiniflow
password: ${{ secrets.DOCKERHUB_TOKEN }}
# https://github.com/marketplace/actions/build-and-push-docker-images
- name: Build and push full image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: infiniflow/ragflow:${{ env.RELEASE_TAG }}
file: Dockerfile
platforms: linux/amd64
# https://github.com/marketplace/actions/build-and-push-docker-images
- name: Build and push slim image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: infiniflow/ragflow:${{ env.RELEASE_TAG }}-slim
file: Dockerfile
build-args: LIGHTEN=1
platforms: linux/amd64
- name: Build ragflow-sdk
if: startsWith(github.ref, 'refs/tags/v')
run: |
cd sdk/python && \
uv build
- name: Publish package distributions to PyPI
if: startsWith(github.ref, 'refs/tags/v')
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: sdk/python/dist/
password: ${{ secrets.PYPI_API_TOKEN }}
verbose: true

153
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,153 @@
name: tests
on:
push:
branches:
- 'main'
- '*.*.*'
paths-ignore:
- 'docs/**'
- '*.md'
- '*.mdx'
pull_request:
types: [ opened, synchronize, reopened, labeled ]
paths-ignore:
- 'docs/**'
- '*.md'
- '*.mdx'
# https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
ragflow_tests:
name: ragflow_tests
# https://docs.github.com/en/actions/using-jobs/using-conditions-to-control-job-execution
# https://github.com/orgs/community/discussions/26261
if: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'ci') }}
runs-on: [ "self-hosted", "debug" ]
steps:
# https://github.com/hmarr/debug-action
#- uses: hmarr/debug-action@v2
- name: Show who triggered this workflow
run: |
echo "Workflow triggered by ${{ github.event_name }}"
- name: Ensure workspace ownership
run: echo "chown -R $USER $GITHUB_WORKSPACE" && sudo chown -R $USER $GITHUB_WORKSPACE
# https://github.com/actions/checkout/issues/1781
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
# https://github.com/astral-sh/ruff-action
- name: Static check with Ruff
uses: astral-sh/ruff-action@v2
with:
version: ">=0.8.2"
args: "check"
- name: Build ragflow:nightly-slim
run: |
RUNNER_WORKSPACE_PREFIX=${RUNNER_WORKSPACE_PREFIX:-$HOME}
sudo docker pull ubuntu:22.04
sudo docker build --progress=plain --build-arg LIGHTEN=1 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
- name: Build ragflow:nightly
run: |
sudo docker build --progress=plain --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly .
- name: Start ragflow:nightly-slim
run: |
echo -e "\nRAGFLOW_IMAGE=infiniflow/ragflow:nightly-slim" >> docker/.env
sudo docker compose -f docker/docker-compose.yml up -d
- name: Stop ragflow:nightly-slim
if: always() # always run this step even if previous steps failed
run: |
sudo docker compose -f docker/docker-compose.yml down -v
- name: Start ragflow:nightly
run: |
echo -e "\nRAGFLOW_IMAGE=infiniflow/ragflow:nightly" >> docker/.env
sudo docker compose -f docker/docker-compose.yml up -d
- name: Run sdk tests against Elasticsearch
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_sdk_api && pytest -s --tb=short get_email.py t_dataset.py t_chat.py t_session.py t_document.py t_chunk.py
- name: Run frontend api tests against Elasticsearch
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_frontend_api && pytest -s --tb=short get_email.py test_dataset.py
- name: Run http api tests against Elasticsearch
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_http_api && pytest -s --tb=short -m "not slow"
- name: Stop ragflow:nightly
if: always() # always run this step even if previous steps failed
run: |
sudo docker compose -f docker/docker-compose.yml down -v
- name: Start ragflow:nightly
run: |
sudo DOC_ENGINE=infinity docker compose -f docker/docker-compose.yml up -d
- name: Run sdk tests against Infinity
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_sdk_api && pytest -s --tb=short get_email.py t_dataset.py t_chat.py t_session.py t_document.py t_chunk.py
- name: Run frontend api tests against Infinity
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_frontend_api && pytest -s --tb=short get_email.py test_dataset.py
- name: Run http api tests against Infinity
run: |
export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY=""
export HOST_ADDRESS=http://host.docker.internal:9380
until sudo docker exec ragflow-server curl -s --connect-timeout 5 ${HOST_ADDRESS} > /dev/null; do
echo "Waiting for service to be available..."
sleep 5
done
cd sdk/python && uv sync --python 3.10 --frozen && uv pip install . && source .venv/bin/activate && cd test/test_http_api && DOC_ENGINE=infinity pytest -s --tb=short -m "not slow"
- name: Stop ragflow:nightly
if: always() # always run this step even if previous steps failed
run: |
sudo DOC_ENGINE=infinity docker compose -f docker/docker-compose.yml down -v

8
.gitignore vendored
View File

@ -35,4 +35,10 @@ rag/res/deepdoc
sdk/python/ragflow.egg-info/
sdk/python/build/
sdk/python/dist/
sdk/python/ragflow_sdk.egg-info/
sdk/python/ragflow_sdk.egg-info/
huggingface.co/
nltk_data/
# Exclude hash-like temporary files like 9b5ad71b2ce5302211f9c61530b329a4922fc6a4
*[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*
.lh/

View File

@ -1,16 +1,10 @@
---
sidebar_position: 0
slug: /contribution_guidelines
---
# Contribution guidelines
Thanks for wanting to contribute to RAGFlow. This document offers guidlines and major considerations for submitting your contributions.
This document offers guidelines and major considerations for submitting your contributions to RAGFlow.
- To report a bug, file a [GitHub issue](https://github.com/infiniflow/ragflow/issues/new/choose) with us.
- For further questions, you can explore existing discussions or initiate a new one in [Discussions](https://github.com/orgs/infiniflow/discussions).
## What you can contribute
The list below mentions some contributions you can make, but it is not a complete list.
@ -27,7 +21,7 @@ The list below mentions some contributions you can make, but it is not a complet
### General workflow
1. Fork our GitHub repository.
2. Clone your fork to your local machine:
2. Clone your fork to your local machine:
`git clone git@github.com:<yourname>/ragflow.git`
3. Create a local branch:
`git checkout -b my-branch`
@ -39,14 +33,16 @@ The list below mentions some contributions you can make, but it is not a complet
### Before filing a PR
- Consider splitting a large PR into multiple smaller, standalone PRs to keep a traceable development history.
- Consider splitting a large PR into multiple smaller, standalone PRs to keep a traceable development history.
- Ensure that your PR addresses just one issue, or keep any unrelated changes small.
- Add test cases when contributing new features. They demonstrate that your code functions correctly and protect against potential issues from future changes.
### Describing your PR
### Describing your PR
- Ensure that your PR title is concise and clear, providing all the required information.
- Refer to a corresponding GitHub issue in your PR description if applicable.
- Refer to a corresponding GitHub issue in your PR description if applicable.
- Include sufficient design details for *breaking changes* or *API changes* in your description.
### Reviewing & merging a PR
- Ensure that your PR passes all Continuous Integration (CI) tests before merging it.
Ensure that your PR passes all Continuous Integration (CI) tests before merging it.

View File

@ -1,23 +1,211 @@
FROM infiniflow/ragflow-base:v2.0
USER root
# base stage
FROM ubuntu:22.04 AS base
USER root
SHELL ["/bin/bash", "-c"]
ARG NEED_MIRROR=0
ARG LIGHTEN=0
ENV LIGHTEN=${LIGHTEN}
WORKDIR /ragflow
ADD ./web ./web
RUN cd ./web && npm i --force && npm run build
# Copy models downloaded via download_deps.py
RUN mkdir -p /ragflow/rag/res/deepdoc /root/.ragflow
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/huggingface.co,target=/huggingface.co \
cp /huggingface.co/InfiniFlow/huqie/huqie.txt.trie /ragflow/rag/res/ && \
tar --exclude='.*' -cf - \
/huggingface.co/InfiniFlow/text_concat_xgb_v1.0 \
/huggingface.co/InfiniFlow/deepdoc \
| tar -xf - --strip-components=3 -C /ragflow/rag/res/deepdoc
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/huggingface.co,target=/huggingface.co \
if [ "$LIGHTEN" != "1" ]; then \
(tar -cf - \
/huggingface.co/BAAI/bge-large-zh-v1.5 \
/huggingface.co/maidalun1020/bce-embedding-base_v1 \
| tar -xf - --strip-components=2 -C /root/.ragflow) \
fi
ADD ./api ./api
ADD ./conf ./conf
ADD ./deepdoc ./deepdoc
ADD ./rag ./rag
ADD ./agent ./agent
ADD ./graphrag ./graphrag
# https://github.com/chrismattmann/tika-python
# This is the only way to run python-tika without internet access. Without this set, the default is to check the tika version and pull latest every time from Apache.
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/,target=/deps \
cp -r /deps/nltk_data /root/ && \
cp /deps/tika-server-standard-3.0.0.jar /deps/tika-server-standard-3.0.0.jar.md5 /ragflow/ && \
cp /deps/cl100k_base.tiktoken /ragflow/9b5ad71b2ce5302211f9c61530b329a4922fc6a4
ENV TIKA_SERVER_JAR="file:///ragflow/tika-server-standard-3.0.0.jar"
ENV DEBIAN_FRONTEND=noninteractive
# Setup apt
# Python package and implicit dependencies:
# opencv-python: libglib2.0-0 libglx-mesa0 libgl1
# aspose-slides: pkg-config libicu-dev libgdiplus libssl1.1_1.1.1f-1ubuntu2_amd64.deb
# python-pptx: default-jdk tika-server-standard-3.0.0.jar
# selenium: libatk-bridge2.0-0 chrome-linux64-121-0-6167-85
# Building C extensions: libpython3-dev libgtk-4-1 libnss3 xdg-utils libgbm-dev
RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
if [ "$NEED_MIRROR" == "1" ]; then \
sed -i 's|http://ports.ubuntu.com|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list; \
sed -i 's|http://archive.ubuntu.com|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list; \
fi; \
rm -f /etc/apt/apt.conf.d/docker-clean && \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache && \
chmod 1777 /tmp && \
apt update && \
apt --no-install-recommends install -y ca-certificates && \
apt update && \
apt install -y libglib2.0-0 libglx-mesa0 libgl1 && \
apt install -y pkg-config libicu-dev libgdiplus && \
apt install -y default-jdk && \
apt install -y libatk-bridge2.0-0 && \
apt install -y libpython3-dev libgtk-4-1 libnss3 xdg-utils libgbm-dev && \
apt install -y libjemalloc-dev && \
apt install -y python3-pip pipx nginx unzip curl wget git vim less
RUN if [ "$NEED_MIRROR" == "1" ]; then \
pip3 config set global.index-url https://mirrors.aliyun.com/pypi/simple && \
pip3 config set global.trusted-host mirrors.aliyun.com; \
mkdir -p /etc/uv && \
echo "[[index]]" > /etc/uv/uv.toml && \
echo 'url = "https://mirrors.aliyun.com/pypi/simple"' >> /etc/uv/uv.toml && \
echo "default = true" >> /etc/uv/uv.toml; \
fi; \
pipx install uv
ENV PYTHONDONTWRITEBYTECODE=1 DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV PATH=/root/.local/bin:$PATH
# nodejs 12.22 on Ubuntu 22.04 is too old
RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt purge -y nodejs npm cargo && \
apt autoremove -y && \
apt update && \
apt install -y nodejs
# A modern version of cargo is needed for the latest version of the Rust compiler.
RUN apt update && apt install -y curl build-essential \
&& if [ "$NEED_MIRROR" == "1" ]; then \
# Use TUNA mirrors for rustup/rust dist files
export RUSTUP_DIST_SERVER="https://mirrors.tuna.tsinghua.edu.cn/rustup"; \
export RUSTUP_UPDATE_ROOT="https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup"; \
echo "Using TUNA mirrors for Rustup."; \
fi; \
# Force curl to use HTTP/1.1
curl --proto '=https' --tlsv1.2 --http1.1 -sSf https://sh.rustup.rs | bash -s -- -y --profile minimal \
&& echo 'export PATH="/root/.cargo/bin:${PATH}"' >> /root/.bashrc
ENV PATH="/root/.cargo/bin:${PATH}"
RUN cargo --version && rustc --version
# Add msssql ODBC driver
# macOS ARM64 environment, install msodbcsql18.
# general x86_64 environment, install msodbcsql17.
RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list > /etc/apt/sources.list.d/mssql-release.list && \
apt update && \
arch="$(uname -m)"; \
if [ "$arch" = "arm64" ] || [ "$arch" = "aarch64" ]; then \
# ARM64 (macOS/Apple Silicon or Linux aarch64)
ACCEPT_EULA=Y apt install -y unixodbc-dev msodbcsql18; \
else \
# x86_64 or others
ACCEPT_EULA=Y apt install -y unixodbc-dev msodbcsql17; \
fi || \
{ echo "Failed to install ODBC driver"; exit 1; }
# Add dependencies of selenium
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chrome-linux64-121-0-6167-85,target=/chrome-linux64.zip \
unzip /chrome-linux64.zip && \
mv chrome-linux64 /opt/chrome && \
ln -s /opt/chrome/chrome /usr/local/bin/
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chromedriver-linux64-121-0-6167-85,target=/chromedriver-linux64.zip \
unzip -j /chromedriver-linux64.zip chromedriver-linux64/chromedriver && \
mv chromedriver /usr/local/bin/ && \
rm -f /usr/bin/google-chrome
# https://forum.aspose.com/t/aspose-slides-for-net-no-usable-version-of-libssl-found-with-linux-server/271344/13
# aspose-slides on linux/arm64 is unavailable
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/,target=/deps \
if [ "$(uname -m)" = "x86_64" ]; then \
dpkg -i /deps/libssl1.1_1.1.1f-1ubuntu2_amd64.deb; \
elif [ "$(uname -m)" = "aarch64" ]; then \
dpkg -i /deps/libssl1.1_1.1.1f-1ubuntu2_arm64.deb; \
fi
# builder stage
FROM base AS builder
USER root
WORKDIR /ragflow
# install dependencies from uv.lock file
COPY pyproject.toml uv.lock ./
# https://github.com/astral-sh/uv/issues/10462
# uv records index url into uv.lock but doesn't failover among multiple indexes
RUN --mount=type=cache,id=ragflow_uv,target=/root/.cache/uv,sharing=locked \
if [ "$NEED_MIRROR" == "1" ]; then \
sed -i 's|pypi.org|mirrors.aliyun.com/pypi|g' uv.lock; \
else \
sed -i 's|mirrors.aliyun.com/pypi|pypi.org|g' uv.lock; \
fi; \
if [ "$LIGHTEN" == "1" ]; then \
uv sync --python 3.10 --frozen; \
else \
uv sync --python 3.10 --frozen --all-extras; \
fi
COPY web web
COPY docs docs
RUN --mount=type=cache,id=ragflow_npm,target=/root/.npm,sharing=locked \
cd web && npm install && npm run build
COPY .git /ragflow/.git
RUN version_info=$(git describe --tags --match=v* --first-parent --always); \
if [ "$LIGHTEN" == "1" ]; then \
version_info="$version_info slim"; \
else \
version_info="$version_info full"; \
fi; \
echo "RAGFlow version: $version_info"; \
echo $version_info > /ragflow/VERSION
# production stage
FROM base AS production
USER root
WORKDIR /ragflow
# Copy Python environment and packages
ENV VIRTUAL_ENV=/ragflow/.venv
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
ENV PYTHONPATH=/ragflow/
ENV HF_ENDPOINT=https://hf-mirror.com
ADD docker/entrypoint.sh ./entrypoint.sh
ADD docker/.env ./
RUN chmod +x ./entrypoint.sh
COPY web web
COPY api api
COPY conf conf
COPY deepdoc deepdoc
COPY rag rag
COPY agent agent
COPY graphrag graphrag
COPY agentic_reasoning agentic_reasoning
COPY pyproject.toml uv.lock ./
COPY mcp mcp
ENTRYPOINT ["./entrypoint.sh"]
COPY docker/service_conf.yaml.template ./conf/service_conf.yaml.template
COPY docker/entrypoint.sh ./
RUN chmod +x ./entrypoint*.sh
# Copy compiled web pages
COPY --from=builder /ragflow/web/dist /ragflow/web/dist
COPY --from=builder /ragflow/VERSION /ragflow/VERSION
ENTRYPOINT ["./entrypoint.sh"]

View File

@ -1,34 +0,0 @@
FROM python:3.11
USER root
WORKDIR /ragflow
COPY requirements_arm.txt /ragflow/requirements.txt
RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ --default-timeout=1000 -r requirements.txt &&\
python -c "import nltk;nltk.download('punkt');nltk.download('wordnet')"
RUN apt-get update && \
apt-get install -y curl gnupg && \
rm -rf /var/lib/apt/lists/*
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y --fix-missing nodejs nginx ffmpeg libsm6 libxext6 libgl1
ADD ./web ./web
RUN cd ./web && npm i --force && npm run build
ADD ./api ./api
ADD ./conf ./conf
ADD ./deepdoc ./deepdoc
ADD ./rag ./rag
ADD ./agent ./agent
ADD ./graphrag ./graphrag
ENV PYTHONPATH=/ragflow/
ENV HF_ENDPOINT=https://hf-mirror.com
ADD docker/entrypoint.sh ./entrypoint.sh
ADD docker/.env ./
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

View File

@ -1,27 +0,0 @@
FROM infiniflow/ragflow-base:v2.0
USER root
WORKDIR /ragflow
## for cuda > 12.0
RUN pip uninstall -y onnxruntime-gpu
RUN pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
ADD ./web ./web
RUN cd ./web && npm i --force && npm run build
ADD ./api ./api
ADD ./conf ./conf
ADD ./deepdoc ./deepdoc
ADD ./rag ./rag
ADD ./agent ./agent
ADD ./graphrag ./graphrag
ENV PYTHONPATH=/ragflow/
ENV HF_ENDPOINT=https://hf-mirror.com
ADD docker/entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

10
Dockerfile.deps Normal file
View File

@ -0,0 +1,10 @@
# This builds an image that contains the resources needed by Dockerfile
#
FROM scratch
# Copy resources downloaded via download_deps.py
COPY chromedriver-linux64-121-0-6167-85 chrome-linux64-121-0-6167-85 cl100k_base.tiktoken libssl1.1_1.1.1f-1ubuntu2_amd64.deb libssl1.1_1.1.1f-1ubuntu2_arm64.deb tika-server-standard-3.0.0.jar tika-server-standard-3.0.0.jar.md5 libssl*.deb /
COPY nltk_data /nltk_data
COPY huggingface.co /huggingface.co

View File

@ -1,56 +0,0 @@
FROM ubuntu:22.04
USER root
WORKDIR /ragflow
RUN apt-get update && apt-get install -y wget curl build-essential libopenmpi-dev
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \
bash ~/miniconda.sh -b -p /root/miniconda3 && \
rm ~/miniconda.sh && ln -s /root/miniconda3/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
echo ". /root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc && \
echo "conda activate base" >> ~/.bashrc
ENV PATH /root/miniconda3/bin:$PATH
RUN conda create -y --name py11 python=3.11
ENV CONDA_DEFAULT_ENV py11
ENV CONDA_PREFIX /root/miniconda3/envs/py11
ENV PATH $CONDA_PREFIX/bin:$PATH
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get install -y nodejs
RUN apt-get install -y nginx
ADD ./web ./web
ADD ./api ./api
ADD ./conf ./conf
ADD ./deepdoc ./deepdoc
ADD ./rag ./rag
ADD ./requirements.txt ./requirements.txt
ADD ./agent ./agent
ADD ./graphrag ./graphrag
RUN apt install openmpi-bin openmpi-common libopenmpi-dev
ENV LD_LIBRARY_PATH /usr/lib/x86_64-linux-gnu/openmpi/lib:$LD_LIBRARY_PATH
RUN rm /root/miniconda3/envs/py11/compiler_compat/ld
RUN cd ./web && npm i --force && npm run build
RUN conda run -n py11 pip install -i https://mirrors.aliyun.com/pypi/simple/ -r ./requirements.txt
RUN apt-get update && \
apt-get install -y libglib2.0-0 libgl1-mesa-glx && \
rm -rf /var/lib/apt/lists/*
RUN conda run -n py11 pip install -i https://mirrors.aliyun.com/pypi/simple/ ollama
RUN conda run -n py11 python -m nltk.downloader punkt
RUN conda run -n py11 python -m nltk.downloader wordnet
ENV PYTHONPATH=/ragflow/
ENV HF_ENDPOINT=https://hf-mirror.com
ADD docker/entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]

View File

@ -26,6 +26,7 @@ RUN dnf install -y nginx
ADD ./web ./web
ADD ./api ./api
ADD ./docs ./docs
ADD ./conf ./conf
ADD ./deepdoc ./deepdoc
ADD ./rag ./rag
@ -37,7 +38,7 @@ RUN dnf install -y openmpi openmpi-devel python3-openmpi
ENV C_INCLUDE_PATH /usr/include/openmpi-x86_64:$C_INCLUDE_PATH
ENV LD_LIBRARY_PATH /usr/lib64/openmpi/lib:$LD_LIBRARY_PATH
RUN rm /root/miniconda3/envs/py11/compiler_compat/ld
RUN cd ./web && npm i --force && npm run build
RUN cd ./web && npm i && npm run build
RUN conda run -n py11 pip install $(grep -ivE "mpi4py" ./requirements.txt) # without mpi4py==3.1.5
RUN conda run -n py11 pip install redis
@ -52,6 +53,7 @@ RUN conda run -n py11 python -m nltk.downloader wordnet
ENV PYTHONPATH=/ragflow/
ENV HF_ENDPOINT=https://hf-mirror.com
COPY docker/service_conf.yaml.template ./conf/service_conf.yaml.template
ADD docker/entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh

303
README.md
View File

@ -7,34 +7,42 @@
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a>
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="follow on X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99"></a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.10.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.10.0"></a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Document</a> |
<a href="https://github.com/infiniflow/ragflow/issues/162">Roadmap</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/4XxujFgUN7">Discord</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
<details open>
<summary></b>📕 Table of Contents</b></summary>
<summary><b>📕 Table of Contents</b></summary>
- 💡 [What is RAGFlow?](#-what-is-ragflow)
- 🎮 [Demo](#-demo)
- 📌 [Latest Updates](#-latest-updates)
@ -42,8 +50,9 @@
- 🔎 [System Architecture](#-system-architecture)
- 🎬 [Get Started](#-get-started)
- 🔧 [Configurations](#-configurations)
- 🛠️ [Build from source](#-build-from-source)
- 🛠️ [Launch service from source](#-launch-service-from-source)
- 🔧 [Build a docker image without embedding models](#-build-a-docker-image-without-embedding-models)
- 🔧 [Build a docker image including embedding models](#-build-a-docker-image-including-embedding-models)
- 🔨 [Launch service from source for development](#-launch-service-from-source-for-development)
- 📚 [Documentation](#-documentation)
- 📜 [Roadmap](#-roadmap)
- 🏄 [Community](#-community)
@ -53,43 +62,44 @@
## 💡 What is RAGFlow?
[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.
[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.
## 🎮 Demo
Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/infiniflow/ragflow/assets/12318111/b083d173-dadc-4ea9-bdeb-180d7df514eb" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 Latest Updates
- 2025-03-19 Supports using a multi-modal model to make sense of images within PDF or DOCX files.
- 2025-02-28 Combined with Internet search (Tavily), supports reasoning like Deep Research for any LLMs.
- 2025-01-26 Optimizes knowledge graph extraction and application, offering various configuration options.
- 2024-12-18 Upgrades Document Layout Analysis model in DeepDoc.
- 2024-11-01 Adds keyword extraction and related question generation to the parsed chunks to improve the accuracy of retrieval.
- 2024-08-22 Support text to SQL statements through RAG.
- 2024-08-02 Supports GraphRAG inspired by [graphrag](https://github.com/microsoft/graphrag) and mind map.
- 2024-07-23 Supports audio file parsing.
- 2024-07-21 Supports more LLMs (LocalAI, OpenRouter, StepFun, and Nvidia).
## 🎉 Stay Tuned
- 2024-07-18 Adds more components (Wikipedia, PubMed, Baidu, and Duckduckgo) to the graph.
⭐️ Star our repository to stay up-to-date with exciting new features and improvements! Get instant notifications for new
releases! 🌟
- 2024-07-08 Supports workflow based on [Graph](./graph/README.md).
- 2024-06-27 Supports Markdown and Docx in the Q&A parsing method.
- 2024-06-27 Supports extracting images from Docx files.
- 2024-06-27 Supports extracting tables from Markdown files.
- 2024-06-06 Supports [Self-RAG](https://huggingface.co/papers/2310.11511), which is enabled by default in dialog settings.
- 2024-05-30 Integrates [BCE](https://github.com/netease-youdao/BCEmbedding) and [BGE](https://github.com/FlagOpen/FlagEmbedding) reranker models.
- 2024-05-23 Supports [RAPTOR](https://arxiv.org/html/2401.18059v1) for better text retrieval.
- 2024-05-15 Integrates OpenAI GPT-4o.
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 Key Features
### 🍭 **"Quality in, quality out"**
- [Deep document understanding](./deepdoc/README.md)-based knowledge extraction from unstructured data with complicated formats.
- [Deep document understanding](./deepdoc/README.md)-based knowledge extraction from unstructured data with complicated
formats.
- Finds "needle in a data haystack" of literally unlimited tokens.
### 🍱 **Template-based chunking**
@ -127,7 +137,8 @@ Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
- RAM >= 16 GB
- Disk >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
> If you have not installed Docker on your local machine (Windows, Mac, or Linux), see [Install Docker Engine](https://docs.docker.com/engine/install/).
> If you have not installed Docker on your local machine (Windows, Mac, or Linux),
> see [Install Docker Engine](https://docs.docker.com/engine/install/).
### 🚀 Start up the server
@ -146,7 +157,8 @@ Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
> $ sudo sysctl -w vm.max_map_count=262144
> ```
>
> This change will be reset after a system reboot. To ensure your change remains permanent, add or update the `vm.max_map_count` value in **/etc/sysctl.conf** accordingly:
> This change will be reset after a system reboot. To ensure your change remains permanent, add or update the
> `vm.max_map_count` value in **/etc/sysctl.conf** accordingly:
>
> ```bash
> vm.max_map_count=262144
@ -158,18 +170,29 @@ Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
$ git clone https://github.com/infiniflow/ragflow.git
```
3. Build the pre-built Docker images and start up the server:
3. Start up the server using the pre-built Docker images:
> Running the following commands automatically downloads the *dev* version RAGFlow Docker image. To download and run a specified Docker version, update `RAGFLOW_VERSION` in **docker/.env** to the intended version, for example `RAGFLOW_VERSION=v0.10.0`, before running the following commands.
> [!CAUTION]
> 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.
> The command below downloads the `v0.18.0-slim` edition of the RAGFlow Docker image. See the following table for descriptions of different RAGFlow editions. To download a RAGFlow edition different from `v0.18.0-slim`, update the `RAGFLOW_IMAGE` variable accordingly in **docker/.env** before using `docker compose` to start the server. For example: set `RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0` for the full edition `v0.18.0`.
```bash
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
```
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
> The core image is about 9 GB in size and may take a while to load.
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
|-------------------|-----------------|-----------------------|--------------------------|
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
4. Check the server status after having the server up and running:
@ -180,172 +203,172 @@ Try our demo at [https://demo.ragflow.io](https://demo.ragflow.io).
_The following output confirms a successful launch of the system:_
```bash
____ ______ __
/ __ \ ____ _ ____ _ / ____// /____ _ __
/ /_/ // __ `// __ `// /_ / // __ \| | /| / /
/ _, _// /_/ // /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_| \__,_/ \__, //_/ /_/ \____/ |__/|__/
/____/
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9380
* Running on http://x.x.x.x:9380
INFO:werkzeug:Press CTRL+C to quit
```
> If you skip this confirmation step and directly log in to RAGFlow, your browser may prompt a `network anomaly` error because, at that moment, your RAGFlow may not be fully initialized.
> If you skip this confirmation step and directly log in to RAGFlow, your browser may prompt a `network anormal`
> error because, at that moment, your RAGFlow may not be fully initialized.
5. In your web browser, enter the IP address of your server and log in to RAGFlow.
> With the default settings, you only need to enter `http://IP_OF_YOUR_MACHINE` (**sans** port number) as the default HTTP serving port `80` can be omitted when using the default configurations.
6. In [service_conf.yaml](./docker/service_conf.yaml), select the desired LLM factory in `user_default_llm` and update the `API_KEY` field with the corresponding API key.
> With the default settings, you only need to enter `http://IP_OF_YOUR_MACHINE` (**sans** port number) as the default
> HTTP serving port `80` can be omitted when using the default configurations.
6. In [service_conf.yaml.template](./docker/service_conf.yaml.template), select the desired LLM factory in `user_default_llm` and update
the `API_KEY` field with the corresponding API key.
> See [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup) for more information.
_The show is now on!_
_The show is on!_
## 🔧 Configurations
When it comes to system configurations, you will need to manage the following files:
- [.env](./docker/.env): Keeps the fundamental setups for the system, such as `SVR_HTTP_PORT`, `MYSQL_PASSWORD`, and `MINIO_PASSWORD`.
- [service_conf.yaml](./docker/service_conf.yaml): Configures the back-end services.
- [.env](./docker/.env): Keeps the fundamental setups for the system, such as `SVR_HTTP_PORT`, `MYSQL_PASSWORD`, and
`MINIO_PASSWORD`.
- [service_conf.yaml.template](./docker/service_conf.yaml.template): Configures the back-end services. The environment variables in this file will be automatically populated when the Docker container starts. Any environment variables set within the Docker container will be available for use, allowing you to customize service behavior based on the deployment environment.
- [docker-compose.yml](./docker/docker-compose.yml): The system relies on [docker-compose.yml](./docker/docker-compose.yml) to start up.
You must ensure that changes to the [.env](./docker/.env) file are in line with what are in the [service_conf.yaml](./docker/service_conf.yaml) file.
> The [./docker/README](./docker/README.md) file provides a detailed description of the environment settings and service
> configurations which can be used as `${ENV_VARS}` in the [service_conf.yaml.template](./docker/service_conf.yaml.template) file.
> The [./docker/README](./docker/README.md) file provides a detailed description of the environment settings and service configurations, and you are REQUIRED to ensure that all environment settings listed in the [./docker/README](./docker/README.md) file are aligned with the corresponding configurations in the [service_conf.yaml](./docker/service_conf.yaml) file.
To update the default HTTP serving port (80), go to [docker-compose.yml](./docker/docker-compose.yml) and change `80:80`
to `<YOUR_SERVING_PORT>:80`.
To update the default HTTP serving port (80), go to [docker-compose.yml](./docker/docker-compose.yml) and change `80:80` to `<YOUR_SERVING_PORT>:80`.
Updates to the above configurations require a reboot of all containers to take effect:
> Updates to all system configurations require a system reboot to take effect:
>
> ```bash
> $ docker-compose up -d
> $ docker compose -f docker-compose.yml up -d
> ```
## 🛠️ Build from source
### Switch doc engine from Elasticsearch to Infinity
To build the Docker images from source:
RAGFlow uses Elasticsearch by default for storing full text and vectors. To switch to [Infinity](https://github.com/infiniflow/infinity/), follow these steps:
1. Stop all running containers:
```bash
$ docker compose -f docker/docker-compose.yml down -v
```
> [!WARNING]
> `-v` will delete the docker container volumes, and the existing data will be cleared.
2. Set `DOC_ENGINE` in **docker/.env** to `infinity`.
3. Start the containers:
```bash
$ docker compose -f docker-compose.yml up -d
```
> [!WARNING]
> Switching to Infinity on a Linux/arm64 machine is not yet officially supported.
## 🔧 Build a Docker image without embedding models
This image is approximately 2 GB in size and relies on external LLM and embedding services.
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
$ docker build -t infiniflow/ragflow:dev .
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🛠️ Launch service from source
## 🔧 Build a Docker image including embedding models
To launch the service from source:
This image is approximately 9 GB in size. As it includes embedding models, it relies on external LLM services only.
1. Clone the repository:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly .
```
## 🔨 Launch service from source for development
1. Install uv, or skip this step if it is already installed:
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
pipx install uv
```
2. Create a virtual environment, ensuring that Anaconda or Miniconda is installed:
2. Clone the source code and install Python dependencies:
```bash
$ conda create -n ragflow python=3.11.0
$ conda activate ragflow
$ pip install -r requirements.txt
```
```bash
# If your CUDA version is higher than 12.0, run the following additional commands:
$ pip uninstall -y onnxruntime-gpu
$ pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
3. Copy the entry script and configure environment variables:
3. Launch the dependent services (MinIO, Elasticsearch, Redis, and MySQL) using Docker Compose:
```bash
# Get the Python path:
$ which python
# Get the ragflow project path:
$ pwd
```
```bash
$ cp docker/entrypoint.sh .
$ vi entrypoint.sh
docker compose -f docker/docker-compose-base.yml up -d
```
Add the following line to `/etc/hosts` to resolve all hosts specified in **docker/.env** to `127.0.0.1`:
```
127.0.0.1 es01 infinity mysql minio redis
```
4. If you cannot access HuggingFace, set the `HF_ENDPOINT` environment variable to use a mirror site:
```bash
# Adjust configurations according to your actual situation (the following two export commands are newly added):
# - Assign the result of `which python` to `PY`.
# - Assign the result of `pwd` to `PYTHONPATH`.
# - Comment out `LD_LIBRARY_PATH`, if it is configured.
# - Optional: Add Hugging Face mirror.
PY=${PY}
export PYTHONPATH=${PYTHONPATH}
export HF_ENDPOINT=https://hf-mirror.com
```
4. Launch the third-party services (MinIO, Elasticsearch, Redis, and MySQL):
5. Launch backend service:
```bash
$ cd docker
$ docker compose -f docker-compose-base.yml up -d
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
5. Check the configuration files, ensuring that:
- The settings in **docker/.env** match those in **conf/service_conf.yaml**.
- The IP addresses and ports for related services in **service_conf.yaml** match the local machine IP and ports exposed by the container.
6. Launch the RAGFlow backend service:
6. Install frontend dependencies:
```bash
cd web
npm install
```
7. Launch frontend service:
```bash
$ chmod +x ./entrypoint.sh
$ bash ./entrypoint.sh
npm run dev
```
7. Launch the frontend service:
_The following output confirms a successful launch of the system:_
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ vim .umirc.ts
# Update proxy.target to http://127.0.0.1:9380
$ npm run dev
```
8. Deploy the frontend service:
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ umi build
$ mkdir -p /ragflow/web
$ cp -r dist /ragflow/web
$ apt install nginx -y
$ cp ../docker/nginx/proxy.conf /etc/nginx
$ cp ../docker/nginx/nginx.conf /etc/nginx
$ cp ../docker/nginx/ragflow.conf /etc/nginx/conf.d
$ systemctl start nginx
```
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
## 📚 Documentation
- [Quickstart](https://ragflow.io/docs/dev/)
- [User guide](https://ragflow.io/docs/dev/category/user-guides)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQ](https://ragflow.io/docs/dev/faq)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 Roadmap
See the [RAGFlow Roadmap 2024](https://github.com/infiniflow/ragflow/issues/162)
See the [RAGFlow Roadmap 2025](https://github.com/infiniflow/ragflow/issues/4214)
## 🏄 Community
- [Discord](https://discord.gg/4XxujFgUN7)
- [Discord](https://discord.gg/NjYzJD3GM3)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 Contributing
RAGFlow flourishes via open-source collaboration. In this spirit, we embrace diverse contributions from the community. If you would like to be a part, review our [Contribution Guidelines](./docs/references/CONTRIBUTING.md) first.
RAGFlow flourishes via open-source collaboration. In this spirit, we embrace diverse contributions from the community.
If you would like to be a part, review our [Contribution Guidelines](./CONTRIBUTING.md) first.

340
README_id.md Normal file
View File

@ -0,0 +1,340 @@
<div align="center">
<a href="https://demo.ragflow.io/">
<img src="web/src/assets/logo-with-text.png" width="520" alt="Logo ragflow">
</a>
</div>
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="Ikuti di X (Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Lencana Daring" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/Lisensi-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="Lisensi">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Dokumentasi</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Peta Jalan</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
<details open>
<summary><b>📕 Daftar Isi </b> </summary>
- 💡 [Apa Itu RAGFlow?](#-apa-itu-ragflow)
- 🎮 [Demo](#-demo)
- 📌 [Pembaruan Terbaru](#-pembaruan-terbaru)
- 🌟 [Fitur Utama](#-fitur-utama)
- 🔎 [Arsitektur Sistem](#-arsitektur-sistem)
- 🎬 [Mulai](#-mulai)
- 🔧 [Konfigurasi](#-konfigurasi)
- 🔧 [Membangun Image Docker tanpa Model Embedding](#-membangun-image-docker-tanpa-model-embedding)
- 🔧 [Membangun Image Docker dengan Model Embedding](#-membangun-image-docker-dengan-model-embedding)
- 🔨 [Meluncurkan aplikasi dari Sumber untuk Pengembangan](#-meluncurkan-aplikasi-dari-sumber-untuk-pengembangan)
- 📚 [Dokumentasi](#-dokumentasi)
- 📜 [Peta Jalan](#-peta-jalan)
- 🏄 [Komunitas](#-komunitas)
- 🙌 [Kontribusi](#-kontribusi)
</details>
## 💡 Apa Itu RAGFlow?
[RAGFlow](https://ragflow.io/) adalah mesin RAG (Retrieval-Augmented Generation) open-source berbasis pemahaman dokumen yang mendalam. Platform ini menyediakan alur kerja RAG yang efisien untuk bisnis dengan berbagai skala, menggabungkan LLM (Large Language Models) untuk menyediakan kemampuan tanya-jawab yang benar dan didukung oleh referensi dari data terstruktur kompleks.
## 🎮 Demo
Coba demo kami di [https://demo.ragflow.io](https://demo.ragflow.io).
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 Pembaruan Terbaru
- 2025-03-19 Mendukung penggunaan model multi-modal untuk memahami gambar di dalam file PDF atau DOCX.
- 2025-02-28 dikombinasikan dengan pencarian Internet (TAVILY), mendukung penelitian mendalam untuk LLM apa pun.
- 2025-01-26 Optimalkan ekstraksi dan penerapan grafik pengetahuan dan sediakan berbagai opsi konfigurasi.
- 2024-12-18 Meningkatkan model Analisis Tata Letak Dokumen di DeepDoc.
- 2024-11-01 Penambahan ekstraksi kata kunci dan pembuatan pertanyaan terkait untuk meningkatkan akurasi pengambilan.
- 2024-08-22 Dukungan untuk teks ke pernyataan SQL melalui RAG.
## 🎉 Tetap Terkini
⭐️ Star repositori kami untuk tetap mendapat informasi tentang fitur baru dan peningkatan menarik! 🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 Fitur Utama
### 🍭 **"Kualitas Masuk, Kualitas Keluar"**
- Ekstraksi pengetahuan berbasis pemahaman dokumen mendalam dari data tidak terstruktur dengan format yang rumit.
- Menemukan "jarum di tumpukan data" dengan token yang hampir tidak terbatas.
### 🍱 **Pemotongan Berbasis Template**
- Cerdas dan dapat dijelaskan.
- Banyak pilihan template yang tersedia.
### 🌱 **Referensi yang Didasarkan pada Data untuk Mengurangi Hallusinasi**
- Visualisasi pemotongan teks memungkinkan intervensi manusia.
- Tampilan cepat referensi kunci dan referensi yang dapat dilacak untuk mendukung jawaban yang didasarkan pada fakta.
### 🍔 **Kompatibilitas dengan Sumber Data Heterogen**
- Mendukung Word, slide, excel, txt, gambar, salinan hasil scan, data terstruktur, halaman web, dan banyak lagi.
### 🛀 **Alur Kerja RAG yang Otomatis dan Mudah**
- Orkestrasi RAG yang ramping untuk bisnis kecil dan besar.
- LLM yang dapat dikonfigurasi serta model embedding.
- Peringkat ulang berpasangan dengan beberapa pengambilan ulang.
- API intuitif untuk integrasi yang mudah dengan bisnis.
## 🔎 Arsitektur Sistem
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/12318111/d6ac5664-c237-4200-a7c2-a4a00691b485" width="1000"/>
</div>
## 🎬 Mulai
### 📝 Prasyarat
- CPU >= 4 inti
- RAM >= 16 GB
- Disk >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
### 🚀 Menjalankan Server
1. Pastikan `vm.max_map_count` >= 262144:
> Untuk memeriksa nilai `vm.max_map_count`:
>
> ```bash
> $ sysctl vm.max_map_count
> ```
>
> Jika nilainya kurang dari 262144, setel ulang `vm.max_map_count` ke setidaknya 262144:
>
> ```bash
> # Dalam contoh ini, kita atur menjadi 262144:
> $ sudo sysctl -w vm.max_map_count=262144
> ```
>
> Perubahan ini akan hilang setelah sistem direboot. Untuk membuat perubahan ini permanen, tambahkan atau perbarui nilai
> `vm.max_map_count` di **/etc/sysctl.conf**:
>
> ```bash
> vm.max_map_count=262144
> ```
2. Clone repositori:
```bash
$ git clone https://github.com/infiniflow/ragflow.git
```
3. Bangun image Docker pre-built dan jalankan server:
> [!CAUTION]
> 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).
> Perintah di bawah ini mengunduh edisi v0.18.0-slim dari gambar Docker RAGFlow. Silakan merujuk ke tabel berikut untuk deskripsi berbagai edisi RAGFlow. Untuk mengunduh edisi RAGFlow yang berbeda dari v0.18.0-slim, perbarui variabel RAGFLOW_IMAGE di docker/.env sebelum menggunakan docker compose untuk memulai server. Misalnya, atur RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0 untuk edisi lengkap v0.18.0.
```bash
$ cd ragflow/docker
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
| ----------------- | --------------- | --------------------- | ------------------------ |
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
1. Periksa status server setelah server aktif dan berjalan:
```bash
$ docker logs -f ragflow-server
```
_Output berikut menandakan bahwa sistem berhasil diluncurkan:_
```bash
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
```
> Jika Anda melewatkan langkah ini dan langsung login ke RAGFlow, browser Anda mungkin menampilkan error `network anormal`
> karena RAGFlow mungkin belum sepenuhnya siap.
2. Buka browser web Anda, masukkan alamat IP server Anda, dan login ke RAGFlow.
> Dengan pengaturan default, Anda hanya perlu memasukkan `http://IP_DEVICE_ANDA` (**tanpa** nomor port) karena
> port HTTP default `80` bisa dihilangkan saat menggunakan konfigurasi default.
3. Dalam [service_conf.yaml.template](./docker/service_conf.yaml.template), pilih LLM factory yang diinginkan di `user_default_llm` dan perbarui
bidang `API_KEY` dengan kunci API yang sesuai.
> Lihat [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup) untuk informasi lebih lanjut.
_Sistem telah siap digunakan!_
## 🔧 Konfigurasi
Untuk konfigurasi sistem, Anda perlu mengelola file-file berikut:
- [.env](./docker/.env): Menyimpan pengaturan dasar sistem, seperti `SVR_HTTP_PORT`, `MYSQL_PASSWORD`, dan
`MINIO_PASSWORD`.
- [service_conf.yaml.template](./docker/service_conf.yaml.template): Mengonfigurasi aplikasi backend.
- [docker-compose.yml](./docker/docker-compose.yml): Sistem ini bergantung pada [docker-compose.yml](./docker/docker-compose.yml) untuk memulai.
Untuk memperbarui port HTTP default (80), buka [docker-compose.yml](./docker/docker-compose.yml) dan ubah `80:80`
menjadi `<YOUR_SERVING_PORT>:80`.
Pembaruan konfigurasi ini memerlukan reboot semua kontainer agar efektif:
> ```bash
> $ docker compose -f docker-compose.yml up -d
> ```
## 🔧 Membangun Docker Image tanpa Model Embedding
Image ini berukuran sekitar 2 GB dan bergantung pada aplikasi LLM eksternal dan embedding.
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🔧 Membangun Docker Image Termasuk Model Embedding
Image ini berukuran sekitar 9 GB. Karena sudah termasuk model embedding, ia hanya bergantung pada aplikasi LLM eksternal.
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly .
```
## 🔨 Menjalankan Aplikasi dari untuk Pengembangan
1. Instal uv, atau lewati langkah ini jika sudah terinstal:
```bash
pipx install uv
```
2. Clone kode sumber dan instal dependensi Python:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
3. Jalankan aplikasi yang diperlukan (MinIO, Elasticsearch, Redis, dan MySQL) menggunakan Docker Compose:
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
Tambahkan baris berikut ke `/etc/hosts` untuk memetakan semua host yang ditentukan di **conf/service_conf.yaml** ke `127.0.0.1`:
```
127.0.0.1 es01 infinity mysql minio redis
```
4. Jika Anda tidak dapat mengakses HuggingFace, atur variabel lingkungan `HF_ENDPOINT` untuk menggunakan situs mirror:
```bash
export HF_ENDPOINT=https://hf-mirror.com
```
5. Jalankan aplikasi backend:
```bash
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
6. Instal dependensi frontend:
```bash
cd web
npm install
```
7. Jalankan aplikasi frontend:
```bash
npm run dev
```
_Output berikut menandakan bahwa sistem berhasil diluncurkan:_
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
## 📚 Dokumentasi
- [Quickstart](https://ragflow.io/docs/dev/)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 Roadmap
Lihat [Roadmap RAGFlow 2025](https://github.com/infiniflow/ragflow/issues/4214)
## 🏄 Komunitas
- [Discord](https://discord.gg/NjYzJD3GM3)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 Kontribusi
RAGFlow berkembang melalui kolaborasi open-source. Dalam semangat ini, kami menerima kontribusi dari komunitas.
Jika Anda ingin berpartisipasi, tinjau terlebih dahulu [Panduan Kontribusi](./CONTRIBUTING.md).

View File

@ -7,29 +7,36 @@
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a>
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="follow on X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99"></a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.10.0-brightgreen"
alt="docker pull infiniflow/ragflow:v0.10.0"></a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Document</a> |
<a href="https://github.com/infiniflow/ragflow/issues/162">Roadmap</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/4XxujFgUN7">Discord</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
@ -40,27 +47,28 @@
## 🎮 Demo
デモをお試しください:[https://demo.ragflow.io](https://demo.ragflow.io)。
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/infiniflow/ragflow/assets/12318111/b083d173-dadc-4ea9-bdeb-180d7df514eb" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 最新情報
- 2025-03-19 PDFまたはDOCXファイル内の画像を理解するために、多モーダルモデルを使用することをサポートします。
- 2025-02-28 インターネット検索 (TAVILY) と組み合わせて、あらゆる LLM の詳細な調査をサポートします。
- 2025-01-26 ナレッジ グラフの抽出と適用を最適化し、さまざまな構成オプションを提供します。
- 2024-12-18 DeepDoc のドキュメント レイアウト分析モデルをアップグレードします。
- 2024-11-01 再現の精度を向上させるために、解析されたチャンクにキーワード抽出と関連質問の生成を追加しました。
- 2024-08-22 RAG を介して SQL ステートメントへのテキストをサポートします。
- 2024-08-02 [graphrag](https://github.com/microsoft/graphrag) からインスピレーションを得た GraphRAG とマインド マップをサポートします。
- 2024-07-23 音声ファイルの解析をサポートしました。
- 2024-07-21 より多くの LLM サプライヤー (LocalAI/OpenRouter/StepFun/Nvidia) をサポートします。
- 2024-07-18 グラフにコンポーネント(Wikipedia/PubMed/Baidu/Duckduckgo)を追加しました。
- 2024-07-08 [Graph](./graph/README.md) ベースのワークフローをサポート
- 2024-06-27 Q&A解析方式はMarkdownファイルとDocxファイルをサポートしています。
- 2024-06-27 Docxファイルからの画像の抽出をサポートします。
- 2024-06-27 Markdownファイルからテーブルを抽出することをサポートします。
- 2024-06-06 会話設定でデフォルトでチェックされている [Self-RAG](https://huggingface.co/papers/2310.11511) をサポートします。
- 2024-05-30 [BCE](https://github.com/netease-youdao/BCEmbedding) 、[BGE](https://github.com/FlagOpen/FlagEmbedding) reranker を統合。
- 2024-05-23 より良いテキスト検索のために [RAPTOR](https://arxiv.org/html/2401.18059v1) をサポート。
- 2024-05-15 OpenAI GPT-4oを統合しました。
## 🎉 続きを楽しみに
⭐️ リポジトリをスター登録して、エキサイティングな新機能やアップデートを最新の状態に保ちましょう!すべての新しいリリースに関する即時通知を受け取れます! 🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 主な特徴
@ -137,17 +145,29 @@
3. ビルド済みの Docker イメージをビルドし、サーバーを起動する:
> [!CAUTION]
> 現在、公式に提供されているすべての Docker イメージは x86 アーキテクチャ向けにビルドされており、ARM64 用の Docker イメージは提供されていません。
> ARM64 アーキテクチャのオペレーティングシステムを使用している場合は、[このドキュメント](https://ragflow.io/docs/dev/build_docker_image)を参照して Docker イメージを自分でビルドしてください。
> 以下のコマンドは、RAGFlow Docker イメージの v0.18.0-slim エディションをダウンロードします。異なる RAGFlow エディションの説明については、以下の表を参照してください。v0.18.0-slim とは異なるエディションをダウンロードするには、docker/.env ファイルの RAGFLOW_IMAGE 変数を適宜更新し、docker compose を使用してサーバーを起動してください。例えば、完全版 v0.18.0 をダウンロードするには、RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0 と設定します。
```bash
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
> 上記のコマンドを実行すると、RAGFlowの開発版dockerイメージが自動的にダウンロードされます。 特定のバージョンのDockerイメージをダウンロードして実行したい場合は、docker/.envファイルのRAGFLOW_VERSION変数を見つけて、対応するバージョンに変更してください。 例えば、RAGFLOW_VERSION=v0.10.0として、上記のコマンドを実行してください。
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
| ----------------- | --------------- | --------------------- | ------------------------ |
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
> コアイメージのサイズは約 9 GB で、ロードに時間がかかる場合があります。
4. サーバーを立ち上げた後、サーバーの状態を確認する:
1. サーバーを立ち上げた後、サーバーの状態を確認する:
```bash
$ docker logs -f ragflow-server
@ -156,23 +176,20 @@
_以下の出力は、システムが正常に起動したことを確認するものです:_
```bash
____ ______ __
/ __ \ ____ _ ____ _ / ____// /____ _ __
/ /_/ // __ `// __ `// /_ / // __ \| | /| / /
/ _, _// /_/ // /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_| \__,_/ \__, //_/ /_/ \____/ |__/|__/
/____/
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9380
* Running on http://x.x.x.x:9380
INFO:werkzeug:Press CTRL+C to quit
```
> もし確認ステップをスキップして直接 RAGFlow にログインした場合、その時点で RAGFlow が完全に初期化されていない可能性があるため、ブラウザーがネットワーク異常エラーを表示するかもしれません。
5. ウェブブラウザで、プロンプトに従ってサーバーの IP アドレスを入力し、RAGFlow にログインします。
2. ウェブブラウザで、プロンプトに従ってサーバーの IP アドレスを入力し、RAGFlow にログインします。
> デフォルトの設定を使用する場合、デフォルトの HTTP サービングポート `80` は省略できるので、与えられたシナリオでは、`http://IP_OF_YOUR_MACHINE`(ポート番号は省略)だけを入力すればよい。
6. [service_conf.yaml](./docker/service_conf.yaml) で、`user_default_llm` で希望の LLM ファクトリを選択し、`API_KEY` フィールドを対応する API キーで更新する。
3. [service_conf.yaml.template](./docker/service_conf.yaml.template) で、`user_default_llm` で希望の LLM ファクトリを選択し、`API_KEY` フィールドを対応する API キーで更新する。
> 詳しくは [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup) を参照してください。
@ -183,111 +200,136 @@
システムコンフィグに関しては、以下のファイルを管理する必要がある:
- [.env](./docker/.env): `SVR_HTTP_PORT`、`MYSQL_PASSWORD`、`MINIO_PASSWORD` などのシステムの基本設定を保持する。
- [service_conf.yaml](./docker/service_conf.yaml): バックエンドのサービスを設定します。
- [service_conf.yaml.template](./docker/service_conf.yaml.template): バックエンドのサービスを設定します。
- [docker-compose.yml](./docker/docker-compose.yml): システムの起動は [docker-compose.yml](./docker/docker-compose.yml) に依存している。
[.env](./docker/.env) ファイルの変更が [service_conf.yaml](./docker/service_conf.yaml) ファイルの内容と一致していることを確認する必要があります。
[.env](./docker/.env) ファイルの変更が [service_conf.yaml.template](./docker/service_conf.yaml.template) ファイルの内容と一致していることを確認する必要があります。
> [./docker/README](./docker/README.md) ファイルは環境設定とサービスコンフィグの詳細な説明を提供し、[./docker/README](./docker/README.md) ファイルに記載されている全ての環境設定が [service_conf.yaml](./docker/service_conf.yaml) ファイルの対応するコンフィグと一致していることを確認することが義務付けられています。
> [./docker/README](./docker/README.md) ファイル ./docker/README には、service_conf.yaml.template ファイルで ${ENV_VARS} として使用できる環境設定とサービス構成の詳細な説明が含まれています。
デフォルトの HTTP サービングポート(80)を更新するには、[docker-compose.yml](./docker/docker-compose.yml) にアクセスして、`80:80` を `<YOUR_SERVING_PORT>:80` に変更します。
> すべてのシステム設定のアップデートを有効にするには、システムの再起動が必要です:
>
> ```bash
> $ docker-compose up -d
> $ docker compose -f docker-compose.yml up -d
> ```
## 🛠️ ソースからビルドする
### Elasticsearch から Infinity にドキュメントエンジンを切り替えます
ソースからDockerイメージをビルドするには:
RAGFlow はデフォルトで Elasticsearch を使用して全文とベクトルを保存します。Infinityに切り替えhttps://github.com/infiniflow/infinity/)、次の手順に従います。
1. 実行中のすべてのコンテナを停止するには:
```bash
$ docker compose -f docker/docker-compose.yml down -v
```
Note: `-v` は docker コンテナのボリュームを削除し、既存のデータをクリアします。
2. **docker/.env** の「DOC \_ ENGINE」を「infinity」に設定します。
3. 起動コンテナ:
```bash
$ docker compose -f docker-compose.yml up -d
```
> [!WARNING]
> Linux/arm64 マシンでの Infinity への切り替えは正式にサポートされていません。
## 🔧 ソースコードで Docker イメージを作成(埋め込みモデルなし)
この Docker イメージのサイズは約 1GB で、外部の大モデルと埋め込みサービスに依存しています。
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
$ docker build -t infiniflow/ragflow:v0.10.0 .
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🛠️ ソースコードからサービスを起動する方法
## 🔧 ソースコードをコンパイルした Docker イメージ(埋め込みモデルを含む)
ソースコードからサービスを起動する場合は、以下の手順に従ってください:
1. リポジトリをクローンします
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
```
2. 仮想環境を作成しますAnacondaまたはMinicondaがインストールされていることを確認してください
```bash
$ conda create -n ragflow python=3.11.0
$ conda activate ragflow
$ pip install -r requirements.txt
```
CUDAのバージョンが12.0以上の場合、以下の追加コマンドを実行してください:
```bash
$ pip uninstall -y onnxruntime-gpu
$ pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
```
3. エントリースクリプトをコピーし、環境変数を設定します
```bash
$ cp docker/entrypoint.sh .
$ vi entrypoint.sh
```
以下のコマンドで Python のパスとragflowプロジェクトのパスを取得します
```bash
$ which python
$ pwd
```
`which python` の出力を `PY` の値として、`pwd` の出力を `PYTHONPATH` の値として設定します。
`LD_LIBRARY_PATH` が既に設定されている場合は、コメントアウトできます。
この Docker のサイズは約 9GB で、埋め込みモデルを含むため、外部の大モデルサービスのみが必要です。
```bash
# 実際の状況に応じて設定を調整してください。以下の二つの export は新たに追加された設定です
PY=${PY}
export PYTHONPATH=${PYTHONPATH}
# オプションHugging Face ミラーを追加
export HF_ENDPOINT=https://hf-mirror.com
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly .
```
4. 基本サービスを起動しま
```bash
$ cd docker
$ docker compose -f docker-compose-base.yml up -d
```
## 🔨 ソースコードからサービスを起動する方法
5. 設定ファイルを確認します
**docker/.env** 内の設定が**conf/service_conf.yaml**内の設定と一致していることを確認してください。**service_conf.yaml**内の関連サービスのIPアドレスとポートは、ローカルマシンのIPアドレスとコンテナが公開するポートに変更する必要があります。
1. uv をインストールする。すでにインストールされている場合は、このステップをスキップしてください:
6. サービスを起動します
```bash
$ chmod +x ./entrypoint.sh
$ bash ./entrypoint.sh
```
```bash
pipx install uv
```
2. ソースコードをクローンし、Python の依存関係をインストールする:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
3. Docker Compose を使用して依存サービスMinIO、Elasticsearch、Redis、MySQLを起動する:
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
`/etc/hosts` に以下の行を追加して、**conf/service_conf.yaml** に指定されたすべてのホストを `127.0.0.1` に解決します:
```
127.0.0.1 es01 infinity mysql minio redis
```
4. HuggingFace にアクセスできない場合は、`HF_ENDPOINT` 環境変数を設定してミラーサイトを使用してください:
```bash
export HF_ENDPOINT=https://hf-mirror.com
```
5. バックエンドサービスを起動する:
```bash
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
6. フロントエンドの依存関係をインストールする:
```bash
cd web
npm install
```
7. フロントエンドサービスを起動する:
```bash
npm run dev
```
_以下の画面で、システムが正常に起動したことを示します:_
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
## 📚 ドキュメンテーション
- [Quickstart](https://ragflow.io/docs/dev/)
- [User guide](https://ragflow.io/docs/dev/category/user-guides)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQ](https://ragflow.io/docs/dev/faq)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 ロードマップ
[RAGFlow ロードマップ 2024](https://github.com/infiniflow/ragflow/issues/162) を参照
[RAGFlow ロードマップ 2025](https://github.com/infiniflow/ragflow/issues/4214) を参照
## 🏄 コミュニティ
- [Discord](https://discord.gg/4XxujFgUN7)
- [Discord](https://discord.gg/NjYzJD3GM3)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 コントリビュート
RAGFlow はオープンソースのコラボレーションによって発展してきました。この精神に基づき、私たちはコミュニティからの多様なコントリビュートを受け入れています。 参加を希望される方は、まず [コントリビューションガイド](./docs/references/CONTRIBUTING.md)をご覧ください。
RAGFlow はオープンソースのコラボレーションによって発展してきました。この精神に基づき、私たちはコミュニティからの多様なコントリビュートを受け入れています。 参加を希望される方は、まず [コントリビューションガイド](./CONTRIBUTING.md)をご覧ください。

View File

@ -7,101 +7,97 @@
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="follow on X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99"></a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.10.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.10.0"></a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Document</a> |
<a href="https://github.com/infiniflow/ragflow/issues/162">Roadmap</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/4XxujFgUN7">Discord</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
## 💡 RAGFlow란?
[RAGFlow](https://ragflow.io/)는 심층 문서 이해에 기반한 오픈소스 RAG (Retrieval-Augmented Generation) 엔진입니다. 이 엔진은 대규모 언어 모델(LLM)과 결합하여 정확한 질문 응답 기능을 제공하며, 다양한 복잡한 형식의 데이터에서 신뢰할 수 있는 출처를 바탕으로 한 인용을 통해 이를 뒷받침합니다. RAGFlow는 규모에 상관없이 모든 기업에 최적화된 RAG 워크플로우를 제공합니다.
## 🎮 데모
데모를 [https://demo.ragflow.io](https://demo.ragflow.io)에서 실행해 보세요.
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/infiniflow/ragflow/assets/12318111/b083d173-dadc-4ea9-bdeb-180d7df514eb" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 업데이트
- 2025-03-19 PDF 또는 DOCX 파일 내의 이미지를 이해하기 위해 다중 모드 모델을 사용하는 것을 지원합니다.
- 2025-02-28 인터넷 검색(TAVILY)과 결합되어 모든 LLM에 대한 심층 연구를 지원합니다.
- 2025-01-26 지식 그래프 추출 및 적용을 최적화하고 다양한 구성 옵션을 제공합니다.
- 2024-12-18 DeepDoc의 문서 레이아웃 분석 모델 업그레이드.
- 2024-11-01 파싱된 청크에 키워드 추출 및 관련 질문 생성을 추가하여 재현율을 향상시킵니다.
- 2024-08-22 RAG를 통해 SQL 문에 텍스트를 지원합니다.
- 2024-08-02: [graphrag](https://github.com/microsoft/graphrag)와 마인드맵에서 영감을 받은 GraphRAG를 지원합니다.
- 2024-07-23: 오디오 파일 분석을 지원합니다.
## 🎉 계속 지켜봐 주세요
- 2024-07-21: 더 많은 LLMs(LocalAI, OpenRouter, StepFun, Nvidia)를 지원합니다.
- 2024-07-18: 그래프에 더 많은 구성요소(Wikipedia, PubMed, Baidu, Duckduckgo)를 추가합니다.
- 2024-07-08: [Graph](./graph/README.md)를 기반으로 한 워크플로우를 지원합니다.
- 2024-06-27: Q&A 분석 방법에서 Markdown과 Docx를 지원합니다.
- 2024-06-27: Docx 파일에서 이미지 추출을 지원합니다.
- 2024-06-27: Markdown 파일에서 표 추출을 지원합니다.
- 2024-06-06: 대화 설정에서 기본으로 [Self-RAG](https://huggingface.co/papers/2310.11511)를 지원합니다.
- 2024-05-30: [BCE](https://github.com/netease-youdao/BCEmbedding) 및 [BGE](https://github.com/FlagOpen/FlagEmbedding) reranker 모델을 통합합니다.
- 2024-05-23: 더 나은 텍스트 검색을 위해 [RAPTOR](https://arxiv.org/html/2401.18059v1)를 지원합니다.
- 2024-05-15: OpenAI GPT-4o를 통합합니다.
⭐️우리의 저장소를 즐겨찾기에 등록하여 흥미로운 새로운 기능과 업데이트를 최신 상태로 유지하세요! 모든 새로운 릴리스에 대한 즉시 알림을 받으세요! 🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 주요 기능
### 🍭 **"Quality in, quality out"**
- [심층 문서 이해](./deepdoc/README.md)를 기반으로 복잡한 형식의 비정형 데이터에서 지식을 추출합니다.
- 문자 그대로 무한한 토큰에서 "데이터 속의 바늘"을 찾아냅니다.
### 🍱 **템플릿 기반의 chunking**
- 똑똑하고 설명 가능한 방식.
- 다양한 템플릿 옵션을 제공합니다.
### 🌱 **할루시네이션을 줄인 신뢰할 수 있는 인용**
- 텍스트 청킹을 시각화하여 사용자가 개입할 수 있도록 합니다.
- 중요한 참고 자료와 추적 가능한 인용을 빠르게 확인하여 신뢰할 수 있는 답변을 지원합니다.
### 🍔 **다른 종류의 데이터 소스와의 호환성**
- 워드, 슬라이드, 엑셀, 텍스트 파일, 이미지, 스캔본, 구조화된 데이터, 웹 페이지 등을 지원합니다.
### 🛀 **자동화되고 손쉬운 RAG 워크플로우**
- 개인 및 대규모 비즈니스에 맞춘 효율적인 RAG 오케스트레이션.
- 구성 가능한 LLM 및 임베딩 모델.
- 다중 검색과 결합된 re-ranking.
- 비즈니스와 원활하게 통합할 수 있는 직관적인 API.
## 🔎 시스템 아키텍처
<div align="center" style="margin-top:20px;margin-bottom:20px;">
@ -109,17 +105,19 @@
</div>
## 🎬 시작하기
### 📝 사전 준비 사항
- CPU >= 4 cores
- RAM >= 16 GB
- Disk >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
> 로컬 머신(Windows, Mac, Linux)에 Docker가 설치되지 않은 경우, [Docker 엔진 설치]((https://docs.docker.com/engine/install/))를 참조하세요.
> 로컬 머신(Windows, Mac, Linux)에 Docker가 설치되지 않은 경우, [Docker 엔진 설치](<(https://docs.docker.com/engine/install/)>)를 참조하세요.
### 🚀 서버 시작하기
1. `vm.max_map_count`가 262144 이상인지 확인하세요:
> `vm.max_map_count`의 값을 아래 명령어를 통해 확인하세요:
>
> ```bash
@ -147,17 +145,29 @@
3. 미리 빌드된 Docker 이미지를 생성하고 서버를 시작하세요:
> 다음 명령어를 실행하면 *dev* 버전의 RAGFlow Docker 이미지가 자동으로 다운로드됩니다. 특정 Docker 버전을 다운로드하고 실행하려면, **docker/.env** 파일에서 `RAGFLOW_VERSION`을 원하는 버전으로 업데이트한 후, 예를 들어 `RAGFLOW_VERSION=v0.10.0`로 업데이트 한 뒤, 다음 명령어를 실행하세요.
> [!CAUTION]
> 모든 Docker 이미지는 x86 플랫폼을 위해 빌드되었습니다. 우리는 현재 ARM64 플랫폼을 위한 Docker 이미지를 제공하지 않습니다.
> ARM64 플랫폼을 사용 중이라면, [시스템과 호환되는 Docker 이미지를 빌드하려면 이 가이드를 사용해 주세요](https://ragflow.io/docs/dev/build_docker_image).
> 아래 명령어는 RAGFlow Docker 이미지의 v0.18.0-slim 버전을 다운로드합니다. 다양한 RAGFlow 버전에 대한 설명은 다음 표를 참조하십시오. v0.18.0-slim과 다른 RAGFlow 버전을 다운로드하려면, docker/.env 파일에서 RAGFLOW_IMAGE 변수를 적절히 업데이트한 후 docker compose를 사용하여 서버를 시작하십시오. 예를 들어, 전체 버전인 v0.18.0을 다운로드하려면 RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0로 설정합니다.
```bash
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
> 기본 이미지는 약 9GB 크기이며 로드하는 데 시간이 걸릴 수 있습니다.
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
| ----------------- | --------------- | --------------------- | ------------------------ |
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
4. 서버가 시작된 후 서버 상태를 확인하세요:
1. 서버가 시작된 후 서버 상태를 확인하세요:
```bash
$ docker logs -f ragflow-server
@ -166,23 +176,21 @@
_다음 출력 결과로 시스템이 성공적으로 시작되었음을 확인합니다:_
```bash
____ ______ __
/ __ \ ____ _ ____ _ / ____// /____ _ __
/ /_/ // __ `// __ `// /_ / // __ \| | /| / /
/ _, _// /_/ // /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_| \__,_/ \__, //_/ /_/ \____/ |__/|__/
/____/
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9380
* Running on http://x.x.x.x:9380
INFO:werkzeug:Press CTRL+C to quit
```
> 만약 확인 단계를 건너뛰고 바로 RAGFlow에 로그인하면, RAGFlow가 완전히 초기화되지 않았기 때문에 브라우저에서 `network anomaly` 오류가 발생할 수 있습니다.
5. 웹 브라우저에 서버의 IP 주소를 입력하고 RAGFlow에 로그인하세요.
> 만약 확인 단계를 건너뛰고 바로 RAGFlow에 로그인하면, RAGFlow가 완전히 초기화되지 않았기 때문에 브라우저에서 `network anormal` 오류가 발생할 수 있습니다.
2. 웹 브라우저에 서버의 IP 주소를 입력하고 RAGFlow에 로그인하세요.
> 기본 설정을 사용할 경우, `http://IP_OF_YOUR_MACHINE`만 입력하면 됩니다 (포트 번호는 제외). 기본 HTTP 서비스 포트 `80`은 기본 구성으로 사용할 때 생략할 수 있습니다.
6. [service_conf.yaml](./docker/service_conf.yaml) 파일에서 원하는 LLM 팩토리를 `user_default_llm`에 선택하고, `API_KEY` 필드를 해당 API 키로 업데이트하세요.
3. [service_conf.yaml.template](./docker/service_conf.yaml.template) 파일에서 원하는 LLM 팩토리를 `user_default_llm`에 선택하고, `API_KEY` 필드를 해당 API 키로 업데이트하세요.
> 자세한 내용은 [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup)를 참조하세요.
_이제 쇼가 시작됩니다!_
@ -192,143 +200,135 @@
시스템 설정과 관련하여 다음 파일들을 관리해야 합니다:
- [.env](./docker/.env): `SVR_HTTP_PORT`, `MYSQL_PASSWORD`, `MINIO_PASSWORD`와 같은 시스템의 기본 설정을 포함합니다.
- [service_conf.yaml](./docker/service_conf.yaml): 백엔드 서비스를 구성합니다.
- [service_conf.yaml.template](./docker/service_conf.yaml.template): 백엔드 서비스를 구성합니다.
- [docker-compose.yml](./docker/docker-compose.yml): 시스템은 [docker-compose.yml](./docker/docker-compose.yml)을 사용하여 시작됩니다.
[.env](./docker/.env) 파일의 변경 사항이 [service_conf.yaml](./docker/service_conf.yaml) 파일의 내용과 일치하도록 해야 합니다.
[.env](./docker/.env) 파일의 변경 사항이 [service_conf.yaml.template](./docker/service_conf.yaml.template) 파일의 내용과 일치하도록 해야 합니다.
> [./docker/README](./docker/README.md) 파일에는 환경 설정과 서비스 구성에 대한 자세한 설명이 있으며, [./docker/README](./docker/README.md) 파일에 나열된 모든 환경 설정이 [service_conf.yaml](./docker/service_conf.yaml) 파일의 해당 구성과 일치하도록 해야 합니다.
> [./docker/README](./docker/README.md) 파일 ./docker/README은 service_conf.yaml.template 파일에서 ${ENV_VARS}로 사용할 수 있는 환경 설정과 서비스 구성에 대한 자세한 설명을 제공합니다.
기본 HTTP 서비스 포트(80)를 업데이트하려면 [docker-compose.yml](./docker/docker-compose.yml) 파일에서 `80:80`을 `<YOUR_SERVING_PORT>:80`으로 변경하세요.
> 모든 시스템 구성 업데이트는 적용되기 위해 시스템 재부팅이 필요합니다.
>
> ```bash
> $ docker-compose up -d
> $ docker compose -f docker-compose.yml up -d
> ```
## 🛠️ 소스에서 빌드하기
### Elasticsearch 에서 Infinity 로 문서 엔진 전환
Docker 이미지를 소스에서 빌드하려면:
RAGFlow 는 기본적으로 Elasticsearch 를 사용하여 전체 텍스트 및 벡터를 저장합니다. [Infinity]로 전환(https://github.com/infiniflow/infinity/), 다음 절차를 따르십시오.
1. 실행 중인 모든 컨테이너를 중지합니다.
```bash
$docker compose-f docker/docker-compose.yml down -v
```
Note: `-v` 는 docker 컨테이너의 볼륨을 삭제하고 기존 데이터를 지우며, 이 작업은 컨테이너를 중지하는 것과 동일합니다.
2. **docker/.env**의 "DOC_ENGINE" 을 "infinity" 로 설정합니다.
3. 컨테이너 부팅:
```bash
$docker compose-f docker/docker-compose.yml up -d
```
> [!WARNING]
> Linux/arm64 시스템에서 Infinity로 전환하는 것은 공식적으로 지원되지 않습니다.
## 🔧 소스 코드로 Docker 이미지를 컴파일합니다(임베딩 모델 포함하지 않음)
이 Docker 이미지의 크기는 약 1GB이며, 외부 대형 모델과 임베딩 서비스에 의존합니다.
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
$ docker build -t infiniflow/ragflow:dev .
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🔧 소스 코드로 Docker 이미지를 컴파일합니다(임베딩 모델 포함)
## 🛠️ 소스에서 서비스 시작하기
이 Docker의 크기는 약 9GB이며, 이미 임베딩 모델을 포함하고 있으므로 외부 대형 모델 서비스에만 의존하면 됩니다.
서비스를 소스에서 시작하려면:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly .
```
1. 레포지토리를 클론하세요:
## 🔨 소스 코드로 서비스를 시작합니다.
1. uv를 설치하거나 이미 설치된 경우 이 단계를 건너뜁니다:
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
pipx install uv
```
2. 가상 환경을 생성하고, Anaconda 또는 Miniconda가 설치되어 있는지 확인하세요:
```bash
$ conda create -n ragflow python=3.11.0
$ conda activate ragflow
$ pip install -r requirements.txt
```
```bash
# CUDA 버전이 12.0보다 높은 경우, 다음 명령어를 추가로 실행하세요:
$ pip uninstall -y onnxruntime-gpu
$ pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
```
3. 진입 스크립트를 복사하고 환경 변수를 설정하세요:
```bash
# 파이썬 경로를 받아옵니다:
$ which python
# RAGFlow 프로젝트 경로를 받아옵니다:
$ pwd
```
```bash
$ cp docker/entrypoint.sh .
$ vi entrypoint.sh
```
2. 소스 코드를 클론하고 Python 의존성을 설치합니다:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
3. Docker Compose를 사용하여 의존 서비스(MinIO, Elasticsearch, Redis 및 MySQL)를 시작합니다:
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
`/etc/hosts` 에 다음 줄을 추가하여 **conf/service_conf.yaml** 에 지정된 모든 호스트를 `127.0.0.1` 로 해결합니다:
```
127.0.0.1 es01 infinity mysql minio redis
```
4. HuggingFace에 접근할 수 없는 경우, `HF_ENDPOINT` 환경 변수를 설정하여 미러 사이트를 사용하세요:
```bash
# 실제 상황에 맞게 설정 조정하기 (다음 두 개의 export 명령어는 새로 추가되었습니다):
# - `which python`의 결과를 `PY`에 할당합니다.
# - `pwd`의 결과를 `PYTHONPATH`에 할당합니다.
# - `LD_LIBRARY_PATH`가 설정되어 있는 경우 주석 처리합니다.
# - 선택 사항: Hugging Face 미러 추가.
PY=${PY}
export PYTHONPATH=${PYTHONPATH}
export HF_ENDPOINT=https://hf-mirror.com
```
4. 다른 서비스(MinIO, Elasticsearch, Redis, MySQL)를 시작하세요:
```bash
$ cd docker
$ docker compose -f docker-compose-base.yml up -d
```
5. 설정 파일을 확인하여 다음 사항을 확인하세요:
- **docker/.env**의 설정이 **conf/service_conf.yaml**의 설정과 일치하는지 확인합니다.
- **service_conf.yaml**의 관련 서비스에 대한 IP 주소와 포트가 로컬 머신의 IP 주소와 컨테이너에서 노출된 포트와 일치하는지 확인합니다.
6. RAGFlow 백엔드 서비스를 시작합니다:
5. 백엔드 서비스를 시작합니다:
```bash
$ chmod +x ./entrypoint.sh
$ bash ./entrypoint.sh
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
6. 프론트엔드 의존성을 설치합니다:
```bash
cd web
npm install
```
7. 프론트엔드 서비스를 시작합니다:
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ vim .umirc.ts
# proxy.target을 http://127.0.0.1:9380로 업데이트합니다.
$ npm run dev
npm run dev
```
8. 프론트엔드 서비스를 배포합니다:
_다음 인터페이스는 시스템이 성공적으로 시작되었음을 나타냅니다:_
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ umi build
$ mkdir -p /ragflow/web
$ cp -r dist /ragflow/web
$ apt install nginx -y
$ cp ../docker/nginx/proxy.conf /etc/nginx
$ cp ../docker/nginx/nginx.conf /etc/nginx
$ cp ../docker/nginx/ragflow.conf /etc/nginx/conf.d
$ systemctl start nginx
```
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
## 📚 문서
- [Quickstart](https://ragflow.io/docs/dev/)
- [User guide](https://ragflow.io/docs/dev/category/user-guides)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQ](https://ragflow.io/docs/dev/faq)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 로드맵
[RAGFlow 로드맵 2024](https://github.com/infiniflow/ragflow/issues/162)을 확인하세요.
[RAGFlow 로드맵 2025](https://github.com/infiniflow/ragflow/issues/4214)을 확인하세요.
## 🏄 커뮤니티
- [Discord](https://discord.gg/4XxujFgUN7)
- [Discord](https://discord.gg/NjYzJD3GM3)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 컨트리뷰션
RAGFlow는 오픈소스 협업을 통해 발전합니다. 이러한 정신을 바탕으로, 우리는 커뮤니티의 다양한 기여를 환영합니다. 참여하고 싶으시다면, 먼저 [가이드라인](./docs/references/CONTRIBUTING.md)을 검토해 주세요.
RAGFlow는 오픈소스 협업을 통해 발전합니다. 이러한 정신을 바탕으로, 우리는 커뮤니티의 다양한 기여를 환영합니다. 참여하고 싶으시다면, 먼저 [가이드라인](./CONTRIBUTING.md)을 검토해 주세요.

361
README_pt_br.md Normal file
View File

@ -0,0 +1,361 @@
<div align="center">
<a href="https://demo.ragflow.io/">
<img src="web/src/assets/logo-with-text.png" width="520" alt="ragflow logo">
</a>
</div>
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="seguir no X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Badge Estático" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="licença">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Documentação</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
<details open>
<summary><b>📕 Índice</b></summary>
- 💡 [O que é o RAGFlow?](#-o-que-é-o-ragflow)
- 🎮 [Demo](#-demo)
- 📌 [Últimas Atualizações](#-últimas-atualizações)
- 🌟 [Principais Funcionalidades](#-principais-funcionalidades)
- 🔎 [Arquitetura do Sistema](#-arquitetura-do-sistema)
- 🎬 [Primeiros Passos](#-primeiros-passos)
- 🔧 [Configurações](#-configurações)
- 🔧 [Construir uma imagem docker sem incorporar modelos](#-construir-uma-imagem-docker-sem-incorporar-modelos)
- 🔧 [Construir uma imagem docker incluindo modelos](#-construir-uma-imagem-docker-incluindo-modelos)
- 🔨 [Lançar serviço a partir do código-fonte para desenvolvimento](#-lançar-serviço-a-partir-do-código-fonte-para-desenvolvimento)
- 📚 [Documentação](#-documentação)
- 📜 [Roadmap](#-roadmap)
- 🏄 [Comunidade](#-comunidade)
- 🙌 [Contribuindo](#-contribuindo)
</details>
## 💡 O que é o RAGFlow?
[RAGFlow](https://ragflow.io/) é um mecanismo RAG (Geração Aumentada por Recuperação) de código aberto baseado em entendimento profundo de documentos. Ele oferece um fluxo de trabalho RAG simplificado para empresas de qualquer porte, combinando LLMs (Modelos de Linguagem de Grande Escala) para fornecer capacidades de perguntas e respostas verídicas, respaldadas por citações bem fundamentadas de diversos dados complexos formatados.
## 🎮 Demo
Experimente nossa demo em [https://demo.ragflow.io](https://demo.ragflow.io).
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 Últimas Atualizações
- 19-03-2025 Suporta o uso de um modelo multi-modal para entender imagens dentro de arquivos PDF ou DOCX.
- 28-02-2025 combinado com a pesquisa na Internet (T AVI LY), suporta pesquisas profundas para qualquer LLM.
- 26-01-2025 Otimize a extração e aplicação de gráficos de conhecimento e forneça uma variedade de opções de configuração.
- 18-12-2024 Atualiza o modelo de Análise de Layout de Documentos no DeepDoc.
- 01-11-2024 Adiciona extração de palavras-chave e geração de perguntas relacionadas aos blocos analisados para melhorar a precisão da recuperação.
- 22-08-2024 Suporta conversão de texto para comandos SQL via RAG.
## 🎉 Fique Ligado
⭐️ Dê uma estrela no nosso repositório para se manter atualizado com novas funcionalidades e melhorias empolgantes! Receba notificações instantâneas sobre novos lançamentos! 🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 Principais Funcionalidades
### 🍭 **"Qualidade entra, qualidade sai"**
- Extração de conhecimento baseada em [entendimento profundo de documentos](./deepdoc/README.md) a partir de dados não estruturados com formatos complicados.
- Encontra a "agulha no palheiro de dados" de literalmente tokens ilimitados.
### 🍱 **Fragmentação baseada em templates**
- Inteligente e explicável.
- Muitas opções de templates para escolher.
### 🌱 **Citações fundamentadas com menos alucinações**
- Visualização da fragmentação de texto para permitir intervenção humana.
- Visualização rápida das referências chave e citações rastreáveis para apoiar respostas fundamentadas.
### 🍔 **Compatibilidade com fontes de dados heterogêneas**
- Suporta Word, apresentações, excel, txt, imagens, cópias digitalizadas, dados estruturados, páginas da web e mais.
### 🛀 **Fluxo de trabalho RAG automatizado e sem esforço**
- Orquestração RAG simplificada voltada tanto para negócios pessoais quanto grandes empresas.
- Modelos LLM e de incorporação configuráveis.
- Múltiplas recuperações emparelhadas com reclassificação fundida.
- APIs intuitivas para integração sem problemas com os negócios.
## 🔎 Arquitetura do Sistema
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/12318111/d6ac5664-c237-4200-a7c2-a4a00691b485" width="1000"/>
</div>
## 🎬 Primeiros Passos
### 📝 Pré-requisitos
- CPU >= 4 núcleos
- RAM >= 16 GB
- Disco >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
> Se você não instalou o Docker na sua máquina local (Windows, Mac ou Linux), veja [Instalar Docker Engine](https://docs.docker.com/engine/install/).
### 🚀 Iniciar o servidor
1. Certifique-se de que `vm.max_map_count` >= 262144:
> Para verificar o valor de `vm.max_map_count`:
>
> ```bash
> $ sysctl vm.max_map_count
> ```
>
> Se necessário, redefina `vm.max_map_count` para um valor de pelo menos 262144:
>
> ```bash
> # Neste caso, defina para 262144:
> $ sudo sysctl -w vm.max_map_count=262144
> ```
>
> Essa mudança será resetada após a reinicialização do sistema. Para garantir que a alteração permaneça permanente, adicione ou atualize o valor de `vm.max_map_count` em **/etc/sysctl.conf**:
>
> ```bash
> vm.max_map_count=262144
> ```
2. Clone o repositório:
```bash
$ git clone https://github.com/infiniflow/ragflow.git
```
3. Inicie o servidor usando as imagens Docker pré-compiladas:
> [!CAUTION]
> 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.
> O comando abaixo baixa a edição `v0.18.0-slim` 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.18.0-slim`, atualize a variável `RAGFLOW_IMAGE` conforme necessário no **docker/.env** antes de usar `docker compose` para iniciar o servidor. Por exemplo: defina `RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0` para a edição completa `v0.18.0`.
```bash
$ cd ragflow/docker
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
| Tag da imagem RAGFlow | Tamanho da imagem (GB) | Possui modelos de incorporação? | Estável? |
| --------------------- | ---------------------- | ------------------------------- | ------------------------ |
| v0.18.0 | ~9 | :heavy_check_mark: | Lançamento estável |
| v0.18.0-slim | ~2 | ❌ | Lançamento estável |
| nightly | ~9 | :heavy_check_mark: | _Instável_ build noturno |
| nightly-slim | ~2 | ❌ | _Instável_ build noturno |
4. Verifique o status do servidor após tê-lo iniciado:
```bash
$ docker logs -f ragflow-server
```
_O seguinte resultado confirma o lançamento bem-sucedido do sistema:_
```bash
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Rodando em todos os endereços (0.0.0.0)
```
> Se você pular essa etapa de confirmação e acessar diretamente o RAGFlow, seu navegador pode exibir um erro `network anormal`, pois, nesse momento, seu RAGFlow pode não estar totalmente inicializado.
5. No seu navegador, insira o endereço IP do seu servidor e faça login no RAGFlow.
> Com as configurações padrão, você só precisa digitar `http://IP_DO_SEU_MÁQUINA` (**sem** o número da porta), pois a porta HTTP padrão `80` pode ser omitida ao usar as configurações padrão.
6. Em [service_conf.yaml.template](./docker/service_conf.yaml.template), selecione a fábrica LLM desejada em `user_default_llm` e atualize o campo `API_KEY` com a chave de API correspondente.
> Consulte [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup) para mais informações.
_O show está no ar!_
## 🔧 Configurações
Quando se trata de configurações do sistema, você precisará gerenciar os seguintes arquivos:
- [.env](./docker/.env): Contém as configurações fundamentais para o sistema, como `SVR_HTTP_PORT`, `MYSQL_PASSWORD` e `MINIO_PASSWORD`.
- [service_conf.yaml.template](./docker/service_conf.yaml.template): Configura os serviços de back-end. As variáveis de ambiente neste arquivo serão automaticamente preenchidas quando o contêiner Docker for iniciado. Quaisquer variáveis de ambiente definidas dentro do contêiner Docker estarão disponíveis para uso, permitindo personalizar o comportamento do serviço com base no ambiente de implantação.
- [docker-compose.yml](./docker/docker-compose.yml): O sistema depende do [docker-compose.yml](./docker/docker-compose.yml) para iniciar.
> O arquivo [./docker/README](./docker/README.md) fornece uma descrição detalhada das configurações do ambiente e dos serviços, que podem ser usadas como `${ENV_VARS}` no arquivo [service_conf.yaml.template](./docker/service_conf.yaml.template).
Para atualizar a porta HTTP de serviço padrão (80), vá até [docker-compose.yml](./docker/docker-compose.yml) e altere `80:80` para `<SUA_PORTA_DE_SERVIÇO>:80`.
Atualizações nas configurações acima exigem um reinício de todos os contêineres para que tenham efeito:
> ```bash
> $ docker compose -f docker-compose.yml up -d
> ```
### Mudar o mecanismo de documentos de Elasticsearch para Infinity
O RAGFlow usa o Elasticsearch por padrão para armazenar texto completo e vetores. Para mudar para o [Infinity](https://github.com/infiniflow/infinity/), siga estas etapas:
1. Pare todos os contêineres em execução:
```bash
$ docker compose -f docker/docker-compose.yml down -v
```
Note: `-v` irá deletar os volumes do contêiner, e os dados existentes serão apagados.
2. Defina `DOC_ENGINE` no **docker/.env** para `infinity`.
3. Inicie os contêineres:
```bash
$ docker compose -f docker-compose.yml up -d
```
> [!ATENÇÃO]
> A mudança para o Infinity em uma máquina Linux/arm64 ainda não é oficialmente suportada.
## 🔧 Criar uma imagem Docker sem modelos de incorporação
Esta imagem tem cerca de 2 GB de tamanho e depende de serviços externos de LLM e incorporação.
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🔧 Criar uma imagem Docker incluindo modelos de incorporação
Esta imagem tem cerca de 9 GB de tamanho. Como inclui modelos de incorporação, depende apenas de serviços externos de LLM.
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly .
```
## 🔨 Lançar o serviço a partir do código-fonte para desenvolvimento
1. Instale o `uv`, ou pule esta etapa se ele já estiver instalado:
```bash
pipx install uv
```
2. Clone o código-fonte e instale as dependências Python:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # instala os módulos Python dependentes do RAGFlow
```
3. Inicie os serviços dependentes (MinIO, Elasticsearch, Redis e MySQL) usando Docker Compose:
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
Adicione a seguinte linha ao arquivo `/etc/hosts` para resolver todos os hosts especificados em **docker/.env** para `127.0.0.1`:
```
127.0.0.1 es01 infinity mysql minio redis
```
4. Se não conseguir acessar o HuggingFace, defina a variável de ambiente `HF_ENDPOINT` para usar um site espelho:
```bash
export HF_ENDPOINT=https://hf-mirror.com
```
5. Lance o serviço de back-end:
```bash
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
6. Instale as dependências do front-end:
```bash
cd web
npm install
```
7. Lance o serviço de front-end:
```bash
npm run dev
```
_O seguinte resultado confirma o lançamento bem-sucedido do sistema:_
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
## 📚 Documentação
- [Quickstart](https://ragflow.io/docs/dev/)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 Roadmap
Veja o [RAGFlow Roadmap 2025](https://github.com/infiniflow/ragflow/issues/4214)
## 🏄 Comunidade
- [Discord](https://discord.gg/NjYzJD3GM3)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 Contribuindo
O RAGFlow prospera por meio da colaboração de código aberto. Com esse espírito, abraçamos contribuições diversas da comunidade.
Se você deseja fazer parte, primeiro revise nossas [Diretrizes de Contribuição](./CONTRIBUTING.md).

361
README_tzh.md Normal file
View File

@ -0,0 +1,361 @@
<div align="center">
<a href="https://demo.ragflow.io/">
<img src="web/src/assets/logo-with-text.png" width="350" alt="ragflow logo">
</a>
</div>
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="follow on X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Document</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
## 💡 RAGFlow 是什麼?
[RAGFlow](https://ragflow.io/) 是一款基於深度文件理解所建構的開源 RAGRetrieval-Augmented Generation引擎。 RAGFlow 可以為各種規模的企業及個人提供一套精簡的 RAG 工作流程結合大語言模型LLM針對用戶各類不同的複雜格式數據提供可靠的問答以及有理有據的引用。
## 🎮 Demo 試用
請登入網址 [https://demo.ragflow.io](https://demo.ragflow.io) 試用 demo。
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 近期更新
- 2025-03-19 PDF和DOCX中的圖支持用多模態大模型去解析得到描述.
- 2025-02-28 結合網路搜尋Tavily對於任意大模型實現類似 Deep Research 的推理功能.
- 2025-01-26 最佳化知識圖譜的擷取與應用,提供了多種配置選擇。
- 2024-12-18 升級了 DeepDoc 的文檔佈局分析模型。
- 2024-11-01 對解析後的 chunk 加入關鍵字抽取和相關問題產生以提高回想的準確度。
- 2024-08-22 支援用 RAG 技術實現從自然語言到 SQL 語句的轉換。
## 🎉 關注項目
⭐️ 點擊右上角的 Star 追蹤 RAGFlow可以取得最新發布的即時通知 !🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 主要功能
### 🍭 **"Quality in, quality out"**
- 基於[深度文件理解](./deepdoc/README.md),能夠從各類複雜格式的非結構化資料中提取真知灼見。
- 真正在無限上下文token的場景下快速完成大海撈針測試。
### 🍱 **基於模板的文字切片**
- 不只是智能,更重要的是可控可解釋。
- 多種文字範本可供選擇
### 🌱 **有理有據、最大程度降低幻覺hallucination**
- 文字切片過程視覺化,支援手動調整。
- 有理有據:答案提供關鍵引用的快照並支持追根溯源。
### 🍔 **相容各類異質資料來源**
- 支援豐富的文件類型,包括 Word 文件、PPT、excel 表格、txt 檔案、圖片、PDF、影印件、影印件、結構化資料、網頁等。
### 🛀 **全程無憂、自動化的 RAG 工作流程**
- 全面優化的 RAG 工作流程可以支援從個人應用乃至超大型企業的各類生態系統。
- 大語言模型 LLM 以及向量模型皆支援配置。
- 基於多路召回、融合重排序。
- 提供易用的 API可輕鬆整合到各類企業系統。
## 🔎 系統架構
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/12318111/d6ac5664-c237-4200-a7c2-a4a00691b485" width="1000"/>
</div>
## 🎬 快速開始
### 📝 前提條件
- CPU >= 4 核
- RAM >= 16 GB
- Disk >= 50 GB
- Docker >= 24.0.0 & Docker Compose >= v2.26.1
> 如果你並沒有在本機安裝 DockerWindows、Mac或 Linux, 可以參考文件 [Install Docker Engine](https://docs.docker.com/engine/install/) 自行安裝。
### 🚀 啟動伺服器
1. 確保 `vm.max_map_count` 不小於 262144
> 如需確認 `vm.max_map_count` 的大小:
>
> ```bash
> $ sysctl vm.max_map_count
> ```
>
> 如果 `vm.max_map_count` 的值小於 262144可以進行重設
>
> ```bash
> # 這裡我們設為 262144:
> $ sudo sysctl -w vm.max_map_count=262144
> ```
>
> 你的改動會在下次系統重新啟動時被重置。如果希望做永久改動,還需要在 **/etc/sysctl.conf** 檔案裡把 `vm.max_map_count` 的值再相應更新一遍:
>
> ```bash
> vm.max_map_count=262144
> ```
2. 克隆倉庫:
```bash
$ git clone https://github.com/infiniflow/ragflow.git
```
3. 進入 **docker** 資料夾,利用事先編譯好的 Docker 映像啟動伺服器:
> [!CAUTION]
> 所有 Docker 映像檔都是為 x86 平台建置的。目前,我們不提供 ARM64 平台的 Docker 映像檔。
> 如果您使用的是 ARM64 平台,請使用 [這份指南](https://ragflow.io/docs/dev/build_docker_image) 來建置適合您系統的 Docker 映像檔。
> 執行以下指令會自動下載 RAGFlow slim Docker 映像 `v0.18.0-slim`。請參考下表查看不同 Docker 發行版的說明。如需下載不同於 `v0.18.0-slim` 的 Docker 映像,請在執行 `docker compose` 啟動服務之前先更新 **docker/.env** 檔案內的 `RAGFLOW_IMAGE` 變數。例如,你可以透過設定 `RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0` 來下載 RAGFlow 鏡像的 `v0.18.0` 完整發行版。
```bash
$ cd ragflow/docker
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
| ----------------- | --------------- | --------------------- | ------------------------ |
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
> [!TIP]
> 如果你遇到 Docker 映像檔拉不下來的問題,可以在 **docker/.env** 檔案內根據變數 `RAGFLOW_IMAGE` 的註解提示選擇華為雲或阿里雲的對應映像。
>
> - 華為雲鏡像名:`swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow`
> - 阿里雲鏡像名:`registry.cn-hangzhou.aliyuncs.com/infiniflow/ragflow`
4. 伺服器啟動成功後再次確認伺服器狀態:
```bash
$ docker logs -f ragflow-server
```
_出現以下介面提示說明伺服器啟動成功_
```bash
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
```
> 如果您跳過這一步驟系統確認步驟就登入 RAGFlow你的瀏覽器有可能會提示 `network anormal` 或 `網路異常`,因為 RAGFlow 可能並未完全啟動成功。
5. 在你的瀏覽器中輸入你的伺服器對應的 IP 位址並登入 RAGFlow。
> 上面這個範例中,您只需輸入 http://IP_OF_YOUR_MACHINE 即可:未改動過設定則無需輸入連接埠(預設的 HTTP 服務連接埠 80
6. 在 [service_conf.yaml.template](./docker/service_conf.yaml.template) 檔案的 `user_default_llm` 欄位設定 LLM factory並在 `API_KEY` 欄填入和你選擇的大模型相對應的 API key。
> 詳見 [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup)。
_好戲開始接著奏樂接著舞 _
## 🔧 系統配置
系統配置涉及以下三份文件:
- [.env](./docker/.env):存放一些系統環境變量,例如 `SVR_HTTP_PORT`、`MYSQL_PASSWORD`、`MINIO_PASSWORD` 等。
- [service_conf.yaml.template](./docker/service_conf.yaml.template):設定各類別後台服務。
- [docker-compose.yml](./docker/docker-compose.yml): 系統依賴該檔案完成啟動。
請務必確保 [.env](./docker/.env) 檔案中的變數設定與 [service_conf.yaml.template](./docker/service_conf.yaml.template) 檔案中的設定保持一致!
如果無法存取映像網站 hub.docker.com 或模型網站 huggingface.co請依照 [.env](./docker/.env) 註解修改 `RAGFLOW_IMAGE` 和 `HF_ENDPOINT`。
> [./docker/README](./docker/README.md) 解釋了 [service_conf.yaml.template](./docker/service_conf.yaml.template) 用到的環境變數設定和服務配置。
如需更新預設的 HTTP 服務連接埠(80), 可以在[docker-compose.yml](./docker/docker-compose.yml) 檔案中將配置`80:80` 改為`<YOUR_SERVING_PORT>:80` 。
> 所有系統配置都需要透過系統重新啟動生效:
>
> ```bash
> $ docker compose -f docker-compose.yml up -d
> ```
###把文檔引擎從 Elasticsearch 切換成為 Infinity
RAGFlow 預設使用 Elasticsearch 儲存文字和向量資料. 如果要切換為 [Infinity](https://github.com/infiniflow/infinity/), 可以按照下面步驟進行:
1. 停止所有容器運作:
```bash
$ docker compose -f docker/docker-compose.yml down -v
```
Note: `-v` 將會刪除 docker 容器的 volumes已有的資料會被清空。
2. 設定 **docker/.env** 目錄中的 `DOC_ENGINE` 為 `infinity`.
3. 啟動容器:
```bash
$ docker compose -f docker-compose.yml up -d
```
> [!WARNING]
> Infinity 目前官方並未正式支援在 Linux/arm64 架構下的機器上運行.
## 🔧 原始碼編譯 Docker 映像(不含 embedding 模型)
本 Docker 映像大小約 2 GB 左右並且依賴外部的大模型和 embedding 服務。
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🔧 原始碼編譯 Docker 映像(包含 embedding 模型)
本 Docker 大小約 9 GB 左右。由於已包含 embedding 模型,所以只需依賴外部的大模型服務即可。
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly .
```
## 🔨 以原始碼啟動服務
1. 安裝 uv。如已安裝可跳過此步驟
```bash
pipx install uv
export UV_INDEX=https://mirrors.aliyun.com/pypi/simple
```
2. 下載原始碼並安裝 Python 依賴:
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
3. 透過 Docker Compose 啟動依賴的服務MinIO, Elasticsearch, Redis, and MySQL
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
在 `/etc/hosts` 中加入以下程式碼,將 **conf/service_conf.yaml** 檔案中的所有 host 位址都解析為 `127.0.0.1`
```
127.0.0.1 es01 infinity mysql minio redis
```
4. 如果無法存取 HuggingFace可以把環境變數 `HF_ENDPOINT` 設為對應的鏡像網站:
```bash
export HF_ENDPOINT=https://hf-mirror.com
```
5.啟動後端服務:
『`bash
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
6. 安裝前端依賴:
『`bash
cd web
npm install
```
7. 啟動前端服務:
`bash
npm run dev
```
以下界面說明系統已成功啟動_
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
```
## 📚 技術文檔
- [Quickstart](https://ragflow.io/docs/dev/)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 路線圖
詳見 [RAGFlow Roadmap 2025](https://github.com/infiniflow/ragflow/issues/4214) 。
## 🏄 開源社群
- [Discord](https://discord.gg/zd4qPW6t)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 貢獻指南
RAGFlow 只有透過開源協作才能蓬勃發展。秉持這項精神,我們歡迎來自社區的各種貢獻。如果您有意參與其中,請查閱我們的 [貢獻者指南](./CONTRIBUTING.md) 。
## 🤝 商務合作
- [預約諮詢](https://aao615odquw.feishu.cn/share/base/form/shrcnjw7QleretCLqh1nuPo1xxh)
## 👥 加入社區
掃二維碼加入 RAGFlow 小助手,進 RAGFlow 交流群。
<p align="center">
<img src="https://github.com/infiniflow/ragflow/assets/7248/bccf284f-46f2-4445-9809-8f1030fb7585" width=50% height=50%>
</p>

View File

@ -7,28 +7,36 @@
<p align="center">
<a href="./README.md">English</a> |
<a href="./README_zh.md">简体中文</a> |
<a href="./README_tzh.md">繁体中文</a> |
<a href="./README_ja.md">日本語</a> |
<a href="./README_ko.md">한국어</a>
<a href="./README_ko.md">한국어</a> |
<a href="./README_id.md">Bahasa Indonesia</a> |
<a href="/README_pt_br.md">Português (Brasil)</a>
</p>
<p align="center">
<a href="https://x.com/intent/follow?screen_name=infiniflowai" target="_blank">
<img src="https://img.shields.io/twitter/follow/infiniflow?logo=X&color=%20%23f5f5f5" alt="follow on X(Twitter)">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99">
</a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.18.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.18.0">
</a>
<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">
</a>
<a href="https://demo.ragflow.io" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Online-Demo-4e6b99"></a>
<a href="https://hub.docker.com/r/infiniflow/ragflow" target="_blank">
<img src="https://img.shields.io/badge/docker_pull-ragflow:v0.10.0-brightgreen" alt="docker pull infiniflow/ragflow:v0.10.0"></a>
<a href="https://github.com/infiniflow/ragflow/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?labelColor=d4eaf7&color=2e6cc4" alt="license">
</a>
</p>
<h4 align="center">
<a href="https://ragflow.io/docs/dev/">Document</a> |
<a href="https://github.com/infiniflow/ragflow/issues/162">Roadmap</a> |
<a href="https://github.com/infiniflow/ragflow/issues/4214">Roadmap</a> |
<a href="https://twitter.com/infiniflowai">Twitter</a> |
<a href="https://discord.gg/4XxujFgUN7">Discord</a> |
<a href="https://discord.gg/NjYzJD3GM3">Discord</a> |
<a href="https://demo.ragflow.io">Demo</a>
</h4>
@ -39,27 +47,28 @@
## 🎮 Demo 试用
请登录网址 [https://demo.ragflow.io](https://demo.ragflow.io) 试用 demo。
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/infiniflow/ragflow/assets/7248/2f6baa3e-1092-4f11-866d-36f6a9d075e5" width="1200"/>
<img src="https://github.com/infiniflow/ragflow/assets/12318111/b083d173-dadc-4ea9-bdeb-180d7df514eb" width="1200"/>
<img src="https://github.com/user-attachments/assets/504bbbf1-c9f7-4d83-8cc5-e9cb63c26db6" width="1200"/>
</div>
## 🔥 近期更新
- 2024-08-22 支持用RAG技术实现从自然语言到SQL语句的转换。
- 2024-08-02 支持 GraphRAG 启发于 [graphrag](https://github.com/microsoft/graphrag) 和思维导图。
- 2024-07-23 支持解析音频文件
- 2024-07-21 支持更多的大模型供应商(LocalAI/OpenRouter/StepFun/Nvidia)
- 2024-07-18 在Graph中支持算子Wikipedia、PubMed、Baidu和Duckduckgo
- 2024-07-08 支持 Agentic RAG: 基于 [Graph](./graph/README.md) 的工作流
- 2024-06-27 Q&A 解析方式支持 Markdown 文件和 Docx 文件。
- 2024-06-27 支持提取出 Docx 文件中的图片。
- 2024-06-27 支持提取出 Markdown 文件中的表格。
- 2024-06-06 支持 [Self-RAG](https://huggingface.co/papers/2310.11511) ,在对话设置里面默认勾选。
- 2024-05-30 集成 [BCE](https://github.com/netease-youdao/BCEmbedding) 和 [BGE](https://github.com/FlagOpen/FlagEmbedding) 重排序模型。
- 2024-05-23 实现 [RAPTOR](https://arxiv.org/html/2401.18059v1) 提供更好的文本检索。
- 2024-05-15 集成大模型 OpenAI GPT-4o。
- 2025-03-19 PDF和DOCX中的图支持用多模态大模型去解析得到描述.
- 2025-02-28 结合互联网搜索Tavily对于任意大模型实现类似 Deep Research 的推理功能.
- 2025-01-26 优化知识图谱的提取和应用,提供了多种配置选择
- 2024-12-18 升级了 DeepDoc 的文档布局分析模型
- 2024-11-01 对解析后的 chunk 加入关键词抽取和相关问题生成以提高召回的准确度
- 2024-08-22 支持用 RAG 技术实现从自然语言到 SQL 语句的转换
## 🎉 关注项目
⭐️ 点击右上角的 Star 关注 RAGFlow可以获取最新发布的实时通知 !🌟
<div align="center" style="margin-top:20px;margin-bottom:20px;">
<img src="https://github.com/user-attachments/assets/18c9707e-b8aa-4caf-a154-037089c105ba" width="1200"/>
</div>
## 🌟 主要功能
@ -136,15 +145,33 @@
3. 进入 **docker** 文件夹,利用提前编译好的 Docker 镜像启动服务器:
> [!CAUTION]
> 请注意,目前官方提供的所有 Docker 镜像均基于 x86 架构构建,并不提供基于 ARM64 的 Docker 镜像。
> 如果你的操作系统是 ARM64 架构,请参考[这篇文档](https://ragflow.io/docs/dev/build_docker_image)自行构建 Docker 镜像。
> 运行以下命令会自动下载 RAGFlow slim Docker 镜像 `v0.18.0-slim`。请参考下表查看不同 Docker 发行版的描述。如需下载不同于 `v0.18.0-slim` 的 Docker 镜像,请在运行 `docker compose` 启动服务之前先更新 **docker/.env** 文件内的 `RAGFLOW_IMAGE` 变量。比如,你可以通过设置 `RAGFLOW_IMAGE=infiniflow/ragflow:v0.18.0` 来下载 RAGFlow 镜像的 `v0.18.0` 完整发行版。
```bash
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose -f docker-compose-CN.yml up -d
# Use CPU for embedding and DeepDoc tasks:
$ docker compose -f docker-compose.yml up -d
# To use GPU to accelerate embedding and DeepDoc tasks:
# docker compose -f docker-compose-gpu.yml up -d
```
> 请注意,运行上述命令会自动下载 RAGFlow 的开发版本 docker 镜像。如果你想下载并运行特定版本的 docker 镜像,请在 docker/.env 文件中找到 RAGFLOW_VERSION 变量,将其改为对应版本。例如 RAGFLOW_VERSION=v0.10.0,然后运行上述命令。
| RAGFlow image tag | Image size (GB) | Has embedding models? | Stable? |
| ----------------- | --------------- | --------------------- | ------------------------ |
| v0.18.0 | &approx;9 | :heavy_check_mark: | Stable release |
| v0.18.0-slim | &approx;2 | ❌ | Stable release |
| nightly | &approx;9 | :heavy_check_mark: | _Unstable_ nightly build |
| nightly-slim | &approx;2 | ❌ | _Unstable_ nightly build |
> 核心镜像文件大约 9 GB可能需要一定时间拉取。请耐心等待。
> [!TIP]
> 如果你遇到 Docker 镜像拉不下来的问题,可以在 **docker/.env** 文件内根据变量 `RAGFLOW_IMAGE` 的注释提示选择华为云或者阿里云的相应镜像。
>
> - 华为云镜像名:`swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow`
> - 阿里云镜像名:`registry.cn-hangzhou.aliyuncs.com/infiniflow/ragflow`
4. 服务器启动成功后再次确认服务器状态:
@ -155,23 +182,20 @@
_出现以下界面提示说明服务器启动成功_
```bash
____ ______ __
/ __ \ ____ _ ____ _ / ____// /____ _ __
/ /_/ // __ `// __ `// /_ / // __ \| | /| / /
/ _, _// /_/ // /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_| \__,_/ \__, //_/ /_/ \____/ |__/|__/
/____/
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9380
* Running on http://x.x.x.x:9380
INFO:werkzeug:Press CTRL+C to quit
```
> 如果您跳过这一步系统确认步骤就登录 RAGFlow你的浏览器有可能会提示 `network anomaly` 或 `网络异常`,因为 RAGFlow 可能并未完全启动成功。
> 如果您在没有看到上面的提示信息出来之前,就尝试登录 RAGFlow你的浏览器有可能会提示 `network anormal` 或 `网络异常`。
5. 在你的浏览器中输入你的服务器对应的 IP 地址并登录 RAGFlow。
> 上面这个例子中,您只需输入 http://IP_OF_YOUR_MACHINE 即可:未改动过配置则无需输入端口(默认的 HTTP 服务端口 80
6. 在 [service_conf.yaml](./docker/service_conf.yaml) 文件的 `user_default_llm` 栏配置 LLM factory并在 `API_KEY` 栏填写和你选择的大模型相对应的 API key。
6. 在 [service_conf.yaml.template](./docker/service_conf.yaml.template) 文件的 `user_default_llm` 栏配置 LLM factory并在 `API_KEY` 栏填写和你选择的大模型相对应的 API key。
> 详见 [llm_api_key_setup](https://ragflow.io/docs/dev/llm_api_key_setup)。
@ -182,143 +206,150 @@
系统配置涉及以下三份文件:
- [.env](./docker/.env):存放一些基本的系统环境变量,比如 `SVR_HTTP_PORT`、`MYSQL_PASSWORD`、`MINIO_PASSWORD` 等。
- [service_conf.yaml](./docker/service_conf.yaml):配置各类后台服务。
- [docker-compose-CN.yml](./docker/docker-compose-CN.yml): 系统依赖该文件完成启动。
- [service_conf.yaml.template](./docker/service_conf.yaml.template):配置各类后台服务。
- [docker-compose.yml](./docker/docker-compose.yml): 系统依赖该文件完成启动。
请务必确保 [.env](./docker/.env) 文件中的变量设置与 [service_conf.yaml](./docker/service_conf.yaml) 文件中的配置保持一致!
请务必确保 [.env](./docker/.env) 文件中的变量设置与 [service_conf.yaml.template](./docker/service_conf.yaml.template) 文件中的配置保持一致!
> [./docker/README](./docker/README.md) 文件提供了环境变量设置和服务配置的详细信息。请**一定要**确保 [./docker/README](./docker/README.md) 文件当中列出来的环境变量的值与 [service_conf.yaml](./docker/service_conf.yaml) 文件当中的系统配置保持一致
如果不能访问镜像站点 hub.docker.com 或者模型站点 huggingface.co请按照 [.env](./docker/.env) 注释修改 `RAGFLOW_IMAGE` 和 `HF_ENDPOINT`
如需更新默认的 HTTP 服务端口(80), 可以在 [docker-compose-CN.yml](./docker/docker-compose-CN.yml) 文件中将配置 `80:80` 改为 `<YOUR_SERVING_PORT>:80`
> [./docker/README](./docker/README.md) 解释了 [service_conf.yaml.template](./docker/service_conf.yaml.template) 用到的环境变量设置和服务配置
如需更新默认的 HTTP 服务端口(80), 可以在 [docker-compose.yml](./docker/docker-compose.yml) 文件中将配置 `80:80` 改为 `<YOUR_SERVING_PORT>:80`。
> 所有系统配置都需要通过系统重启生效:
>
> ```bash
> $ docker compose -f docker-compose-CN.yml up -d
> $ docker compose -f docker-compose.yml up -d
> ```
## 🛠️ 源码编译、安装 Docker 镜像
### 把文档引擎从 Elasticsearch 切换成为 Infinity
如需从源码安装 Docker 镜像:
RAGFlow 默认使用 Elasticsearch 存储文本和向量数据. 如果要切换为 [Infinity](https://github.com/infiniflow/infinity/), 可以按照下面步骤进行:
1. 停止所有容器运行:
```bash
$ docker compose -f docker/docker-compose.yml down -v
```
Note: `-v` 将会删除 docker 容器的 volumes已有的数据会被清空。
2. 设置 **docker/.env** 目录中的 `DOC_ENGINE` 为 `infinity`.
3. 启动容器:
```bash
$ docker compose -f docker-compose.yml up -d
```
> [!WARNING]
> Infinity 目前官方并未正式支持在 Linux/arm64 架构下的机器上运行.
## 🔧 源码编译 Docker 镜像(不含 embedding 模型)
本 Docker 镜像大小约 2 GB 左右并且依赖外部的大模型和 embedding 服务。
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
$ docker build -t infiniflow/ragflow:v0.10.0 .
$ cd ragflow/docker
$ chmod +x ./entrypoint.sh
$ docker compose up -d
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg LIGHTEN=1 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly-slim .
```
## 🛠️ 源码启动服务
## 🔧 源码编译 Docker 镜像(包含 embedding 模型)
如需从源码启动服务,请参考以下步骤:
1. 克隆仓库
本 Docker 大小约 9 GB 左右。由于已包含 embedding 模型,所以只需依赖外部的大模型服务即可。
```bash
$ git clone https://github.com/infiniflow/ragflow.git
$ cd ragflow/
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
docker build --platform linux/amd64 --build-arg NEED_MIRROR=1 -f Dockerfile -t infiniflow/ragflow:nightly .
```
2. 创建虚拟环境(确保已安装 Anaconda 或 Miniconda
## 🔨 以源代码启动服务
```bash
$ conda create -n ragflow python=3.11.0
$ conda activate ragflow
$ pip install -r requirements.txt
```
如果 cuda > 12.0,需额外执行以下命令:
```bash
$ pip uninstall -y onnxruntime-gpu
$ pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/
```
1. 安装 uv。如已经安装可跳过本步骤
3. 拷贝入口脚本并配置环境变量
```bash
pipx install uv
export UV_INDEX=https://mirrors.aliyun.com/pypi/simple
```
```bash
$ cp docker/entrypoint.sh .
$ vi entrypoint.sh
```
使用以下命令获取python路径及ragflow项目路径
```bash
$ which python
$ pwd
```
2. 下载源代码并安装 Python 依赖:
将上述 `which python` 的输出作为 `PY` 的值,将 `pwd` 的输出作为 `PYTHONPATH` 的值。
```bash
git clone https://github.com/infiniflow/ragflow.git
cd ragflow/
uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules
```
`LD_LIBRARY_PATH` 如果环境已经配置好,可以注释掉。
3. 通过 Docker Compose 启动依赖的服务MinIO, Elasticsearch, Redis, and MySQL
```bash
# 此处配置需要按照实际情况调整,两个 export 为新增配置
PY=${PY}
export PYTHONPATH=${PYTHONPATH}
# 可选:添加 Hugging Face 镜像
export HF_ENDPOINT=https://hf-mirror.com
```
```bash
docker compose -f docker/docker-compose-base.yml up -d
```
4. 启动基础服务
在 `/etc/hosts` 中添加以下代码,目的是将 **conf/service_conf.yaml** 文件中的所有 host 地址都解析为 `127.0.0.1`
```bash
$ cd docker
$ docker compose -f docker-compose-base.yml up -d
```
```
127.0.0.1 es01 infinity mysql minio redis
```
4. 如果无法访问 HuggingFace可以把环境变量 `HF_ENDPOINT` 设成相应的镜像站点:
5. 检查配置文件
确保**docker/.env**中的配置与**conf/service_conf.yaml**中配置一致, **service_conf.yaml**中相关服务的IP地址与端口应该改成本机IP地址及容器映射出来的端口。
```bash
export HF_ENDPOINT=https://hf-mirror.com
```
6. 启动服务
5. 启动后端服务
```bash
$ chmod +x ./entrypoint.sh
$ bash ./entrypoint.sh
```
```bash
source .venv/bin/activate
export PYTHONPATH=$(pwd)
bash docker/launch_backend_service.sh
```
7. 启动WebUI服务
6. 安装前端依赖:
```bash
cd web
npm install
```
7. 启动前端服务:
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ vim .umirc.ts
# 修改proxy.target为http://127.0.0.1:9380
$ npm run dev
```
```bash
npm run dev
```
8. 部署WebUI服务
_以下界面说明系统已经成功启动_
![](https://github.com/user-attachments/assets/0daf462c-a24d-4496-a66f-92533534e187)
8. 开发完成后停止 RAGFlow 服务
停止 RAGFlow 前端和后端服务:
```bash
pkill -f "ragflow_server.py|task_executor.py"
```
```bash
$ cd web
$ npm install --registry=https://registry.npmmirror.com --force
$ umi build
$ mkdir -p /ragflow/web
$ cp -r dist /ragflow/web
$ apt install nginx -y
$ cp ../docker/nginx/proxy.conf /etc/nginx
$ cp ../docker/nginx/nginx.conf /etc/nginx
$ cp ../docker/nginx/ragflow.conf /etc/nginx/conf.d
$ systemctl start nginx
```
## 📚 技术文档
- [Quickstart](https://ragflow.io/docs/dev/)
- [User guide](https://ragflow.io/docs/dev/category/user-guides)
- [Configuration](https://ragflow.io/docs/dev/configurations)
- [Release notes](https://ragflow.io/docs/dev/release_notes)
- [User guides](https://ragflow.io/docs/dev/category/guides)
- [Developer guides](https://ragflow.io/docs/dev/category/developers)
- [References](https://ragflow.io/docs/dev/category/references)
- [FAQ](https://ragflow.io/docs/dev/faq)
- [FAQs](https://ragflow.io/docs/dev/faq)
## 📜 路线图
详见 [RAGFlow Roadmap 2024](https://github.com/infiniflow/ragflow/issues/162) 。
详见 [RAGFlow Roadmap 2025](https://github.com/infiniflow/ragflow/issues/4214) 。
## 🏄 开源社区
- [Discord](https://discord.gg/4XxujFgUN7)
- [Discord](https://discord.gg/zd4qPW6t)
- [Twitter](https://twitter.com/infiniflowai)
- [GitHub Discussions](https://github.com/orgs/infiniflow/discussions)
## 🙌 贡献指南
RAGFlow 只有通过开源协作才能蓬勃发展。秉持这一精神,我们欢迎来自社区的各种贡献。如果您有意参与其中,请查阅我们的 [贡献者指南](./docs/references/CONTRIBUTING.md) 。
RAGFlow 只有通过开源协作才能蓬勃发展。秉持这一精神,我们欢迎来自社区的各种贡献。如果您有意参与其中,请查阅我们的 [贡献者指南](./CONTRIBUTING.md) 。
## 🤝 商务合作
@ -331,4 +362,3 @@ RAGFlow 只有通过开源协作才能蓬勃发展。秉持这一精神,我们
<p align="center">
<img src="https://github.com/infiniflow/ragflow/assets/7248/bccf284f-46f2-4445-9809-8f1030fb7585" width=50% height=50%>
</p>

View File

@ -18,7 +18,7 @@ main
### Actual behavior
The restricted_loads function at [api/utils/__init__.py#L215](https://github.com/infiniflow/ragflow/blob/main/api/utils/__init__.py#L215) is still vulnerable leading via code execution.
The main reson is that numpy module has a numpy.f2py.diagnose.run_command function directly execute commands, but the restricted_loads function allows users import functions in module numpy.
The main reason is that numpy module has a numpy.f2py.diagnose.run_command function directly execute commands, but the restricted_loads function allows users import functions in module numpy.
### Steps to reproduce

View File

@ -10,7 +10,7 @@ It is used to compose a complex work flow or agent.
And this graph is beyond the DAG that we can use circles to describe our agent or work flow.
Under this folder, we propose a test tool ./test/client.py which can test the DSLs such as json files in folder ./test/dsl_examples.
Please use this client at the same folder you start RAGFlow. If it's run by Docker, please go into the container before running the client.
Otherwise, correct configurations in conf/service_conf.yaml is essential.
Otherwise, correct configurations in service_conf.yaml is essential.
```bash
PYTHONPATH=path/to/ragflow python graph/test/client.py -h

View File

@ -11,7 +11,7 @@
在这个文件夹下,我们提出了一个测试工具 ./test/client.py
它可以测试像文件夹./test/dsl_examples下一样的DSL文件。
请在启动 RAGFlow 的同一文件夹中使用此客户端。如果它是通过 Docker 运行的,请在运行客户端之前进入容器。
否则,正确配置 conf/service_conf.yaml 文件是必不可少的。
否则,正确配置 service_conf.yaml 文件是必不可少的。
```bash
PYTHONPATH=path/to/ragflow python graph/test/client.py -h

View File

@ -0,0 +1,18 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from beartype.claw import beartype_this_package
beartype_this_package()

View File

@ -13,10 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import importlib
import logging
import json
import traceback
from abc import ABC
from copy import deepcopy
from functools import partial
@ -24,10 +22,9 @@ import pandas as pd
from agent.component import component_class
from agent.component.base import ComponentBase
from agent.settings import flow_logger, DEBUG
class Canvas(ABC):
class Canvas:
"""
dsl = {
"components": {
@ -88,7 +85,8 @@ class Canvas(ABC):
}
},
"downstream": [],
"upstream": []
"upstream": [],
"parent_id": ""
}
},
"history": [],
@ -139,7 +137,8 @@ class Canvas(ABC):
"components": {}
}
for k in self.dsl.keys():
if k in ["components"]:continue
if k in ["components"]:
continue
dsl[k] = deepcopy(self.dsl[k])
for k, cpn in self.components.items():
@ -162,8 +161,13 @@ class Canvas(ABC):
self.components[k]["obj"].reset()
self._embed_id = ""
def get_component_name(self, cid):
for n in self.dsl["graph"]["nodes"]:
if cid == n["id"]:
return n["data"]["name"]
return ""
def run(self, **kwargs):
ans = ""
if self.answer:
cpn_id = self.answer[0]
self.answer.pop(0)
@ -173,71 +177,107 @@ class Canvas(ABC):
ans = ComponentBase.be_output(str(e))
self.path[-1].append(cpn_id)
if kwargs.get("stream"):
assert isinstance(ans, partial)
return ans
self.history.append(("assistant", ans.to_dict("records")))
return ans
for an in ans():
yield an
else:
yield ans
return
if not self.path:
self.components["begin"]["obj"].run(self.history, **kwargs)
self.path.append(["begin"])
self.path.append([])
ran = -1
waiting = []
without_dependent_checking = []
def prepare2run(cpns):
nonlocal ran, ans
for c in cpns:
if self.path[-1] and c == self.path[-1][-1]: continue
if self.path[-1] and c == self.path[-1][-1]:
continue
cpn = self.components[c]["obj"]
if cpn.component_name == "Answer":
self.answer.append(c)
else:
if DEBUG: print("RUN: ", c)
if cpn.component_name == "Generate":
logging.debug(f"Canvas.prepare2run: {c}")
if c not in without_dependent_checking:
cpids = cpn.get_dependent_components()
if any([c not in self.path[-1] for c in cpids]):
if any([cc not in self.path[-1] for cc in cpids]):
if c not in waiting:
waiting.append(c)
continue
ans = cpn.run(self.history, **kwargs)
yield "*'{}'* is running...🕞".format(self.get_component_name(c))
if cpn.component_name.lower() == "iteration":
st_cpn = cpn.get_start()
assert st_cpn, "Start component not found for Iteration."
if not st_cpn["obj"].end():
cpn = st_cpn["obj"]
c = cpn._id
try:
ans = cpn.run(self.history, **kwargs)
except Exception as e:
logging.exception(f"Canvas.run got exception: {e}")
self.path[-1].append(c)
ran += 1
raise e
self.path[-1].append(c)
ran += 1
prepare2run(self.components[self.path[-2][-1]]["downstream"])
downstream = self.components[self.path[-2][-1]]["downstream"]
if not downstream and self.components[self.path[-2][-1]].get("parent_id"):
cid = self.path[-2][-1]
pid = self.components[cid]["parent_id"]
o, _ = self.components[cid]["obj"].output(allow_partial=False)
oo, _ = self.components[pid]["obj"].output(allow_partial=False)
self.components[pid]["obj"].set_output(pd.concat([oo, o], ignore_index=True).dropna())
downstream = [pid]
for m in prepare2run(downstream):
yield {"content": m, "running_status": True}
while 0 <= ran < len(self.path[-1]):
if DEBUG: print(ran, self.path)
logging.debug(f"Canvas.run: {ran} {self.path}")
cpn_id = self.path[-1][ran]
cpn = self.get_component(cpn_id)
if not cpn["downstream"]: break
if not any([cpn["downstream"], cpn.get("parent_id"), waiting]):
break
loop = self._find_loop()
if loop: raise OverflowError(f"Too much loops: {loop}")
if loop:
raise OverflowError(f"Too much loops: {loop}")
downstream = []
if cpn["obj"].component_name.lower() in ["switch", "categorize", "relevant"]:
switch_out = cpn["obj"].output()[1].iloc[0, 0]
assert switch_out in self.components, \
"{}'s output: {} not valid.".format(cpn_id, switch_out)
try:
prepare2run([switch_out])
except Exception as e:
for p in [c for p in self.path for c in p][::-1]:
if p.lower().find("answer") >= 0:
self.get_component(p)["obj"].set_exception(e)
prepare2run([p])
break
traceback.print_exc()
break
continue
downstream = [switch_out]
else:
downstream = cpn["downstream"]
try:
prepare2run(cpn["downstream"])
except Exception as e:
for p in [c for p in self.path for c in p][::-1]:
if p.lower().find("answer") >= 0:
self.get_component(p)["obj"].set_exception(e)
prepare2run([p])
break
traceback.print_exc()
break
if not downstream and cpn.get("parent_id"):
pid = cpn["parent_id"]
_, o = cpn["obj"].output(allow_partial=False)
_, oo = self.components[pid]["obj"].output(allow_partial=False)
self.components[pid]["obj"].set_output(pd.concat([oo.dropna(axis=1), o.dropna(axis=1)], ignore_index=True).dropna())
downstream = [pid]
for m in prepare2run(downstream):
yield {"content": m, "running_status": True}
if ran >= len(self.path[-1]) and waiting:
without_dependent_checking = waiting
waiting = []
for m in prepare2run(without_dependent_checking):
yield {"content": m, "running_status": True}
without_dependent_checking = []
ran -= 1
if self.answer:
cpn_id = self.answer[0]
@ -246,11 +286,13 @@ class Canvas(ABC):
self.path[-1].append(cpn_id)
if kwargs.get("stream"):
assert isinstance(ans, partial)
return ans
for an in ans():
yield an
else:
yield ans
self.history.append(("assistant", ans.to_dict("records")))
return ans
else:
raise Exception("The dialog flow has no way to interact with you. Please add an 'Interact' component to the end of the flow.")
def get_component(self, cpn_id):
return self.components[cpn_id]
@ -260,9 +302,11 @@ class Canvas(ABC):
def get_history(self, window_size):
convs = []
for role, obj in self.history[window_size * -2:]:
convs.append({"role": role, "content": (obj if role == "user" else
'\n'.join(pd.DataFrame(obj)['content']))})
for role, obj in self.history[window_size * -1:]:
if isinstance(obj, list) and obj and all([isinstance(o, dict) for o in obj]):
convs.append({"role": role, "content": '\n'.join([str(s.get("content", "")) for s in obj])})
else:
convs.append({"role": role, "content": str(obj)})
return convs
def add_user_input(self, question):
@ -276,19 +320,22 @@ class Canvas(ABC):
def _find_loop(self, max_loops=6):
path = self.path[-1][::-1]
if len(path) < 2: return False
if len(path) < 2:
return False
for i in range(len(path)):
if path[i].lower().find("answer") >= 0:
if path[i].lower().find("answer") == 0 or path[i].lower().find("iterationitem") == 0:
path = path[:i]
break
if len(path) < 2: return False
if len(path) < 2:
return False
for l in range(2, len(path) // 2):
pat = ",".join(path[0:l])
for loc in range(2, len(path) // 2):
pat = ",".join(path[0:loc])
path_str = ",".join(path)
if len(pat) >= len(path_str): return False
if len(pat) >= len(path_str):
return False
loop = max_loops
while path_str.find(pat) == 0 and loop >= 0:
loop -= 1
@ -296,7 +343,23 @@ class Canvas(ABC):
return False
path_str = path_str[len(pat)+1:]
if loop < 0:
pat = " => ".join([p.split(":")[0] for p in path[0:l]])
pat = " => ".join([p.split(":")[0] for p in path[0:loc]])
return pat + " => " + pat
return False
def get_prologue(self):
return self.components["begin"]["obj"]._param.prologue
def set_global_param(self, **kwargs):
for k, v in kwargs.items():
for q in self.components["begin"]["obj"]._param.query:
if k != q["key"]:
continue
q["value"] = v
def get_preset_param(self):
return self.components["begin"]["obj"]._param.query
def get_component_input_elements(self, cpnnm):
return self.components[cpnnm]["obj"].get_input_elements()

View File

@ -1,3 +1,19 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import importlib
from .begin import Begin, BeginParam
from .generate import Generate, GenerateParam
@ -9,6 +25,7 @@ from .relevant import Relevant, RelevantParam
from .message import Message, MessageParam
from .rewrite import RewriteQuestion, RewriteQuestionParam
from .keyword import KeywordExtract, KeywordExtractParam
from .concentrator import Concentrator, ConcentratorParam
from .baidu import Baidu, BaiduParam
from .duckduckgo import DuckDuckGo, DuckDuckGoParam
from .wikipedia import Wikipedia, WikipediaParam
@ -22,8 +39,95 @@ from .github import GitHub, GitHubParam
from .baidufanyi import BaiduFanyi, BaiduFanyiParam
from .qweather import QWeather, QWeatherParam
from .exesql import ExeSQL, ExeSQLParam
from .yahoofinance import YahooFinance, YahooFinanceParam
from .wencai import WenCai, WenCaiParam
from .jin10 import Jin10, Jin10Param
from .tushare import TuShare, TuShareParam
from .akshare import AkShare, AkShareParam
from .crawler import Crawler, CrawlerParam
from .invoke import Invoke, InvokeParam
from .template import Template, TemplateParam
from .email import Email, EmailParam
from .iteration import Iteration, IterationParam
from .iterationitem import IterationItem, IterationItemParam
def component_class(class_name):
m = importlib.import_module("agent.component")
c = getattr(m, class_name)
return c
__all__ = [
"Begin",
"BeginParam",
"Generate",
"GenerateParam",
"Retrieval",
"RetrievalParam",
"Answer",
"AnswerParam",
"Categorize",
"CategorizeParam",
"Switch",
"SwitchParam",
"Relevant",
"RelevantParam",
"Message",
"MessageParam",
"RewriteQuestion",
"RewriteQuestionParam",
"KeywordExtract",
"KeywordExtractParam",
"Concentrator",
"ConcentratorParam",
"Baidu",
"BaiduParam",
"DuckDuckGo",
"DuckDuckGoParam",
"Wikipedia",
"WikipediaParam",
"PubMed",
"PubMedParam",
"ArXiv",
"ArXivParam",
"Google",
"GoogleParam",
"Bing",
"BingParam",
"GoogleScholar",
"GoogleScholarParam",
"DeepL",
"DeepLParam",
"GitHub",
"GitHubParam",
"BaiduFanyi",
"BaiduFanyiParam",
"QWeather",
"QWeatherParam",
"ExeSQL",
"ExeSQLParam",
"YahooFinance",
"YahooFinanceParam",
"WenCai",
"WenCaiParam",
"Jin10",
"Jin10Param",
"TuShare",
"TuShareParam",
"AkShare",
"AkShareParam",
"Crawler",
"CrawlerParam",
"Invoke",
"InvokeParam",
"Iteration",
"IterationParam",
"IterationItem",
"IterationItemParam",
"Template",
"TemplateParam",
"Email",
"EmailParam",
"component_class"
]

View File

@ -0,0 +1,56 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import pandas as pd
from agent.component.base import ComponentBase, ComponentParamBase
class AkShareParam(ComponentParamBase):
"""
Define the AkShare component parameters.
"""
def __init__(self):
super().__init__()
self.top_n = 10
def check(self):
self.check_positive_integer(self.top_n, "Top N")
class AkShare(ComponentBase, ABC):
component_name = "AkShare"
def _run(self, history, **kwargs):
import akshare as ak
ans = self.get_input()
ans = ",".join(ans["content"]) if "content" in ans else ""
if not ans:
return AkShare.be_output("")
try:
ak_res = []
stock_news_em_df = ak.stock_news_em(symbol=ans)
stock_news_em_df = stock_news_em_df.head(self._param.top_n)
ak_res = [{"content": '<a href="' + i["新闻链接"] + '">' + i["新闻标题"] + '</a>\n 新闻内容: ' + i[
"新闻内容"] + " \n发布时间:" + i["发布时间"] + " \n文章来源: " + i["文章来源"]} for index, i in stock_news_em_df.iterrows()]
except Exception as e:
return AkShare.be_output("**ERROR**: " + str(e))
if not ak_res:
return AkShare.be_output("")
return pd.DataFrame(ak_res)

View File

@ -16,6 +16,7 @@
import random
from abc import ABC
from functools import partial
from typing import Tuple, Union
import pandas as pd
@ -76,4 +77,13 @@ class Answer(ComponentBase, ABC):
def set_exception(self, e):
self.exception = e
def output(self, allow_partial=True) -> Tuple[str, Union[pd.DataFrame, partial]]:
if allow_partial:
return super.output()
for r, c in self._canvas.history[::-1]:
if r == "user":
return self._param.output_var_name, pd.DataFrame([{"content": c}])
self._param.output_var_name, pd.DataFrame([])

View File

@ -13,13 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
import arxiv
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
class ArXivParam(ComponentParamBase):
"""
Define the ArXiv component parameters.
@ -65,5 +64,5 @@ class ArXiv(ComponentBase, ABC):
return ArXiv.be_output("")
df = pd.DataFrame(arxiv_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {str(df)}")
return df

View File

@ -13,13 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
import logging
from abc import ABC
from functools import partial
import pandas as pd
import requests
import re
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -46,7 +44,7 @@ class Baidu(ComponentBase, ABC):
return Baidu.be_output("")
try:
url = 'https://www.baidu.com/s?wd=' + ans + '&rn=' + str(self._param.top_n)
url = 'http://www.baidu.com/s?wd=' + ans + '&rn=' + str(self._param.top_n)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'}
response = requests.get(url=url, headers=headers)
@ -64,6 +62,6 @@ class Baidu(ComponentBase, ABC):
return Baidu.be_output("")
df = pd.DataFrame(baidu_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {str(df)}")
return df

View File

@ -36,13 +36,9 @@ class BaiduFanyiParam(ComponentParamBase):
self.domain = 'finance'
def check(self):
self.check_positive_integer(self.top_n, "Top N")
self.check_empty(self.appid, "BaiduFanyi APPID")
self.check_empty(self.secret_key, "BaiduFanyi Secret Key")
self.check_valid_value(self.trans_type, "Translate type", ['translate', 'fieldtranslate'])
self.check_valid_value(self.trans_type, "Translate domain",
['it', 'finance', 'machinery', 'senimed', 'novel', 'academic', 'aerospace', 'wiki',
'news', 'law', 'contract'])
self.check_valid_value(self.source_lang, "Source language",
['auto', 'zh', 'en', 'yue', 'wyw', 'jp', 'kor', 'fra', 'spa', 'th', 'ara', 'ru', 'pt',
'de', 'it', 'el', 'nl', 'pl', 'bul', 'est', 'dan', 'fin', 'cs', 'rom', 'slo', 'swe',
@ -97,3 +93,4 @@ class BaiduFanyi(ComponentBase, ABC):
except Exception as e:
BaiduFanyi.be_output("**Error**:" + str(e))

View File

@ -17,14 +17,13 @@ from abc import ABC
import builtins
import json
import os
from copy import deepcopy
import logging
from functools import partial
from typing import List, Dict, Tuple, Union
from typing import Tuple, Union
import pandas as pd
from agent import settings
from agent.settings import flow_logger, DEBUG
_FEEDED_DEPRECATED_PARAMS = "_feeded_deprecated_params"
_DEPRECATED_PARAMS = "_deprecated_params"
@ -36,6 +35,9 @@ class ComponentParamBase(ABC):
def __init__(self):
self.output_var_name = "output"
self.message_history_window_size = 22
self.query = []
self.inputs = []
self.debug_inputs = []
def set_name(self, name: str):
self._name = name
@ -81,7 +83,6 @@ class ComponentParamBase(ABC):
return {name: True for name in self.get_feeded_deprecated_params()}
def __str__(self):
return json.dumps(self.as_dict(), ensure_ascii=False)
def as_dict(self):
@ -359,13 +360,13 @@ class ComponentParamBase(ABC):
def _warn_deprecated_param(self, param_name, descr):
if self._deprecated_params_set.get(param_name):
flow_logger.warning(
logging.warning(
f"{descr} {param_name} is deprecated and ignored in this version."
)
def _warn_to_deprecate_param(self, param_name, descr, new_param):
if self._deprecated_params_set.get(param_name):
flow_logger.warning(
logging.warning(
f"{descr} {param_name} will be deprecated in future release; "
f"please use {new_param} instead."
)
@ -383,22 +384,41 @@ class ComponentBase(ABC):
"params": {}
}
"""
out = getattr(self._param, self._param.output_var_name)
if isinstance(out, pd.DataFrame) and "chunks" in out:
del out["chunks"]
setattr(self._param, self._param.output_var_name, out)
return """{{
"component_name": "{}",
"params": {}
"params": {},
"output": {},
"inputs": {}
}}""".format(self.component_name,
self._param
)
self._param,
json.dumps(json.loads(str(self._param)).get("output", {}), ensure_ascii=False),
json.dumps(json.loads(str(self._param)).get("inputs", []), ensure_ascii=False)
)
def __init__(self, canvas, id, param: ComponentParamBase):
from agent.canvas import Canvas # Local import to avoid cyclic dependency
assert isinstance(canvas, Canvas), "canvas must be an instance of Canvas"
self._canvas = canvas
self._id = id
self._param = param
self._param.check()
def get_dependent_components(self):
cpnts = set([para["component_id"].split("@")[0] for para in self._param.query \
if para.get("component_id") \
and para["component_id"].lower().find("answer") < 0 \
and para["component_id"].lower().find("begin") < 0])
return list(cpnts)
def run(self, history, **kwargs):
flow_logger.info("{}, history: {}, kwargs: {}".format(self, json.dumps(history, ensure_ascii=False),
logging.debug("{}, history: {}, kwargs: {}".format(self, json.dumps(history, ensure_ascii=False),
json.dumps(kwargs, ensure_ascii=False)))
self._param.debug_inputs = []
try:
res = self._run(history, **kwargs)
self.set_output(res)
@ -413,75 +433,153 @@ class ComponentBase(ABC):
def output(self, allow_partial=True) -> Tuple[str, Union[pd.DataFrame, partial]]:
o = getattr(self._param, self._param.output_var_name)
if not isinstance(o, partial) and not isinstance(o, pd.DataFrame):
if not isinstance(o, list): o = [o]
o = pd.DataFrame(o)
if not isinstance(o, partial):
if not isinstance(o, pd.DataFrame):
if isinstance(o, list):
return self._param.output_var_name, pd.DataFrame(o).dropna()
if o is None:
return self._param.output_var_name, pd.DataFrame()
return self._param.output_var_name, pd.DataFrame([{"content": str(o)}])
return self._param.output_var_name, o
if allow_partial or not isinstance(o, partial):
if not isinstance(o, partial) and not isinstance(o, pd.DataFrame):
return pd.DataFrame(o if isinstance(o, list) else [o])
return pd.DataFrame(o if isinstance(o, list) else [o]).dropna()
return self._param.output_var_name, o
outs = None
for oo in o():
if not isinstance(oo, pd.DataFrame):
outs = pd.DataFrame(oo if isinstance(oo, list) else [oo])
else: outs = oo
outs = pd.DataFrame(oo if isinstance(oo, list) else [oo]).dropna()
else:
outs = oo.dropna()
return self._param.output_var_name, outs
def reset(self):
setattr(self._param, self._param.output_var_name, None)
self._param.inputs = []
def set_output(self, v: pd.DataFrame):
def set_output(self, v):
setattr(self._param, self._param.output_var_name, v)
def get_input(self):
upstream_outs = []
if self._param.debug_inputs:
return pd.DataFrame([{"content": v["value"]} for v in self._param.debug_inputs if v.get("value")])
reversed_cpnts = []
if len(self._canvas.path) > 1:
reversed_cpnts.extend(self._canvas.path[-2])
reversed_cpnts.extend(self._canvas.path[-1])
up_cpns = self.get_upstream()
reversed_up_cpnts = [cpn for cpn in reversed_cpnts if cpn in up_cpns]
if DEBUG: print(self.component_name, reversed_cpnts[::-1])
for u in reversed_cpnts[::-1]:
if self.get_component_name(u) in ["switch"]: continue
if self._param.query:
self._param.inputs = []
outs = []
for q in self._param.query:
if q.get("component_id"):
if q["component_id"].split("@")[0].lower().find("begin") >= 0:
cpn_id, key = q["component_id"].split("@")
for p in self._canvas.get_component(cpn_id)["obj"]._param.query:
if p["key"] == key:
outs.append(pd.DataFrame([{"content": p.get("value", "")}]))
self._param.inputs.append({"component_id": q["component_id"],
"content": p.get("value", "")})
break
else:
assert False, f"Can't find parameter '{key}' for {cpn_id}"
continue
if q["component_id"].lower().find("answer") == 0:
txt = []
for r, c in self._canvas.history[::-1][:self._param.message_history_window_size][::-1]:
txt.append(f"{r.upper()}:{c}")
txt = "\n".join(txt)
self._param.inputs.append({"content": txt, "component_id": q["component_id"]})
outs.append(pd.DataFrame([{"content": txt}]))
continue
outs.append(self._canvas.get_component(q["component_id"])["obj"].output(allow_partial=False)[1])
self._param.inputs.append({"component_id": q["component_id"],
"content": "\n".join(
[str(d["content"]) for d in outs[-1].to_dict('records')])})
elif q.get("value"):
self._param.inputs.append({"component_id": None, "content": q["value"]})
outs.append(pd.DataFrame([{"content": q["value"]}]))
if outs:
df = pd.concat(outs, ignore_index=True)
if "content" in df:
df = df.drop_duplicates(subset=['content']).reset_index(drop=True)
return df
upstream_outs = []
for u in reversed_up_cpnts[::-1]:
if self.get_component_name(u) in ["switch", "concentrator"]:
continue
if self.component_name.lower() == "generate" and self.get_component_name(u) == "retrieval":
o = self._canvas.get_component(u)["obj"].output(allow_partial=False)[1]
if o is not None:
o["component_id"] = u
upstream_outs.append(o)
continue
if u not in self._canvas.get_component(self._id)["upstream"]: continue
#if self.component_name.lower()!="answer" and u not in self._canvas.get_component(self._id)["upstream"]: continue
if self.component_name.lower().find("switch") < 0 \
and self.get_component_name(u) in ["relevant", "categorize"]:
continue
if u.lower().find("answer") >= 0:
for r, c in self._canvas.history[::-1]:
if r == "user":
upstream_outs.append(pd.DataFrame([{"content": c}]))
upstream_outs.append(pd.DataFrame([{"content": c, "component_id": u}]))
break
break
if self.component_name.lower().find("answer") >= 0 and self.get_component_name(u) in ["relevant"]:
continue
o = self._canvas.get_component(u)["obj"].output(allow_partial=False)[1]
if o is not None:
o["component_id"] = u
upstream_outs.append(o)
break
if upstream_outs:
df = pd.concat(upstream_outs, ignore_index=True)
if "content" in df:
df = df.drop_duplicates(subset=['content']).reset_index(drop=True)
return df
return pd.DataFrame()
assert upstream_outs, "Can't inference the where the component input is. Please identify whose output is this component's input."
df = pd.concat(upstream_outs, ignore_index=True)
if "content" in df:
df = df.drop_duplicates(subset=['content']).reset_index(drop=True)
self._param.inputs = []
for _, r in df.iterrows():
self._param.inputs.append({"component_id": r["component_id"], "content": r["content"]})
return df
def get_input_elements(self):
assert self._param.query, "Please verify the input parameters first."
eles = []
for q in self._param.query:
if q.get("component_id"):
cpn_id = q["component_id"]
if cpn_id.split("@")[0].lower().find("begin") >= 0:
cpn_id, key = cpn_id.split("@")
eles.extend(self._canvas.get_component(cpn_id)["obj"]._param.query)
continue
eles.append({"name": self._canvas.get_component_name(cpn_id), "key": cpn_id})
else:
eles.append({"key": q["value"], "name": q["value"], "value": q["value"]})
return eles
def get_stream_input(self):
reversed_cpnts = []
if len(self._canvas.path) > 1:
reversed_cpnts.extend(self._canvas.path[-2])
reversed_cpnts.extend(self._canvas.path[-1])
up_cpns = self.get_upstream()
reversed_up_cpnts = [cpn for cpn in reversed_cpnts if cpn in up_cpns]
for u in reversed_cpnts[::-1]:
if self.get_component_name(u) in ["switch", "answer"]: continue
for u in reversed_up_cpnts[::-1]:
if self.get_component_name(u) in ["switch", "answer"]:
continue
return self._canvas.get_component(u)["obj"].output()[1]
@staticmethod
@ -490,3 +588,14 @@ class ComponentBase(ABC):
def get_component_name(self, cpn_id):
return self._canvas.get_component(cpn_id)["obj"].component_name.lower()
def debug(self, **kwargs):
return self._run([], **kwargs)
def get_parent(self):
pid = self._canvas.get_component(self._id)["parent_id"]
return self._canvas.get_component(pid)["obj"]
def get_upstream(self):
cpn_nms = self._canvas.get_component(self._id)['upstream']
return cpn_nms

View File

@ -26,6 +26,7 @@ class BeginParam(ComponentParamBase):
def __init__(self):
super().__init__()
self.prologue = "Hi! I'm your smart assistant. What can I do for you?"
self.query = []
def check(self):
return True
@ -42,7 +43,7 @@ class Begin(ComponentBase):
def stream_output(self):
res = {"content": self._param.prologue}
yield res
self.set_output(res)
self.set_output(self.be_output(res))

View File

@ -13,13 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
import requests
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
class BingParam(ComponentParamBase):
"""
Define the Bing component parameters.
@ -81,5 +80,5 @@ class Bing(ComponentBase, ABC):
return Bing.be_output("")
df = pd.DataFrame(bing_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {str(df)}")
return df

View File

@ -13,11 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
from api.db import LLMType
from api.db.services.llm_service import LLMBundle
from agent.component import GenerateParam, Generate
from agent.settings import DEBUG
class CategorizeParam(GenerateParam):
@ -34,36 +34,46 @@ class CategorizeParam(GenerateParam):
super().check()
self.check_empty(self.category_description, "[Categorize] Category examples")
for k, v in self.category_description.items():
if not k: raise ValueError(f"[Categorize] Category name can not be empty!")
if not v.get("to"): raise ValueError(f"[Categorize] 'To' of category {k} can not be empty!")
if not k:
raise ValueError("[Categorize] Category name can not be empty!")
if not v.get("to"):
raise ValueError(f"[Categorize] 'To' of category {k} can not be empty!")
def get_prompt(self):
def get_prompt(self, chat_hist):
cate_lines = []
for c, desc in self.category_description.items():
for l in desc.get("examples", "").split("\n"):
if not l: continue
cate_lines.append("Question: {}\tCategory: {}".format(l, c))
for line in desc.get("examples", "").split("\n"):
if not line:
continue
cate_lines.append("USER: {}\nCategory: {}".format(line, c))
descriptions = []
for c, desc in self.category_description.items():
if desc.get("description"):
descriptions.append(
"--------------------\nCategory: {}\nDescription: {}\n".format(c, desc["description"]))
"\nCategory: {}\nDescription: {}".format(c, desc["description"]))
self.prompt = """
You're a text classifier. You need to categorize the users questions into {} categories,
namely: {}
Here's description of each category:
{}
Role: You're a text classifier.
Task: You need to categorize the users questions into {} categories, namely: {}
You could learn from the following examples:
{}
You could learn from the above examples.
Just mention the category names, no need for any additional words.
Here's description of each category:
{}
You could learn from the following examples:
{}
You could learn from the above examples.
Requirements:
- Just mention the category names, no need for any additional words.
---- Real Data ----
USER: {}\n
""".format(
len(self.category_description.keys()),
"/".join(list(self.category_description.keys())),
"\n".join(descriptions),
"- ".join(cate_lines)
"\n\n- ".join(cate_lines),
chat_hist
)
return self.prompt
@ -73,15 +83,26 @@ class Categorize(Generate, ABC):
def _run(self, history, **kwargs):
input = self.get_input()
input = "Question: " + ("; ".join(input["content"]) if "content" in input else "") + "Category: "
input = " - ".join(input["content"]) if "content" in input else ""
chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id)
ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": input}],
ans = chat_mdl.chat(self._param.get_prompt(input), [{"role": "user", "content": "\nCategory: "}],
self._param.gen_conf())
if DEBUG: print(ans, ":::::::::::::::::::::::::::::::::", input)
logging.debug(f"input: {input}, answer: {str(ans)}")
# Count the number of times each category appears in the answer.
category_counts = {}
for c in self._param.category_description.keys():
if ans.lower().find(c.lower()) >= 0:
return Categorize.be_output(self._param.category_description[c]["to"])
count = ans.lower().count(c.lower())
category_counts[c] = count
# If a category is found, return the category with the highest count.
if any(category_counts.values()):
max_category = max(category_counts.items(), key=lambda x: x[1])
return Categorize.be_output(self._param.category_description[max_category[0]]["to"])
return Categorize.be_output(self._param.category_description.items()[-1][1]["to"])
return Categorize.be_output(list(self._param.category_description.items())[-1][1]["to"])
def debug(self, **kwargs):
df = self._run([], **kwargs)
cpn_id = df.iloc[0, 0]
return Categorize.be_output(self._canvas.get_component_name(cpn_id))

View File

@ -1,75 +0,0 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import pandas as pd
from api.db import LLMType
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import LLMBundle
from api.settings import retrievaler
from agent.component.base import ComponentBase, ComponentParamBase
class CiteParam(ComponentParamBase):
"""
Define the Retrieval component parameters.
"""
def __init__(self):
super().__init__()
self.cite_sources = []
def check(self):
self.check_empty(self.cite_source, "Please specify where you want to cite from.")
class Cite(ComponentBase, ABC):
component_name = "Cite"
def _run(self, history, **kwargs):
input = "\n- ".join(self.get_input()["content"])
sources = [self._canvas.get_component(cpn_id).output()[1] for cpn_id in self._param.cite_source]
query = []
for role, cnt in history[::-1][:self._param.message_history_window_size]:
if role != "user":continue
query.append(cnt)
query = "\n".join(query)
kbs = KnowledgebaseService.get_by_ids(self._param.kb_ids)
if not kbs:
raise ValueError("Can't find knowledgebases by {}".format(self._param.kb_ids))
embd_nms = list(set([kb.embd_id for kb in kbs]))
assert len(embd_nms) == 1, "Knowledge bases use different embedding models."
embd_mdl = LLMBundle(kbs[0].tenant_id, LLMType.EMBEDDING, embd_nms[0])
rerank_mdl = None
if self._param.rerank_id:
rerank_mdl = LLMBundle(kbs[0].tenant_id, LLMType.RERANK, self._param.rerank_id)
kbinfos = retrievaler.retrieval(query, embd_mdl, kbs[0].tenant_id, self._param.kb_ids,
1, self._param.top_n,
self._param.similarity_threshold, 1 - self._param.keywords_similarity_weight,
aggs=False, rerank_mdl=rerank_mdl)
if not kbinfos["chunks"]: return pd.DataFrame()
df = pd.DataFrame(kbinfos["chunks"])
df["content"] = df["content_with_weight"]
del df["content_with_weight"]
return df

View File

@ -0,0 +1,36 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
from agent.component.base import ComponentBase, ComponentParamBase
class ConcentratorParam(ComponentParamBase):
"""
Define the Concentrator component parameters.
"""
def __init__(self):
super().__init__()
def check(self):
return True
class Concentrator(ComponentBase, ABC):
component_name = "Concentrator"
def _run(self, history, **kwargs):
return Concentrator.be_output("")

View File

@ -0,0 +1,67 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import asyncio
from crawl4ai import AsyncWebCrawler
from agent.component.base import ComponentBase, ComponentParamBase
from api.utils.web_utils import is_valid_url
class CrawlerParam(ComponentParamBase):
"""
Define the Crawler component parameters.
"""
def __init__(self):
super().__init__()
self.proxy = None
self.extract_type = "markdown"
def check(self):
self.check_valid_value(self.extract_type, "Type of content from the crawler", ['html', 'markdown', 'content'])
class Crawler(ComponentBase, ABC):
component_name = "Crawler"
def _run(self, history, **kwargs):
ans = self.get_input()
ans = " - ".join(ans["content"]) if "content" in ans else ""
if not is_valid_url(ans):
return Crawler.be_output("URL not valid")
try:
result = asyncio.run(self.get_web(ans))
return Crawler.be_output(result)
except Exception as e:
return Crawler.be_output(f"An unexpected error occurred: {str(e)}")
async def get_web(self, url):
proxy = self._param.proxy if self._param.proxy else None
async with AsyncWebCrawler(verbose=True, proxy=proxy) as crawler:
result = await crawler.arun(
url=url,
bypass_cache=True
)
if self._param.extract_type == 'html':
return result.cleaned_html
elif self._param.extract_type == 'markdown':
return result.markdown
elif self._param.extract_type == 'content':
result.extracted_content
return result.markdown

View File

@ -14,7 +14,6 @@
# limitations under the License.
#
from abc import ABC
import re
from agent.component.base import ComponentBase, ComponentParamBase
import deepl

View File

@ -13,10 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
from duckduckgo_search import DDGS
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -62,5 +62,5 @@ class DuckDuckGo(ComponentBase, ABC):
return DuckDuckGo.be_output("")
df = pd.DataFrame(duck_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug("df: {df}")
return df

141
agent/component/email.py Normal file
View File

@ -0,0 +1,141 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import json
import smtplib
import logging
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import formataddr
from agent.component.base import ComponentBase, ComponentParamBase
class EmailParam(ComponentParamBase):
"""
Define the Email component parameters.
"""
def __init__(self):
super().__init__()
# Fixed configuration parameters
self.smtp_server = "" # SMTP server address
self.smtp_port = 465 # SMTP port
self.email = "" # Sender email
self.password = "" # Email authorization code
self.sender_name = "" # Sender name
def check(self):
# Check required parameters
self.check_empty(self.smtp_server, "SMTP Server")
self.check_empty(self.email, "Email")
self.check_empty(self.password, "Password")
self.check_empty(self.sender_name, "Sender Name")
class Email(ComponentBase, ABC):
component_name = "Email"
def _run(self, history, **kwargs):
# Get upstream component output and parse JSON
ans = self.get_input()
content = "".join(ans["content"]) if "content" in ans else ""
if not content:
return Email.be_output("No content to send")
success = False
try:
# Parse JSON string passed from upstream
email_data = json.loads(content)
# Validate required fields
if "to_email" not in email_data:
return Email.be_output("Missing required field: to_email")
# Create email object
msg = MIMEMultipart('alternative')
# Properly handle sender name encoding
msg['From'] = formataddr((str(Header(self._param.sender_name,'utf-8')), self._param.email))
msg['To'] = email_data["to_email"]
if "cc_email" in email_data and email_data["cc_email"]:
msg['Cc'] = email_data["cc_email"]
msg['Subject'] = Header(email_data.get("subject", "No Subject"), 'utf-8').encode()
# Use content from email_data or default content
email_content = email_data.get("content", "No content provided")
# msg.attach(MIMEText(email_content, 'plain', 'utf-8'))
msg.attach(MIMEText(email_content, 'html', 'utf-8'))
# Connect to SMTP server and send
logging.info(f"Connecting to SMTP server {self._param.smtp_server}:{self._param.smtp_port}")
context = smtplib.ssl.create_default_context()
with smtplib.SMTP(self._param.smtp_server, self._param.smtp_port) as server:
server.ehlo()
server.starttls(context=context)
server.ehlo()
# Login
logging.info(f"Attempting to login with email: {self._param.email}")
server.login(self._param.email, self._param.password)
# Get all recipient list
recipients = [email_data["to_email"]]
if "cc_email" in email_data and email_data["cc_email"]:
recipients.extend(email_data["cc_email"].split(','))
# Send email
logging.info(f"Sending email to recipients: {recipients}")
try:
server.send_message(msg, self._param.email, recipients)
success = True
except Exception as e:
logging.error(f"Error during send_message: {str(e)}")
# Try alternative method
server.sendmail(self._param.email, recipients, msg.as_string())
success = True
try:
server.quit()
except Exception as e:
# Ignore errors when closing connection
logging.warning(f"Non-fatal error during connection close: {str(e)}")
if success:
return Email.be_output("Email sent successfully")
except json.JSONDecodeError:
error_msg = "Invalid JSON format in input"
logging.error(error_msg)
return Email.be_output(error_msg)
except smtplib.SMTPAuthenticationError:
error_msg = "SMTP Authentication failed. Please check your email and authorization code."
logging.error(error_msg)
return Email.be_output(f"Failed to send email: {error_msg}")
except smtplib.SMTPConnectError:
error_msg = f"Failed to connect to SMTP server {self._param.smtp_server}:{self._param.smtp_port}"
logging.error(error_msg)
return Email.be_output(f"Failed to send email: {error_msg}")
except smtplib.SMTPException as e:
error_msg = f"SMTP error occurred: {str(e)}"
logging.error(error_msg)
return Email.be_output(f"Failed to send email: {error_msg}")
except Exception as e:
error_msg = f"Unexpected error: {str(e)}"
logging.error(error_msg)
return Email.be_output(f"Failed to send email: {error_msg}")

View File

@ -15,12 +15,17 @@
#
from abc import ABC
import re
from copy import deepcopy
import pandas as pd
from peewee import MySQLDatabase, PostgresqlDatabase
from agent.component.base import ComponentBase, ComponentParamBase
import pymysql
import psycopg2
from agent.component import GenerateParam, Generate
import pyodbc
import logging
class ExeSQLParam(ComponentParamBase):
class ExeSQLParam(GenerateParam):
"""
Define the ExeSQL component parameters.
"""
@ -37,60 +42,113 @@ class ExeSQLParam(ComponentParamBase):
self.top_n = 30
def check(self):
self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb'])
super().check()
self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb', 'mssql'])
self.check_empty(self.database, "Database name")
self.check_empty(self.username, "database username")
self.check_empty(self.host, "IP Address")
self.check_positive_integer(self.port, "IP Port")
self.check_empty(self.password, "Database password")
self.check_positive_integer(self.top_n, "Number of records")
if self.database == "rag_flow":
if self.host == "ragflow-mysql":
raise ValueError("For the security reason, it dose not support database named rag_flow.")
if self.password == "infini_rag_flow":
raise ValueError("For the security reason, it dose not support database named rag_flow.")
class ExeSQL(ComponentBase, ABC):
class ExeSQL(Generate, ABC):
component_name = "ExeSQL"
def _run(self, history, **kwargs):
if not hasattr(self, "_loop"):
setattr(self, "_loop", 0)
if self._loop >= self._param.loop:
self._loop = 0
raise Exception("Maximum loop time exceeds. Can't query the correct data via sql statement.")
self._loop += 1
ans = self.get_input()
ans = "".join(ans["content"]) if "content" in ans else ""
ans = re.sub(r'^.*?SELECT ', 'SELECT ', repr(ans), flags=re.IGNORECASE)
def _refactor(self, ans):
ans = re.sub(r"<think>.*</think>", "", ans, flags=re.DOTALL)
match = re.search(r"```sql\s*(.*?)\s*```", ans, re.DOTALL)
if match:
ans = match.group(1) # Query content
return ans
else:
print("no markdown")
ans = re.sub(r'^.*?SELECT ', 'SELECT ', (ans), flags=re.IGNORECASE)
ans = re.sub(r';.*?SELECT ', '; SELECT ', ans, flags=re.IGNORECASE)
ans = re.sub(r';[^;]*$', r';', ans)
if not ans:
return ExeSQL.be_output("SQL statement not found!")
raise Exception("SQL statement not found!")
return ans
def _run(self, history, **kwargs):
ans = self.get_input()
ans = "".join([str(a) for a in ans["content"]]) if "content" in ans else ""
ans = self._refactor(ans)
if self._param.db_type in ["mysql", "mariadb"]:
db = MySQLDatabase(self._param.database, user=self._param.username, host=self._param.host,
port=self._param.port, password=self._param.password)
db = pymysql.connect(db=self._param.database, user=self._param.username, host=self._param.host,
port=self._param.port, password=self._param.password)
elif self._param.db_type == 'postgresql':
db = PostgresqlDatabase(self._param.database, user=self._param.username, host=self._param.host,
port=self._param.port, password=self._param.password)
db = psycopg2.connect(dbname=self._param.database, user=self._param.username, host=self._param.host,
port=self._param.port, password=self._param.password)
elif self._param.db_type == 'mssql':
conn_str = (
r'DRIVER={ODBC Driver 17 for SQL Server};'
r'SERVER=' + self._param.host + ',' + str(self._param.port) + ';'
r'DATABASE=' + self._param.database + ';'
r'UID=' + self._param.username + ';'
r'PWD=' + self._param.password
)
db = pyodbc.connect(conn_str)
try:
db.connect()
cursor = db.cursor()
except Exception as e:
return ExeSQL.be_output("**Error**: \nDatabase Connection Failed! \n" + str(e))
raise Exception("Database Connection Failed! \n" + str(e))
if not hasattr(self, "_loop"):
setattr(self, "_loop", 0)
self._loop += 1
input_list = re.split(r';', ans.replace(r"\n", " "))
sql_res = []
for single_sql in re.split(r';', ans):
if not single_sql:
continue
try:
query = db.execute_sql(single_sql)
single_res = pd.DataFrame([i for i in query.fetchmany(size=self._param.top_n)])
single_res.columns = [i[0] for i in query.description]
sql_res.append({"content": "\nTotal: " + str(query.rowcount) + "\n" + single_res.to_markdown()})
except Exception as e:
sql_res.append({"content": "**Error**:" + str(e) + "\nError SQL Statement:" + single_sql})
pass
for i in range(len(input_list)):
single_sql = input_list[i]
while self._loop <= self._param.loop:
self._loop += 1
if not single_sql:
break
try:
cursor.execute(single_sql)
if cursor.rowcount == 0:
sql_res.append({"content": "No record in the database!"})
break
if self._param.db_type == 'mssql':
single_res = pd.DataFrame.from_records(cursor.fetchmany(self._param.top_n),
columns=[desc[0] for desc in cursor.description])
else:
single_res = pd.DataFrame([i for i in cursor.fetchmany(self._param.top_n)])
single_res.columns = [i[0] for i in cursor.description]
sql_res.append({"content": single_res.to_markdown(index=False, floatfmt=".6f")})
break
except Exception as e:
single_sql = self._regenerate_sql(single_sql, str(e), **kwargs)
single_sql = self._refactor(single_sql)
if self._loop > self._param.loop:
sql_res.append({"content": "Can't query the correct data via SQL statement."})
db.close()
if not sql_res:
return ExeSQL.be_output("No record in the database!")
return ExeSQL.be_output("")
return pd.DataFrame(sql_res)
def _regenerate_sql(self, failed_sql, error_message, **kwargs):
prompt = f'''
## You are the Repair SQL Statement Helper, please modify the original SQL statement based on the SQL query error report.
## The original SQL statement is as follows:{failed_sql}.
## The contents of the SQL query error report is as follows:{error_message}.
## Answer only the modified SQL statement. Please do not give any explanation, just answer the code.
'''
self._param.prompt = prompt
kwargs_ = deepcopy(kwargs)
kwargs_["stream"] = False
response = Generate._run(self, [], **kwargs_)
try:
regenerated_sql = response.loc[0, "content"]
return regenerated_sql
except Exception as e:
logging.error(f"Failed to regenerate SQL: {e}")
return None
def debug(self, **kwargs):
return self._run([], **kwargs)

View File

@ -13,13 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import re
from functools import partial
import pandas as pd
from api.db import LLMType
from api.db.services.conversation_service import structure_answer
from api.db.services.llm_service import LLMBundle
from api.settings import retrievaler
from api import settings
from agent.component.base import ComponentBase, ComponentParamBase
from rag.prompts import message_fit_in
class GenerateParam(ComponentParamBase):
@ -50,11 +53,16 @@ class GenerateParam(ComponentParamBase):
def gen_conf(self):
conf = {}
if self.max_tokens > 0: conf["max_tokens"] = self.max_tokens
if self.temperature > 0: conf["temperature"] = self.temperature
if self.top_p > 0: conf["top_p"] = self.top_p
if self.presence_penalty > 0: conf["presence_penalty"] = self.presence_penalty
if self.frequency_penalty > 0: conf["frequency_penalty"] = self.frequency_penalty
if self.max_tokens > 0:
conf["max_tokens"] = self.max_tokens
if self.temperature > 0:
conf["temperature"] = self.temperature
if self.top_p > 0:
conf["top_p"] = self.top_p
if self.presence_penalty > 0:
conf["presence_penalty"] = self.presence_penalty
if self.frequency_penalty > 0:
conf["frequency_penalty"] = self.frequency_penalty
return conf
@ -62,58 +70,118 @@ class Generate(ComponentBase):
component_name = "Generate"
def get_dependent_components(self):
cpnts = [para["component_id"] for para in self._param.parameters]
return cpnts
inputs = self.get_input_elements()
cpnts = set([i["key"] for i in inputs[1:] if i["key"].lower().find("answer") < 0 and i["key"].lower().find("begin") < 0])
return list(cpnts)
def set_cite(self, retrieval_res, answer):
retrieval_res = retrieval_res.dropna(subset=["vector", "content_ltks"]).reset_index(drop=True)
if "empty_response" in retrieval_res.columns:
retrieval_res["empty_response"].fillna("", inplace=True)
answer, idx = retrievaler.insert_citations(answer, [ck["content_ltks"] for _, ck in retrieval_res.iterrows()],
[ck["vector"] for _, ck in retrieval_res.iterrows()],
LLMBundle(self._canvas.get_tenant_id(), LLMType.EMBEDDING,
self._canvas.get_embedding_model()), tkweight=0.7,
vtweight=0.3)
chunks = json.loads(retrieval_res["chunks"][0])
answer, idx = settings.retrievaler.insert_citations(answer,
[ck["content_ltks"] for ck in chunks],
[ck["vector"] for ck in chunks],
LLMBundle(self._canvas.get_tenant_id(), LLMType.EMBEDDING,
self._canvas.get_embedding_model()), tkweight=0.7,
vtweight=0.3)
doc_ids = set([])
recall_docs = []
for i in idx:
did = retrieval_res.loc[int(i), "doc_id"]
if did in doc_ids: continue
did = chunks[int(i)]["doc_id"]
if did in doc_ids:
continue
doc_ids.add(did)
recall_docs.append({"doc_id": did, "doc_name": retrieval_res.loc[int(i), "docnm_kwd"]})
recall_docs.append({"doc_id": did, "doc_name": chunks[int(i)]["docnm_kwd"]})
del retrieval_res["vector"]
del retrieval_res["content_ltks"]
for c in chunks:
del c["vector"]
del c["content_ltks"]
reference = {
"chunks": [ck.to_dict() for _, ck in retrieval_res.iterrows()],
"chunks": chunks,
"doc_aggs": recall_docs
}
if answer.lower().find("invalid key") >= 0 or answer.lower().find("invalid api") >= 0:
answer += " Please set LLM API-Key in 'User Setting -> Model Providers -> API-Key'"
answer += " Please set LLM API-Key in 'User Setting -> Model providers -> API-Key'"
res = {"content": answer, "reference": reference}
res = structure_answer(None, res, "", "")
return res
def get_input_elements(self):
key_set = set([])
res = [{"key": "user", "name": "Input your question here:"}]
for r in re.finditer(r"\{([a-z]+[:@][a-z0-9_-]+)\}", self._param.prompt, flags=re.IGNORECASE):
cpn_id = r.group(1)
if cpn_id in key_set:
continue
if cpn_id.lower().find("begin@") == 0:
cpn_id, key = cpn_id.split("@")
for p in self._canvas.get_component(cpn_id)["obj"]._param.query:
if p["key"] != key:
continue
res.append({"key": r.group(1), "name": p["name"]})
key_set.add(r.group(1))
continue
cpn_nm = self._canvas.get_component_name(cpn_id)
if not cpn_nm:
continue
res.append({"key": cpn_id, "name": cpn_nm})
key_set.add(cpn_id)
return res
def _run(self, history, **kwargs):
chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id)
prompt = self._param.prompt
retrieval_res = self.get_input()
input = (" - " + "\n - ".join(retrieval_res["content"])) if "content" in retrieval_res else ""
for para in self._param.parameters:
cpn = self._canvas.get_component(para["component_id"])["obj"]
retrieval_res = []
self._param.inputs = []
for para in self.get_input_elements()[1:]:
if para["key"].lower().find("begin@") == 0:
cpn_id, key = para["key"].split("@")
for p in self._canvas.get_component(cpn_id)["obj"]._param.query:
if p["key"] == key:
kwargs[para["key"]] = p.get("value", "")
self._param.inputs.append(
{"component_id": para["key"], "content": kwargs[para["key"]]})
break
else:
assert False, f"Can't find parameter '{key}' for {cpn_id}"
continue
component_id = para["key"]
cpn = self._canvas.get_component(component_id)["obj"]
if cpn.component_name.lower() == "answer":
hist = self._canvas.get_history(1)
if hist:
hist = hist[0]["content"]
else:
hist = ""
kwargs[para["key"]] = hist
continue
_, out = cpn.output(allow_partial=False)
if "content" not in out.columns:
kwargs[para["key"]] = "Nothing"
kwargs[para["key"]] = ""
else:
kwargs[para["key"]] = " - " + "\n - ".join(out["content"])
if cpn.component_name.lower() == "retrieval":
retrieval_res.append(out)
kwargs[para["key"]] = " - " + "\n - ".join([o if isinstance(o, str) else str(o) for o in out["content"]])
self._param.inputs.append({"component_id": para["key"], "content": kwargs[para["key"]]})
if retrieval_res:
retrieval_res = pd.concat(retrieval_res, ignore_index=True)
else:
retrieval_res = pd.DataFrame([])
kwargs["input"] = input
for n, v in kwargs.items():
# prompt = re.sub(r"\{%s\}"%n, re.escape(str(v)), prompt)
prompt = re.sub(r"\{%s\}" % n, str(v), prompt)
prompt = re.sub(r"\{%s\}" % re.escape(n), str(v).replace("\\", " "), prompt)
if not self._param.inputs and prompt.find("{input}") >= 0:
retrieval_res = self.get_input()
input = (" - " + "\n - ".join(
[c for c in retrieval_res["content"] if isinstance(c, str)])) if "content" in retrieval_res else ""
prompt = re.sub(r"\{input\}", re.escape(input), prompt)
downstreams = self._canvas.get_component(self._id)["downstream"]
if kwargs.get("stream") and len(downstreams) == 1 and self._canvas.get_component(downstreams[0])[
@ -121,36 +189,64 @@ class Generate(ComponentBase):
return partial(self.stream_output, chat_mdl, prompt, retrieval_res)
if "empty_response" in retrieval_res.columns and not "".join(retrieval_res["content"]):
res = {"content": "\n- ".join(retrieval_res["empty_response"]) if "\n- ".join(
retrieval_res["empty_response"]) else "Nothing found in knowledgebase!", "reference": []}
return Generate.be_output(res)
empty_res = "\n- ".join([str(t) for t in retrieval_res["empty_response"] if str(t)])
res = {"content": empty_res if empty_res else "Nothing found in knowledgebase!", "reference": []}
return pd.DataFrame([res])
ans = chat_mdl.chat(prompt, self._canvas.get_history(self._param.message_history_window_size),
self._param.gen_conf())
if self._param.cite and "content_ltks" in retrieval_res.columns and "vector" in retrieval_res.columns:
df = self.set_cite(retrieval_res, ans)
return pd.DataFrame(df)
msg = self._canvas.get_history(self._param.message_history_window_size)
if len(msg) < 1:
msg.append({"role": "user", "content": "Output: "})
_, msg = message_fit_in([{"role": "system", "content": prompt}, *msg], int(chat_mdl.max_length * 0.97))
if len(msg) < 2:
msg.append({"role": "user", "content": "Output: "})
ans = chat_mdl.chat(msg[0]["content"], msg[1:], self._param.gen_conf())
ans = re.sub(r"<think>.*</think>", "", ans, flags=re.DOTALL)
if self._param.cite and "chunks" in retrieval_res.columns:
res = self.set_cite(retrieval_res, ans)
return pd.DataFrame([res])
return Generate.be_output(ans)
def stream_output(self, chat_mdl, prompt, retrieval_res):
res = None
if "empty_response" in retrieval_res.columns and not "".join(retrieval_res["content"]):
res = {"content": "\n- ".join(retrieval_res["empty_response"]) if "\n- ".join(
retrieval_res["empty_response"]) else "Nothing found in knowledgebase!", "reference": []}
empty_res = "\n- ".join([str(t) for t in retrieval_res["empty_response"] if str(t)])
res = {"content": empty_res if empty_res else "Nothing found in knowledgebase!", "reference": []}
yield res
self.set_output(res)
return
msg = self._canvas.get_history(self._param.message_history_window_size)
if msg and msg[0]['role'] == 'assistant':
msg.pop(0)
if len(msg) < 1:
msg.append({"role": "user", "content": "Output: "})
_, msg = message_fit_in([{"role": "system", "content": prompt}, *msg], int(chat_mdl.max_length * 0.97))
if len(msg) < 2:
msg.append({"role": "user", "content": "Output: "})
answer = ""
for ans in chat_mdl.chat_streamly(prompt, self._canvas.get_history(self._param.message_history_window_size),
self._param.gen_conf()):
for ans in chat_mdl.chat_streamly(msg[0]["content"], msg[1:], self._param.gen_conf()):
res = {"content": ans, "reference": []}
answer = ans
yield res
if self._param.cite and "content_ltks" in retrieval_res.columns and "vector" in retrieval_res.columns:
if self._param.cite and "chunks" in retrieval_res.columns:
res = self.set_cite(retrieval_res, answer)
yield res
self.set_output(res)
self.set_output(Generate.be_output(res))
def debug(self, **kwargs):
chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id)
prompt = self._param.prompt
for para in self._param.debug_inputs:
kwargs[para["key"]] = para.get("value", "")
for n, v in kwargs.items():
prompt = re.sub(r"\{%s\}" % re.escape(n), str(v).replace("\\", " "), prompt)
u = kwargs.get("user")
ans = chat_mdl.chat(prompt, [{"role": "user", "content": u if u else "Output: "}], self._param.gen_conf())
return pd.DataFrame([ans])

View File

@ -13,10 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
import pandas as pd
import requests
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -57,5 +57,5 @@ class GitHub(ComponentBase, ABC):
return GitHub.be_output("")
df = pd.DataFrame(github_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {df}")
return df

View File

@ -13,10 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
from serpapi import GoogleSearch
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -85,12 +85,12 @@ class Google(ComponentBase, ABC):
"hl": self._param.language, "num": self._param.top_n})
google_res = [{"content": '<a href="' + i["link"] + '">' + i["title"] + '</a> ' + i["snippet"]} for i in
client.get_dict()["organic_results"]]
except Exception as e:
except Exception:
return Google.be_output("**ERROR**: Existing Unavailable Parameters!")
if not google_res:
return Google.be_output("")
df = pd.DataFrame(google_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {df}")
return df

View File

@ -13,9 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
from scholarly import scholarly
@ -58,13 +58,13 @@ class GoogleScholar(ComponentBase, ABC):
'pub_url'] + '"></a> ' + "\n author: " + ",".join(pub['bib']['author']) + '\n Abstract: ' + pub[
'bib'].get('abstract', 'no abstract')})
except StopIteration or Exception as e:
print("**ERROR** " + str(e))
except StopIteration or Exception:
logging.exception("GoogleScholar")
break
if not scholar_res:
return GoogleScholar.be_output("")
df = pd.DataFrame(scholar_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {df}")
return df

132
agent/component/invoke.py Normal file
View File

@ -0,0 +1,132 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import re
from abc import ABC
import requests
from deepdoc.parser import HtmlParser
from agent.component.base import ComponentBase, ComponentParamBase
class InvokeParam(ComponentParamBase):
"""
Define the Crawler component parameters.
"""
def __init__(self):
super().__init__()
self.proxy = None
self.headers = ""
self.method = "get"
self.variables = []
self.url = ""
self.timeout = 60
self.clean_html = False
self.datatype = "json" # New parameter to determine data posting type
def check(self):
self.check_valid_value(self.method.lower(), "Type of content from the crawler", ['get', 'post', 'put'])
self.check_empty(self.url, "End point URL")
self.check_positive_integer(self.timeout, "Timeout time in second")
self.check_boolean(self.clean_html, "Clean HTML")
self.check_valid_value(self.datatype.lower(), "Data post type", ['json', 'formdata']) # Check for valid datapost value
class Invoke(ComponentBase, ABC):
component_name = "Invoke"
def _run(self, history, **kwargs):
args = {}
for para in self._param.variables:
if para.get("component_id"):
if '@' in para["component_id"]:
component = para["component_id"].split('@')[0]
field = para["component_id"].split('@')[1]
cpn = self._canvas.get_component(component)["obj"]
for param in cpn._param.query:
if param["key"] == field:
if "value" in param:
args[para["key"]] = param["value"]
else:
cpn = self._canvas.get_component(para["component_id"])["obj"]
if cpn.component_name.lower() == "answer":
args[para["key"]] = self._canvas.get_history(1)[0]["content"]
continue
_, out = cpn.output(allow_partial=False)
if not out.empty:
args[para["key"]] = "\n".join(out["content"])
else:
args[para["key"]] = para["value"]
url = self._param.url.strip()
if url.find("http") != 0:
url = "http://" + url
method = self._param.method.lower()
headers = {}
if self._param.headers:
headers = json.loads(self._param.headers)
proxies = None
if re.sub(r"https?:?/?/?", "", self._param.proxy):
proxies = {"http": self._param.proxy, "https": self._param.proxy}
if method == 'get':
response = requests.get(url=url,
params=args,
headers=headers,
proxies=proxies,
timeout=self._param.timeout)
if self._param.clean_html:
sections = HtmlParser()(None, response.content)
return Invoke.be_output("\n".join(sections))
return Invoke.be_output(response.text)
if method == 'put':
if self._param.datatype.lower() == 'json':
response = requests.put(url=url,
json=args,
headers=headers,
proxies=proxies,
timeout=self._param.timeout)
else:
response = requests.put(url=url,
data=args,
headers=headers,
proxies=proxies,
timeout=self._param.timeout)
if self._param.clean_html:
sections = HtmlParser()(None, response.content)
return Invoke.be_output("\n".join(sections))
return Invoke.be_output(response.text)
if method == 'post':
if self._param.datatype.lower() == 'json':
response = requests.post(url=url,
json=args,
headers=headers,
proxies=proxies,
timeout=self._param.timeout)
else:
response = requests.post(url=url,
data=args,
headers=headers,
proxies=proxies,
timeout=self._param.timeout)
if self._param.clean_html:
sections = HtmlParser()(None, response.content)
return Invoke.be_output("\n".join(sections))
return Invoke.be_output(response.text)

View File

@ -0,0 +1,45 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
from agent.component.base import ComponentBase, ComponentParamBase
class IterationParam(ComponentParamBase):
"""
Define the Iteration component parameters.
"""
def __init__(self):
super().__init__()
self.delimiter = ","
def check(self):
self.check_empty(self.delimiter, "Delimiter")
class Iteration(ComponentBase, ABC):
component_name = "Iteration"
def get_start(self):
for cid in self._canvas.components.keys():
if self._canvas.get_component(cid)["obj"].component_name.lower() != "iterationitem":
continue
if self._canvas.get_component(cid)["parent_id"] == self._id:
return self._canvas.get_component(cid)
def _run(self, history, **kwargs):
return self.output(allow_partial=False)[1]

View File

@ -0,0 +1,53 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import pandas as pd
from agent.component.base import ComponentBase, ComponentParamBase
class IterationItemParam(ComponentParamBase):
"""
Define the IterationItem component parameters.
"""
def check(self):
return True
class IterationItem(ComponentBase, ABC):
component_name = "IterationItem"
def __init__(self, canvas, id, param: ComponentParamBase):
super().__init__(canvas, id, param)
self._idx = 0
def _run(self, history, **kwargs):
parent = self.get_parent()
ans = parent.get_input()
ans = parent._param.delimiter.join(ans["content"]) if "content" in ans else ""
ans = [a.strip() for a in ans.split(parent._param.delimiter)]
if not ans:
self._idx = -1
return pd.DataFrame()
df = pd.DataFrame([{"content": ans[self._idx]}])
self._idx += 1
if self._idx >= len(ans):
self._idx = -1
return df
def end(self):
return self._idx == -1

130
agent/component/jin10.py Normal file
View File

@ -0,0 +1,130 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
from abc import ABC
import pandas as pd
import requests
from agent.component.base import ComponentBase, ComponentParamBase
class Jin10Param(ComponentParamBase):
"""
Define the Jin10 component parameters.
"""
def __init__(self):
super().__init__()
self.type = "flash"
self.secret_key = "xxx"
self.flash_type = '1'
self.calendar_type = 'cj'
self.calendar_datatype = 'data'
self.symbols_type = 'GOODS'
self.symbols_datatype = 'symbols'
self.contain = ""
self.filter = ""
def check(self):
self.check_valid_value(self.type, "Type", ['flash', 'calendar', 'symbols', 'news'])
self.check_valid_value(self.flash_type, "Flash Type", ['1', '2', '3', '4', '5'])
self.check_valid_value(self.calendar_type, "Calendar Type", ['cj', 'qh', 'hk', 'us'])
self.check_valid_value(self.calendar_datatype, "Calendar DataType", ['data', 'event', 'holiday'])
self.check_valid_value(self.symbols_type, "Symbols Type", ['GOODS', 'FOREX', 'FUTURE', 'CRYPTO'])
self.check_valid_value(self.symbols_datatype, 'Symbols DataType', ['symbols', 'quotes'])
class Jin10(ComponentBase, ABC):
component_name = "Jin10"
def _run(self, history, **kwargs):
ans = self.get_input()
ans = " - ".join(ans["content"]) if "content" in ans else ""
if not ans:
return Jin10.be_output("")
jin10_res = []
headers = {'secret-key': self._param.secret_key}
try:
if self._param.type == "flash":
params = {
'category': self._param.flash_type,
'contain': self._param.contain,
'filter': self._param.filter
}
response = requests.get(
url='https://open-data-api.jin10.com/data-api/flash?category=' + self._param.flash_type,
headers=headers, data=json.dumps(params))
response = response.json()
for i in response['data']:
jin10_res.append({"content": i['data']['content']})
if self._param.type == "calendar":
params = {
'category': self._param.calendar_type
}
response = requests.get(
url='https://open-data-api.jin10.com/data-api/calendar/' + self._param.calendar_datatype + '?category=' + self._param.calendar_type,
headers=headers, data=json.dumps(params))
response = response.json()
jin10_res.append({"content": pd.DataFrame(response['data']).to_markdown()})
if self._param.type == "symbols":
params = {
'type': self._param.symbols_type
}
if self._param.symbols_datatype == "quotes":
params['codes'] = 'BTCUSD'
response = requests.get(
url='https://open-data-api.jin10.com/data-api/' + self._param.symbols_datatype + '?type=' + self._param.symbols_type,
headers=headers, data=json.dumps(params))
response = response.json()
if self._param.symbols_datatype == "symbols":
for i in response['data']:
i['Commodity Code'] = i['c']
i['Stock Exchange'] = i['e']
i['Commodity Name'] = i['n']
i['Commodity Type'] = i['t']
del i['c'], i['e'], i['n'], i['t']
if self._param.symbols_datatype == "quotes":
for i in response['data']:
i['Selling Price'] = i['a']
i['Buying Price'] = i['b']
i['Commodity Code'] = i['c']
i['Stock Exchange'] = i['e']
i['Highest Price'] = i['h']
i['Yesterdays Closing Price'] = i['hc']
i['Lowest Price'] = i['l']
i['Opening Price'] = i['o']
i['Latest Price'] = i['p']
i['Market Quote Time'] = i['t']
del i['a'], i['b'], i['c'], i['e'], i['h'], i['hc'], i['l'], i['o'], i['p'], i['t']
jin10_res.append({"content": pd.DataFrame(response['data']).to_markdown()})
if self._param.type == "news":
params = {
'contain': self._param.contain,
'filter': self._param.filter
}
response = requests.get(
url='https://open-data-api.jin10.com/data-api/news',
headers=headers, data=json.dumps(params))
response = response.json()
jin10_res.append({"content": pd.DataFrame(response['data']).to_markdown()})
except Exception as e:
return Jin10.be_output("**ERROR**: " + str(e))
if not jin10_res:
return Jin10.be_output("")
return pd.DataFrame(jin10_res)

View File

@ -13,12 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import re
from abc import ABC
from api.db import LLMType
from api.db.services.llm_service import LLMBundle
from agent.component import GenerateParam, Generate
from agent.settings import DEBUG
class KeywordExtractParam(GenerateParam):
@ -50,16 +50,17 @@ class KeywordExtract(Generate, ABC):
component_name = "KeywordExtract"
def _run(self, history, **kwargs):
q = ""
for r, c in self._canvas.history[::-1]:
if r == "user":
q += c
break
query = self.get_input()
query = str(query["content"][0]) if "content" in query else ""
chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id)
ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": q}],
ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": query}],
self._param.gen_conf())
ans = re.sub(r"<think>.*</think>", "", ans, flags=re.DOTALL)
ans = re.sub(r".*keyword:", "", ans).strip()
if DEBUG: print(ans, ":::::::::::::::::::::::::::::::::")
logging.debug(f"ans: {ans}")
return KeywordExtract.be_output(ans)
def debug(self, **kwargs):
return self._run([], **kwargs)

View File

@ -13,11 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
from Bio import Entrez
import re
import pandas as pd
import xml.etree.ElementTree as ET
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -47,12 +48,15 @@ class PubMed(ComponentBase, ABC):
try:
Entrez.email = self._param.email
pubmedids = Entrez.read(Entrez.esearch(db='pubmed', retmax=self._param.top_n, term=ans))['IdList']
pubmedcnt = ET.fromstring(
Entrez.efetch(db='pubmed', id=",".join(pubmedids), retmode="xml").read().decode("utf-8"))
pubmedcnt = ET.fromstring(re.sub(r'<(/?)b>|<(/?)i>', '', Entrez.efetch(db='pubmed', id=",".join(pubmedids),
retmode="xml").read().decode(
"utf-8")))
pubmed_res = [{"content": 'Title:' + child.find("MedlineCitation").find("Article").find(
"ArticleTitle").text + '\nUrl:<a href=" https://pubmed.ncbi.nlm.nih.gov/' + child.find(
"MedlineCitation").find("PMID").text + '">' + '</a>\n' + 'Abstract:' + child.find(
"MedlineCitation").find("Article").find("Abstract").find("AbstractText").text} for child in
"MedlineCitation").find("PMID").text + '">' + '</a>\n' + 'Abstract:' + (
child.find("MedlineCitation").find("Article").find("Abstract").find(
"AbstractText").text if child.find("MedlineCitation").find(
"Article").find("Abstract") else "No abstract available")} for child in
pubmedcnt.findall("PubmedArticle")]
except Exception as e:
return PubMed.be_output("**ERROR**: " + str(e))
@ -61,5 +65,5 @@ class PubMed(ComponentBase, ABC):
return PubMed.be_output("")
df = pd.DataFrame(pubmed_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {df}")
return df

View File

@ -51,7 +51,7 @@ class QWeatherParam(ComponentParamBase):
['zh', 'zh-hant', 'en', 'de', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'hi', 'th', 'ar', 'pt',
'bn', 'ms', 'nl', 'el', 'la', 'sv', 'id', 'pl', 'tr', 'cs', 'et', 'vi', 'fil', 'fi',
'he', 'is', 'nb'])
self.check_vaild_value(self.time_period, "Time period", ['now', '3d', '7d', '10d', '15d', '30d'])
self.check_valid_value(self.time_period, "Time period", ['now', '3d', '7d', '10d', '15d', '30d'])
class QWeather(ComponentBase, ABC):

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
from api.db import LLMType
from api.db.services.llm_service import LLMBundle
@ -70,11 +71,13 @@ class Relevant(Generate, ABC):
ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": ans}],
self._param.gen_conf())
print(ans, ":::::::::::::::::::::::::::::::::")
logging.debug(ans)
if ans.lower().find("yes") >= 0:
return Relevant.be_output(self._param.yes)
if ans.lower().find("no") >= 0:
return Relevant.be_output(self._param.no)
assert False, f"Relevant component got: {ans}"
def debug(self, **kwargs):
return self._run([], **kwargs)

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import logging
from abc import ABC
import pandas as pd
@ -20,8 +22,11 @@ import pandas as pd
from api.db import LLMType
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import LLMBundle
from api.settings import retrievaler
from api import settings
from agent.component.base import ComponentBase, ComponentParamBase
from rag.app.tag import label_question
from rag.prompts import kb_prompt
from rag.utils.tavily_conn import Tavily
class RetrievalParam(ComponentParamBase):
@ -38,51 +43,69 @@ class RetrievalParam(ComponentParamBase):
self.kb_ids = []
self.rerank_id = ""
self.empty_response = ""
self.tavily_api_key = ""
self.use_kg = False
def check(self):
self.check_decimal_float(self.similarity_threshold, "[Retrieval] Similarity threshold")
self.check_decimal_float(self.keywords_similarity_weight, "[Retrieval] Keywords similarity weight")
self.check_decimal_float(self.keywords_similarity_weight, "[Retrieval] Keyword similarity weight")
self.check_positive_number(self.top_n, "[Retrieval] Top N")
self.check_empty(self.kb_ids, "[Retrieval] Knowledge bases")
class Retrieval(ComponentBase, ABC):
component_name = "Retrieval"
def _run(self, history, **kwargs):
query = []
for role, cnt in history[::-1][:self._param.message_history_window_size]:
if role != "user":continue
query.append(cnt)
query = "\n".join(query)
query = self.get_input()
query = str(query["content"][0]) if "content" in query else ""
kbs = KnowledgebaseService.get_by_ids(self._param.kb_ids)
if not kbs:
raise ValueError("Can't find knowledgebases by {}".format(self._param.kb_ids))
return Retrieval.be_output("")
embd_nms = list(set([kb.embd_id for kb in kbs]))
assert len(embd_nms) == 1, "Knowledge bases use different embedding models."
embd_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.EMBEDDING, embd_nms[0])
self._canvas.set_embedding_model(embd_nms[0])
embd_mdl = None
if embd_nms:
embd_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.EMBEDDING, embd_nms[0])
self._canvas.set_embedding_model(embd_nms[0])
rerank_mdl = None
if self._param.rerank_id:
rerank_mdl = LLMBundle(kbs[0].tenant_id, LLMType.RERANK, self._param.rerank_id)
kbinfos = retrievaler.retrieval(query, embd_mdl, kbs[0].tenant_id, self._param.kb_ids,
if kbs:
kbinfos = settings.retrievaler.retrieval(query, embd_mdl, kbs[0].tenant_id, self._param.kb_ids,
1, self._param.top_n,
self._param.similarity_threshold, 1 - self._param.keywords_similarity_weight,
aggs=False, rerank_mdl=rerank_mdl)
aggs=False, rerank_mdl=rerank_mdl,
rank_feature=label_question(query, kbs))
else:
kbinfos = {"chunks": [], "doc_aggs": []}
if self._param.use_kg and kbs:
ck = settings.kg_retrievaler.retrieval(query,
[kbs[0].tenant_id],
self._param.kb_ids,
embd_mdl,
LLMBundle(kbs[0].tenant_id, LLMType.CHAT))
if ck["content_with_weight"]:
kbinfos["chunks"].insert(0, ck)
if self._param.tavily_api_key:
tav = Tavily(self._param.tavily_api_key)
tav_res = tav.retrieve_chunks(query)
kbinfos["chunks"].extend(tav_res["chunks"])
kbinfos["doc_aggs"].extend(tav_res["doc_aggs"])
if not kbinfos["chunks"]:
df = Retrieval.be_output("")
df["empty_response"] = self._param.empty_response
if self._param.empty_response and self._param.empty_response.strip():
df["empty_response"] = self._param.empty_response
return df
df = pd.DataFrame(kbinfos["chunks"])
df["content"] = df["content_with_weight"]
del df["content_with_weight"]
print(">>>>>>>>>>>>>>>>>>>>>>>>>>\n", query, df)
return df
df = pd.DataFrame({"content": kb_prompt(kbinfos, 200000), "chunks": json.dumps(kbinfos["chunks"])})
logging.debug("{} {}".format(query, df))
return df.dropna()

View File

@ -14,59 +14,81 @@
# limitations under the License.
#
from abc import ABC
from api.db import LLMType
from api.db.services.llm_service import LLMBundle
from agent.component import GenerateParam, Generate
from rag.prompts import full_question
class RewriteQuestionParam(GenerateParam):
"""
Define the QuestionRewrite component parameters.
"""
def __init__(self):
super().__init__()
self.temperature = 0.9
self.prompt = ""
self.loop = 1
self.language = ""
def check(self):
super().check()
def get_prompt(self):
self.prompt = """
You are an expert at query expansion to generate a paraphrasing of a question.
I can't retrieval relevant information from the knowledge base by using user's question directly.
You need to expand or paraphrase user's question by multiple ways such as using synonyms words/phrase,
writing the abbreviation in its entirety, adding some extra descriptions or explanations,
changing the way of expression, translating the original question into another language (English/Chinese), etc.
And return 5 versions of question and one is from translation.
Just list the question. No other words are needed.
"""
return self.prompt
class RewriteQuestion(Generate, ABC):
component_name = "RewriteQuestion"
def _run(self, history, **kwargs):
if not hasattr(self, "_loop"):
setattr(self, "_loop", 0)
if self._loop >= self._param.loop:
self._loop = 0
raise Exception("Maximum loop time exceeds. Can't find relevant information.")
self._loop += 1
q = "Question: "
for r, c in self._canvas.history[::-1]:
if r == "user":
q += c
break
chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id)
ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": q}],
self._param.gen_conf())
print(ans, ":::::::::::::::::::::::::::::::::")
hist = self._canvas.get_history(self._param.message_history_window_size)
query = self.get_input()
query = str(query["content"][0]) if "content" in query else ""
messages = [h for h in hist if h["role"]!="system"]
if messages[-1]["role"] != "user":
messages.append({"role": "user", "content": query})
ans = full_question(self._canvas.get_tenant_id(), self._param.llm_id, messages, self.gen_lang(self._param.language))
self._canvas.history.pop()
self._canvas.history.append(("user", ans))
return RewriteQuestion.be_output(ans)
@staticmethod
def gen_lang(language):
# convert code lang to language word for the prompt
language_dict = {'af': 'Afrikaans', 'ak': 'Akan', 'sq': 'Albanian', 'ws': 'Samoan', 'am': 'Amharic',
'ar': 'Arabic', 'hy': 'Armenian', 'az': 'Azerbaijani', 'eu': 'Basque', 'be': 'Belarusian',
'bem': 'Bemba', 'bn': 'Bengali', 'bh': 'Bihari',
'xx-bork': 'Bork', 'bs': 'Bosnian', 'br': 'Breton', 'bg': 'Bulgarian', 'bt': 'Bhutani',
'km': 'Cambodian', 'ca': 'Catalan', 'chr': 'Cherokee', 'ny': 'Chichewa', 'zh-cn': 'Chinese',
'zh-tw': 'Chinese', 'co': 'Corsican',
'hr': 'Croatian', 'cs': 'Czech', 'da': 'Danish', 'nl': 'Dutch', 'xx-elmer': 'Elmer',
'en': 'English', 'eo': 'Esperanto', 'et': 'Estonian', 'ee': 'Ewe', 'fo': 'Faroese',
'tl': 'Filipino', 'fi': 'Finnish', 'fr': 'French',
'fy': 'Frisian', 'gaa': 'Ga', 'gl': 'Galician', 'ka': 'Georgian', 'de': 'German',
'el': 'Greek', 'kl': 'Greenlandic', 'gn': 'Guarani', 'gu': 'Gujarati', 'xx-hacker': 'Hacker',
'ht': 'Haitian Creole', 'ha': 'Hausa', 'haw': 'Hawaiian',
'iw': 'Hebrew', 'hi': 'Hindi', 'hu': 'Hungarian', 'is': 'Icelandic', 'ig': 'Igbo',
'id': 'Indonesian', 'ia': 'Interlingua', 'ga': 'Irish', 'it': 'Italian', 'ja': 'Japanese',
'jw': 'Javanese', 'kn': 'Kannada', 'kk': 'Kazakh', 'rw': 'Kinyarwanda',
'rn': 'Kirundi', 'xx-klingon': 'Klingon', 'kg': 'Kongo', 'ko': 'Korean', 'kri': 'Krio',
'ku': 'Kurdish', 'ckb': 'Kurdish (Sorani)', 'ky': 'Kyrgyz', 'lo': 'Laothian', 'la': 'Latin',
'lv': 'Latvian', 'ln': 'Lingala', 'lt': 'Lithuanian',
'loz': 'Lozi', 'lg': 'Luganda', 'ach': 'Luo', 'mk': 'Macedonian', 'mg': 'Malagasy',
'ms': 'Malay', 'ml': 'Malayalam', 'mt': 'Maltese', 'mv': 'Maldivian', 'mi': 'Maori',
'mr': 'Marathi', 'mfe': 'Mauritian Creole', 'mo': 'Moldavian', 'mn': 'Mongolian',
'sr-me': 'Montenegrin', 'my': 'Burmese', 'ne': 'Nepali', 'pcm': 'Nigerian Pidgin',
'nso': 'Northern Sotho', 'no': 'Norwegian', 'nn': 'Norwegian Nynorsk', 'oc': 'Occitan',
'or': 'Oriya', 'om': 'Oromo', 'ps': 'Pashto', 'fa': 'Persian',
'xx-pirate': 'Pirate', 'pl': 'Polish', 'pt': 'Portuguese', 'pt-br': 'Portuguese (Brazilian)',
'pt-pt': 'Portuguese (Portugal)', 'pa': 'Punjabi', 'qu': 'Quechua', 'ro': 'Romanian',
'rm': 'Romansh', 'nyn': 'Runyankole', 'ru': 'Russian', 'gd': 'Scots Gaelic',
'sr': 'Serbian', 'sh': 'Serbo-Croatian', 'st': 'Sesotho', 'tn': 'Setswana',
'crs': 'Seychellois Creole', 'sn': 'Shona', 'sd': 'Sindhi', 'si': 'Sinhalese', 'sk': 'Slovak',
'sl': 'Slovenian', 'so': 'Somali', 'es': 'Spanish', 'es-419': 'Spanish (Latin America)',
'su': 'Sundanese',
'sw': 'Swahili', 'sv': 'Swedish', 'tg': 'Tajik', 'ta': 'Tamil', 'tt': 'Tatar', 'te': 'Telugu',
'th': 'Thai', 'ti': 'Tigrinya', 'to': 'Tongan', 'lua': 'Tshiluba', 'tum': 'Tumbuka',
'tr': 'Turkish', 'tk': 'Turkmen', 'tw': 'Twi',
'ug': 'Uyghur', 'uk': 'Ukrainian', 'ur': 'Urdu', 'uz': 'Uzbek', 'vu': 'Vanuatu',
'vi': 'Vietnamese', 'cy': 'Welsh', 'wo': 'Wolof', 'xh': 'Xhosa', 'yi': 'Yiddish',
'yo': 'Yoruba', 'zu': 'Zulu'}
if language in language_dict:
return language_dict[language]
else:
return ""

View File

@ -41,44 +41,48 @@ class SwitchParam(ComponentParamBase):
def check(self):
self.check_empty(self.conditions, "[Switch] conditions")
for cond in self.conditions:
if not cond["to"]: raise ValueError(f"[Switch] 'To' can not be empty!")
if cond["logical_operator"] not in ["and", "or"] and len(cond["items"]) > 1:
raise ValueError(f"[Switch] Please set logical_operator correctly!")
if not cond["to"]:
raise ValueError("[Switch] 'To' can not be empty!")
class Switch(ComponentBase, ABC):
component_name = "Switch"
def get_dependent_components(self):
res = []
for cond in self._param.conditions:
for item in cond["items"]:
if not item["cpn_id"]:
continue
if item["cpn_id"].lower().find("begin") >= 0 or item["cpn_id"].lower().find("answer") >= 0:
continue
cid = item["cpn_id"].split("@")[0]
res.append(cid)
return list(set(res))
def _run(self, history, **kwargs):
for cond in self._param.conditions:
if len(cond["items"]) == 1:
out = self._canvas.get_component(cond["items"][0]["cpn_id"])["obj"].output()[1]
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
if self.process_operator(cpn_input, cond["items"][0]["operator"], cond["items"][0]["value"]):
return Switch.be_output(cond["to"])
continue
if cond["logical_operator"] == "and":
res = True
for item in cond["items"]:
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
if not self.process_operator(cpn_input, item["operator"], item["value"]):
res = False
break
if res:
return Switch.be_output(cond["to"])
continue
res = False
res = []
for item in cond["items"]:
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
if self.process_operator(cpn_input, item["operator"], item["value"]):
res = True
break
if res:
if not item["cpn_id"]:
continue
cid = item["cpn_id"].split("@")[0]
if item["cpn_id"].find("@") > 0:
cpn_id, key = item["cpn_id"].split("@")
for p in self._canvas.get_component(cid)["obj"]._param.query:
if p["key"] == key:
res.append(self.process_operator(p.get("value",""), item["operator"], item.get("value", "")))
break
else:
out = self._canvas.get_component(cid)["obj"].output(allow_partial=False)[1]
cpn_input = "" if "content" not in out.columns else " ".join([str(s) for s in out["content"]])
res.append(self.process_operator(cpn_input, item["operator"], item.get("value", "")))
if cond["logical_operator"] != "and" and any(res):
return Switch.be_output(cond["to"])
if all(res):
return Switch.be_output(cond["to"])
return Switch.be_output(self._param.end_cpn_id)
@ -106,22 +110,22 @@ class Switch(ComponentBase, ABC):
elif operator == ">":
try:
return True if float(input) > float(value) else False
except Exception as e:
except Exception:
return True if input > value else False
elif operator == "<":
try:
return True if float(input) < float(value) else False
except Exception as e:
except Exception:
return True if input < value else False
elif operator == "":
try:
return True if float(input) >= float(value) else False
except Exception as e:
except Exception:
return True if input >= value else False
elif operator == "":
try:
return True if float(input) <= float(value) else False
except Exception as e:
except Exception:
return True if input <= value else False
raise ValueError('Not supported operator' + operator)
raise ValueError('Not supported operator' + operator)

134
agent/component/template.py Normal file
View File

@ -0,0 +1,134 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import re
from agent.component.base import ComponentBase, ComponentParamBase
from jinja2 import Template as Jinja2Template
class TemplateParam(ComponentParamBase):
"""
Define the Generate component parameters.
"""
def __init__(self):
super().__init__()
self.content = ""
self.parameters = []
def check(self):
self.check_empty(self.content, "[Template] Content")
return True
class Template(ComponentBase):
component_name = "Template"
def get_dependent_components(self):
inputs = self.get_input_elements()
cpnts = set([i["key"] for i in inputs if i["key"].lower().find("answer") < 0 and i["key"].lower().find("begin") < 0])
return list(cpnts)
def get_input_elements(self):
key_set = set([])
res = []
for r in re.finditer(r"\{([a-z]+[:@][a-z0-9_-]+)\}", self._param.content, flags=re.IGNORECASE):
cpn_id = r.group(1)
if cpn_id in key_set:
continue
if cpn_id.lower().find("begin@") == 0:
cpn_id, key = cpn_id.split("@")
for p in self._canvas.get_component(cpn_id)["obj"]._param.query:
if p["key"] != key:
continue
res.append({"key": r.group(1), "name": p["name"]})
key_set.add(r.group(1))
continue
cpn_nm = self._canvas.get_component_name(cpn_id)
if not cpn_nm:
continue
res.append({"key": cpn_id, "name": cpn_nm})
key_set.add(cpn_id)
return res
def _run(self, history, **kwargs):
content = self._param.content
self._param.inputs = []
for para in self.get_input_elements():
if para["key"].lower().find("begin@") == 0:
cpn_id, key = para["key"].split("@")
for p in self._canvas.get_component(cpn_id)["obj"]._param.query:
if p["key"] == key:
value = p.get("value", "")
self.make_kwargs(para, kwargs, value)
break
else:
assert False, f"Can't find parameter '{key}' for {cpn_id}"
continue
component_id = para["key"]
cpn = self._canvas.get_component(component_id)["obj"]
if cpn.component_name.lower() == "answer":
hist = self._canvas.get_history(1)
if hist:
hist = hist[0]["content"]
else:
hist = ""
self.make_kwargs(para, kwargs, hist)
continue
_, out = cpn.output(allow_partial=False)
result = ""
if "content" in out.columns:
result = "\n".join(
[o if isinstance(o, str) else str(o) for o in out["content"]]
)
self.make_kwargs(para, kwargs, result)
template = Jinja2Template(content)
try:
content = template.render(kwargs)
except Exception:
pass
for n, v in kwargs.items():
if not isinstance(v, str):
try:
v = json.dumps(v, ensure_ascii=False)
except Exception:
pass
content = re.sub(
r"\{%s\}" % re.escape(n), v, content
)
content = re.sub(
r"(#+)", r" \1 ", content
)
return Template.be_output(content)
def make_kwargs(self, para, kwargs, value):
self._param.inputs.append(
{"component_id": para["key"], "content": value}
)
try:
value = json.loads(value)
except Exception:
pass
kwargs[para["key"]] = value

View File

@ -0,0 +1,72 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
from abc import ABC
import pandas as pd
import time
import requests
from agent.component.base import ComponentBase, ComponentParamBase
class TuShareParam(ComponentParamBase):
"""
Define the TuShare component parameters.
"""
def __init__(self):
super().__init__()
self.token = "xxx"
self.src = "eastmoney"
self.start_date = "2024-01-01 09:00:00"
self.end_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.keyword = ""
def check(self):
self.check_valid_value(self.src, "Quick News Source",
["sina", "wallstreetcn", "10jqka", "eastmoney", "yuncaijing", "fenghuang", "jinrongjie"])
class TuShare(ComponentBase, ABC):
component_name = "TuShare"
def _run(self, history, **kwargs):
ans = self.get_input()
ans = ",".join(ans["content"]) if "content" in ans else ""
if not ans:
return TuShare.be_output("")
try:
tus_res = []
params = {
"api_name": "news",
"token": self._param.token,
"params": {"src": self._param.src, "start_date": self._param.start_date,
"end_date": self._param.end_date}
}
response = requests.post(url="http://api.tushare.pro", data=json.dumps(params).encode('utf-8'))
response = response.json()
if response['code'] != 0:
return TuShare.be_output(response['msg'])
df = pd.DataFrame(response['data']['items'])
df.columns = response['data']['fields']
tus_res.append({"content": (df[df['content'].str.contains(self._param.keyword, case=False)]).to_markdown()})
except Exception as e:
return TuShare.be_output("**ERROR**: " + str(e))
if not tus_res:
return TuShare.be_output("")
return pd.DataFrame(tus_res)

80
agent/component/wencai.py Normal file
View File

@ -0,0 +1,80 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from abc import ABC
import pandas as pd
import pywencai
from agent.component.base import ComponentBase, ComponentParamBase
class WenCaiParam(ComponentParamBase):
"""
Define the WenCai component parameters.
"""
def __init__(self):
super().__init__()
self.top_n = 10
self.query_type = "stock"
def check(self):
self.check_positive_integer(self.top_n, "Top N")
self.check_valid_value(self.query_type, "Query type",
['stock', 'zhishu', 'fund', 'hkstock', 'usstock', 'threeboard', 'conbond', 'insurance',
'futures', 'lccp',
'foreign_exchange'])
class WenCai(ComponentBase, ABC):
component_name = "WenCai"
def _run(self, history, **kwargs):
ans = self.get_input()
ans = ",".join(ans["content"]) if "content" in ans else ""
if not ans:
return WenCai.be_output("")
try:
wencai_res = []
res = pywencai.get(query=ans, query_type=self._param.query_type, perpage=self._param.top_n)
if isinstance(res, pd.DataFrame):
wencai_res.append({"content": res.to_markdown()})
if isinstance(res, dict):
for item in res.items():
if isinstance(item[1], list):
wencai_res.append({"content": item[0] + "\n" + pd.DataFrame(item[1]).to_markdown()})
continue
if isinstance(item[1], str):
wencai_res.append({"content": item[0] + "\n" + item[1]})
continue
if isinstance(item[1], dict):
if "meta" in item[1].keys():
continue
wencai_res.append({"content": pd.DataFrame.from_dict(item[1], orient='index').to_markdown()})
continue
if isinstance(item[1], pd.DataFrame):
if "image_url" in item[1].columns:
continue
wencai_res.append({"content": item[1].to_markdown()})
continue
wencai_res.append({"content": item[0] + "\n" + str(item[1])})
except Exception as e:
return WenCai.be_output("**ERROR**: " + str(e))
if not wencai_res:
return WenCai.be_output("")
return pd.DataFrame(wencai_res)

View File

@ -13,12 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import random
import logging
from abc import ABC
from functools import partial
import wikipedia
import pandas as pd
from agent.settings import DEBUG
from agent.component.base import ComponentBase, ComponentParamBase
@ -65,5 +63,5 @@ class Wikipedia(ComponentBase, ABC):
return Wikipedia.be_output("")
df = pd.DataFrame(wiki_res)
if DEBUG: print(df, ":::::::::::::::::::::::::::::::::")
logging.debug(f"df: {df}")
return df

View File

@ -0,0 +1,84 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from abc import ABC
import pandas as pd
from agent.component.base import ComponentBase, ComponentParamBase
import yfinance as yf
class YahooFinanceParam(ComponentParamBase):
"""
Define the YahooFinance component parameters.
"""
def __init__(self):
super().__init__()
self.info = True
self.history = False
self.count = False
self.financials = False
self.income_stmt = False
self.balance_sheet = False
self.cash_flow_statement = False
self.news = True
def check(self):
self.check_boolean(self.info, "get all stock info")
self.check_boolean(self.history, "get historical market data")
self.check_boolean(self.count, "show share count")
self.check_boolean(self.financials, "show financials")
self.check_boolean(self.income_stmt, "income statement")
self.check_boolean(self.balance_sheet, "balance sheet")
self.check_boolean(self.cash_flow_statement, "cash flow statement")
self.check_boolean(self.news, "show news")
class YahooFinance(ComponentBase, ABC):
component_name = "YahooFinance"
def _run(self, history, **kwargs):
ans = self.get_input()
ans = "".join(ans["content"]) if "content" in ans else ""
if not ans:
return YahooFinance.be_output("")
yohoo_res = []
try:
msft = yf.Ticker(ans)
if self._param.info:
yohoo_res.append({"content": "info:\n" + pd.Series(msft.info).to_markdown() + "\n"})
if self._param.history:
yohoo_res.append({"content": "history:\n" + msft.history().to_markdown() + "\n"})
if self._param.financials:
yohoo_res.append({"content": "calendar:\n" + pd.DataFrame(msft.calendar).to_markdown() + "\n"})
if self._param.balance_sheet:
yohoo_res.append({"content": "balance sheet:\n" + msft.balance_sheet.to_markdown() + "\n"})
yohoo_res.append(
{"content": "quarterly balance sheet:\n" + msft.quarterly_balance_sheet.to_markdown() + "\n"})
if self._param.cash_flow_statement:
yohoo_res.append({"content": "cash flow statement:\n" + msft.cashflow.to_markdown() + "\n"})
yohoo_res.append(
{"content": "quarterly cash flow statement:\n" + msft.quarterly_cashflow.to_markdown() + "\n"})
if self._param.news:
yohoo_res.append({"content": "news:\n" + pd.DataFrame(msft.news).to_markdown() + "\n"})
except Exception:
logging.exception("YahooFinance got exception")
if not yohoo_res:
return YahooFinance.be_output("")
return pd.DataFrame(yohoo_res)

View File

@ -1,5 +1,5 @@
#
# Copyright 2019 The FATE Authors. All Rights Reserved.
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,22 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Logger
import os
from api.utils.file_utils import get_project_base_directory
from api.utils.log_utils import LoggerFactory, getLogger
DEBUG = 0
LoggerFactory.set_directory(
os.path.join(
get_project_base_directory(),
"logs",
"flow"))
# {CRITICAL: 50, FATAL:50, ERROR:40, WARNING:30, WARN:30, INFO:20, DEBUG:10, NOTSET:0}
LoggerFactory.LEVEL = 30
flow_logger = getLogger("flow")
database_logger = getLogger("database")
FLOAT_ZERO = 1e-8
PARAM_MAXDEPTH = 5

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ if __name__ == '__main__':
else:
print(ans["content"])
if DEBUG: print(canvas.path)
if DEBUG:
print(canvas.path)
question = input("\n==================== User =====================\n> ")
canvas.add_user_input(question)

View File

@ -26,20 +26,48 @@
"category_description": {
"product_related": {
"description": "The question is about the product usage, appearance and how it works.",
"examples": "Why it always beaming?\nHow to install it onto the wall?\nIt leaks, what to do?"
"examples": "Why it always beaming?\nHow to install it onto the wall?\nIt leaks, what to do?",
"to": "message:0"
},
"others": {
"description": "The question is not about the product usage, appearance and how it works.",
"examples": "How are you doing?\nWhat is your name?\nAre you a robot?\nWhat's the weather?\nWill it rain?"
"examples": "How are you doing?\nWhat is your name?\nAre you a robot?\nWhat's the weather?\nWill it rain?",
"to": "message:1"
}
}
}
},
"downstream": [],
"downstream": ["message:0","message:1"],
"upstream": ["answer:0"]
},
"message:0": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 0!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["categorize:0"]
},
"message:1": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 1!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["categorize:0"]
}
},
"history": [],
"messages": [],
"path": [],
"reference": [],
"answer": []
}
}

View File

@ -0,0 +1,113 @@
{
"components": {
"begin": {
"obj":{
"component_name": "Begin",
"params": {
"prologue": "Hi there!"
}
},
"downstream": ["answer:0"],
"upstream": []
},
"answer:0": {
"obj": {
"component_name": "Answer",
"params": {}
},
"downstream": ["categorize:0"],
"upstream": ["begin"]
},
"categorize:0": {
"obj": {
"component_name": "Categorize",
"params": {
"llm_id": "deepseek-chat",
"category_description": {
"product_related": {
"description": "The question is about the product usage, appearance and how it works.",
"examples": "Why it always beaming?\nHow to install it onto the wall?\nIt leaks, what to do?",
"to": "concentrator:0"
},
"others": {
"description": "The question is not about the product usage, appearance and how it works.",
"examples": "How are you doing?\nWhat is your name?\nAre you a robot?\nWhat's the weather?\nWill it rain?",
"to": "concentrator:1"
}
}
}
},
"downstream": ["concentrator:0","concentrator:1"],
"upstream": ["answer:0"]
},
"concentrator:0": {
"obj": {
"component_name": "Concentrator",
"params": {}
},
"downstream": ["message:0"],
"upstream": ["categorize:0"]
},
"concentrator:1": {
"obj": {
"component_name": "Concentrator",
"params": {}
},
"downstream": ["message:1_0","message:1_1","message:1_2"],
"upstream": ["categorize:0"]
},
"message:0": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 0_0!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["concentrator:0"]
},
"message:1_0": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 1_0!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["concentrator:1"]
},
"message:1_1": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 1_1!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["concentrator:1"]
},
"message:1_2": {
"obj": {
"component_name": "Message",
"params": {
"messages": [
"Message 1_2!!!!!!!"
]
}
},
"downstream": ["answer:0"],
"upstream": ["concentrator:1"]
}
},
"history": [],
"messages": [],
"path": [],
"reference": [],
"answer": []
}

View File

@ -0,0 +1 @@
from .deep_research import DeepResearcher as DeepResearcher

View File

@ -0,0 +1,223 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import re
from functools import partial
from agentic_reasoning.prompts import BEGIN_SEARCH_QUERY, BEGIN_SEARCH_RESULT, END_SEARCH_RESULT, MAX_SEARCH_LIMIT, \
END_SEARCH_QUERY, REASON_PROMPT, RELEVANT_EXTRACTION_PROMPT
from api.db.services.llm_service import LLMBundle
from rag.nlp import extract_between
from rag.prompts import kb_prompt
from rag.utils.tavily_conn import Tavily
class DeepResearcher:
def __init__(self,
chat_mdl: LLMBundle,
prompt_config: dict,
kb_retrieve: partial = None,
kg_retrieve: partial = None
):
self.chat_mdl = chat_mdl
self.prompt_config = prompt_config
self._kb_retrieve = kb_retrieve
self._kg_retrieve = kg_retrieve
@staticmethod
def _remove_query_tags(text):
"""Remove query tags from text"""
pattern = re.escape(BEGIN_SEARCH_QUERY) + r"(.*?)" + re.escape(END_SEARCH_QUERY)
return re.sub(pattern, "", text)
@staticmethod
def _remove_result_tags(text):
"""Remove result tags from text"""
pattern = re.escape(BEGIN_SEARCH_RESULT) + r"(.*?)" + re.escape(END_SEARCH_RESULT)
return re.sub(pattern, "", text)
def _generate_reasoning(self, msg_history):
"""Generate reasoning steps"""
query_think = ""
if msg_history[-1]["role"] != "user":
msg_history.append({"role": "user", "content": "Continues reasoning with the new information.\n"})
else:
msg_history[-1]["content"] += "\n\nContinues reasoning with the new information.\n"
for ans in self.chat_mdl.chat_streamly(REASON_PROMPT, msg_history, {"temperature": 0.7}):
ans = re.sub(r"<think>.*</think>", "", ans, flags=re.DOTALL)
if not ans:
continue
query_think = ans
yield query_think
return query_think
def _extract_search_queries(self, query_think, question, step_index):
"""Extract search queries from thinking"""
queries = extract_between(query_think, BEGIN_SEARCH_QUERY, END_SEARCH_QUERY)
if not queries and step_index == 0:
# If this is the first step and no queries are found, use the original question as the query
queries = [question]
return queries
def _truncate_previous_reasoning(self, all_reasoning_steps):
"""Truncate previous reasoning steps to maintain a reasonable length"""
truncated_prev_reasoning = ""
for i, step in enumerate(all_reasoning_steps):
truncated_prev_reasoning += f"Step {i + 1}: {step}\n\n"
prev_steps = truncated_prev_reasoning.split('\n\n')
if len(prev_steps) <= 5:
truncated_prev_reasoning = '\n\n'.join(prev_steps)
else:
truncated_prev_reasoning = ''
for i, step in enumerate(prev_steps):
if i == 0 or i >= len(prev_steps) - 4 or BEGIN_SEARCH_QUERY in step or BEGIN_SEARCH_RESULT in step:
truncated_prev_reasoning += step + '\n\n'
else:
if truncated_prev_reasoning[-len('\n\n...\n\n'):] != '\n\n...\n\n':
truncated_prev_reasoning += '...\n\n'
return truncated_prev_reasoning.strip('\n')
def _retrieve_information(self, search_query):
"""Retrieve information from different sources"""
# 1. Knowledge base retrieval
kbinfos = self._kb_retrieve(question=search_query) if self._kb_retrieve else {"chunks": [], "doc_aggs": []}
# 2. Web retrieval (if Tavily API is configured)
if self.prompt_config.get("tavily_api_key"):
tav = Tavily(self.prompt_config["tavily_api_key"])
tav_res = tav.retrieve_chunks(search_query)
kbinfos["chunks"].extend(tav_res["chunks"])
kbinfos["doc_aggs"].extend(tav_res["doc_aggs"])
# 3. Knowledge graph retrieval (if configured)
if self.prompt_config.get("use_kg") and self._kg_retrieve:
ck = self._kg_retrieve(question=search_query)
if ck["content_with_weight"]:
kbinfos["chunks"].insert(0, ck)
return kbinfos
def _update_chunk_info(self, chunk_info, kbinfos):
"""Update chunk information for citations"""
if not chunk_info["chunks"]:
# If this is the first retrieval, use the retrieval results directly
for k in chunk_info.keys():
chunk_info[k] = kbinfos[k]
else:
# Merge newly retrieved information, avoiding duplicates
cids = [c["chunk_id"] for c in chunk_info["chunks"]]
for c in kbinfos["chunks"]:
if c["chunk_id"] not in cids:
chunk_info["chunks"].append(c)
dids = [d["doc_id"] for d in chunk_info["doc_aggs"]]
for d in kbinfos["doc_aggs"]:
if d["doc_id"] not in dids:
chunk_info["doc_aggs"].append(d)
def _extract_relevant_info(self, truncated_prev_reasoning, search_query, kbinfos):
"""Extract and summarize relevant information"""
summary_think = ""
for ans in self.chat_mdl.chat_streamly(
RELEVANT_EXTRACTION_PROMPT.format(
prev_reasoning=truncated_prev_reasoning,
search_query=search_query,
document="\n".join(kb_prompt(kbinfos, 4096))
),
[{"role": "user",
"content": f'Now you should analyze each web page and find helpful information based on the current search query "{search_query}" and previous reasoning steps.'}],
{"temperature": 0.7}):
ans = re.sub(r"<think>.*</think>", "", ans, flags=re.DOTALL)
if not ans:
continue
summary_think = ans
yield summary_think
return summary_think
def thinking(self, chunk_info: dict, question: str):
executed_search_queries = []
msg_history = [{"role": "user", "content": f'Question:\"{question}\"\n'}]
all_reasoning_steps = []
think = "<think>"
for step_index in range(MAX_SEARCH_LIMIT + 1):
# Check if the maximum search limit has been reached
if step_index == MAX_SEARCH_LIMIT - 1:
summary_think = f"\n{BEGIN_SEARCH_RESULT}\nThe maximum search limit is exceeded. You are not allowed to search.\n{END_SEARCH_RESULT}\n"
yield {"answer": think + summary_think + "</think>", "reference": {}, "audio_binary": None}
all_reasoning_steps.append(summary_think)
msg_history.append({"role": "assistant", "content": summary_think})
break
# Step 1: Generate reasoning
query_think = ""
for ans in self._generate_reasoning(msg_history):
query_think = ans
yield {"answer": think + self._remove_query_tags(query_think) + "</think>", "reference": {}, "audio_binary": None}
think += self._remove_query_tags(query_think)
all_reasoning_steps.append(query_think)
# Step 2: Extract search queries
queries = self._extract_search_queries(query_think, question, step_index)
if not queries and step_index > 0:
# If not the first step and no queries, end the search process
break
# Process each search query
for search_query in queries:
logging.info(f"[THINK]Query: {step_index}. {search_query}")
msg_history.append({"role": "assistant", "content": search_query})
think += f"\n\n> {step_index + 1}. {search_query}\n\n"
yield {"answer": think + "</think>", "reference": {}, "audio_binary": None}
# Check if the query has already been executed
if search_query in executed_search_queries:
summary_think = f"\n{BEGIN_SEARCH_RESULT}\nYou have searched this query. Please refer to previous results.\n{END_SEARCH_RESULT}\n"
yield {"answer": think + summary_think + "</think>", "reference": {}, "audio_binary": None}
all_reasoning_steps.append(summary_think)
msg_history.append({"role": "user", "content": summary_think})
think += summary_think
continue
executed_search_queries.append(search_query)
# Step 3: Truncate previous reasoning steps
truncated_prev_reasoning = self._truncate_previous_reasoning(all_reasoning_steps)
# Step 4: Retrieve information
kbinfos = self._retrieve_information(search_query)
# Step 5: Update chunk information
self._update_chunk_info(chunk_info, kbinfos)
# Step 6: Extract relevant information
think += "\n\n"
summary_think = ""
for ans in self._extract_relevant_info(truncated_prev_reasoning, search_query, kbinfos):
summary_think = ans
yield {"answer": think + self._remove_result_tags(summary_think) + "</think>", "reference": {}, "audio_binary": None}
all_reasoning_steps.append(summary_think)
msg_history.append(
{"role": "user", "content": f"\n\n{BEGIN_SEARCH_RESULT}{summary_think}{END_SEARCH_RESULT}\n\n"})
think += self._remove_result_tags(summary_think)
logging.info(f"[THINK]Summary: {step_index}. {summary_think}")
yield think + "</think>"

View File

@ -0,0 +1,113 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
BEGIN_SEARCH_QUERY = "<|begin_search_query|>"
END_SEARCH_QUERY = "<|end_search_query|>"
BEGIN_SEARCH_RESULT = "<|begin_search_result|>"
END_SEARCH_RESULT = "<|end_search_result|>"
MAX_SEARCH_LIMIT = 6
REASON_PROMPT = (
"You are a reasoning assistant with the ability to perform dataset searches to help "
"you answer the user's question accurately. You have special tools:\n\n"
f"- To perform a search: write {BEGIN_SEARCH_QUERY} your query here {END_SEARCH_QUERY}.\n"
f"Then, the system will search and analyze relevant content, then provide you with helpful information in the format {BEGIN_SEARCH_RESULT} ...search results... {END_SEARCH_RESULT}.\n\n"
f"You can repeat the search process multiple times if necessary. The maximum number of search attempts is limited to {MAX_SEARCH_LIMIT}.\n\n"
"Once you have all the information you need, continue your reasoning.\n\n"
"-- Example 1 --\n" ########################################
"Question: \"Are both the directors of Jaws and Casino Royale from the same country?\"\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY}Who is the director of Jaws?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nThe director of Jaws is Steven Spielberg...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information.\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY}Where is Steven Spielberg from?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nSteven Allan Spielberg is an American filmmaker...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information...\n\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY}Who is the director of Casino Royale?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nCasino Royale is a 2006 spy film directed by Martin Campbell...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information...\n\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY}Where is Martin Campbell from?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nMartin Campbell (born 24 October 1943) is a New Zealand film and television director...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information...\n\n"
"Assistant:\nIt's enough to answer the question\n"
"-- Example 2 --\n" #########################################
"Question: \"When was the founder of craigslist born?\"\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY}Who was the founder of craigslist?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nCraigslist was founded by Craig Newmark...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information.\n"
"Assistant:\n"
f" {BEGIN_SEARCH_QUERY} When was Craig Newmark born?{END_SEARCH_QUERY}\n\n"
"User:\n"
f" {BEGIN_SEARCH_RESULT}\nCraig Newmark was born on December 6, 1952...\n{END_SEARCH_RESULT}\n\n"
"Continues reasoning with the new information...\n\n"
"Assistant:\nIt's enough to answer the question\n"
"**Remember**:\n"
f"- You have a dataset to search, so you just provide a proper search query.\n"
f"- Use {BEGIN_SEARCH_QUERY} to request a dataset search and end with {END_SEARCH_QUERY}.\n"
"- The language of query MUST be as the same as 'Question' or 'search result'.\n"
"- If no helpful information can be found, rewrite the search query to be less and precise keywords.\n"
"- When done searching, continue your reasoning.\n\n"
'Please answer the following question. You should think step by step to solve it.\n\n'
)
RELEVANT_EXTRACTION_PROMPT = """**Task Instruction:**
You are tasked with reading and analyzing web pages based on the following inputs: **Previous Reasoning Steps**, **Current Search Query**, and **Searched Web Pages**. Your objective is to extract relevant and helpful information for **Current Search Query** from the **Searched Web Pages** and seamlessly integrate this information into the **Previous Reasoning Steps** to continue reasoning for the original question.
**Guidelines:**
1. **Analyze the Searched Web Pages:**
- Carefully review the content of each searched web page.
- Identify factual information that is relevant to the **Current Search Query** and can aid in the reasoning process for the original question.
2. **Extract Relevant Information:**
- Select the information from the Searched Web Pages that directly contributes to advancing the **Previous Reasoning Steps**.
- Ensure that the extracted information is accurate and relevant.
3. **Output Format:**
- **If the web pages provide helpful information for current search query:** Present the information beginning with `**Final Information**` as shown below.
- The language of query **MUST BE** as the same as 'Search Query' or 'Web Pages'.\n"
**Final Information**
[Helpful information]
- **If the web pages do not provide any helpful information for current search query:** Output the following text.
**Final Information**
No helpful information found.
**Inputs:**
- **Previous Reasoning Steps:**
{prev_reasoning}
- **Current Search Query:**
{search_query}
- **Searched Web Pages:**
{document}
"""

View File

@ -0,0 +1,18 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from beartype.claw import beartype_this_package
beartype_this_package()

View File

@ -13,14 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import os
import sys
import logging
from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path
from flask import Blueprint, Flask
from werkzeug.wrappers.request import Request
from flask_cors import CORS
from flasgger import Swagger
from itsdangerous.url_safe import URLSafeTimedSerializer as Serializer
from api.db import StatusEnum
from api.db.db_models import close_connection
@ -29,32 +31,60 @@ from api.utils import CustomJSONEncoder, commands
from flask_session import Session
from flask_login import LoginManager
from api.settings import SECRET_KEY, stat_logger
from api.settings import API_VERSION, access_logger
from api import settings
from api.utils.api_utils import server_error_response
from itsdangerous.url_safe import URLSafeTimedSerializer as Serializer
from api.constants import API_VERSION
__all__ = ['app']
logger = logging.getLogger('flask.app')
for h in access_logger.handlers:
logger.addHandler(h)
__all__ = ["app"]
Request.json = property(lambda self: self.get_json(force=True, silent=True))
app = Flask(__name__)
CORS(app, supports_credentials=True,max_age=2592000)
# Add this at the beginning of your file to configure Swagger UI
swagger_config = {
"headers": [],
"specs": [
{
"endpoint": "apispec",
"route": "/apispec.json",
"rule_filter": lambda rule: True, # Include all endpoints
"model_filter": lambda tag: True, # Include all models
}
],
"static_url_path": "/flasgger_static",
"swagger_ui": True,
"specs_route": "/apidocs/",
}
swagger = Swagger(
app,
config=swagger_config,
template={
"swagger": "2.0",
"info": {
"title": "RAGFlow API",
"description": "",
"version": "1.0.0",
},
"securityDefinitions": {
"ApiKeyAuth": {"type": "apiKey", "name": "Authorization", "in": "header"}
},
},
)
CORS(app, supports_credentials=True, max_age=2592000)
app.url_map.strict_slashes = False
app.json_encoder = CustomJSONEncoder
app.errorhandler(Exception)(server_error_response)
## convince for dev and debug
#app.config["LOGIN_DISABLED"] = True
# app.config["LOGIN_DISABLED"] = True
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
app.config['MAX_CONTENT_LENGTH'] = int(os.environ.get("MAX_CONTENT_LENGTH", 128 * 1024 * 1024))
app.config["MAX_CONTENT_LENGTH"] = int(
os.environ.get("MAX_CONTENT_LENGTH", 1024 * 1024 * 1024)
)
Session(app)
login_manager = LoginManager()
@ -64,17 +94,23 @@ commands.register_commands(app)
def search_pages_path(pages_dir):
app_path_list = [path for path in pages_dir.glob('*_app.py') if not path.name.startswith('.')]
api_path_list = [path for path in pages_dir.glob('*_api.py') if not path.name.startswith('.')]
app_path_list = [
path for path in pages_dir.glob("*_app.py") if not path.name.startswith(".")
]
api_path_list = [
path for path in pages_dir.glob("*sdk/*.py") if not path.name.startswith(".")
]
app_path_list.extend(api_path_list)
return app_path_list
def register_page(page_path):
path = f'{page_path}'
path = f"{page_path}"
page_name = page_path.stem.rstrip('_api') if "_api" in path else page_path.stem.rstrip('_app')
module_name = '.'.join(page_path.parts[page_path.parts.index('api'):-1] + (page_name,))
page_name = page_path.stem.rstrip("_app")
module_name = ".".join(
page_path.parts[page_path.parts.index("api"): -1] + (page_name,)
)
spec = spec_from_file_location(module_name, page_path)
page = module_from_spec(spec)
@ -82,8 +118,11 @@ def register_page(page_path):
page.manager = Blueprint(page_name, module_name)
sys.modules[module_name] = page
spec.loader.exec_module(page)
page_name = getattr(page, 'page_name', page_name)
url_prefix = f'/api/{API_VERSION}/{page_name}' if "_api" in path else f'/{API_VERSION}/{page_name}'
page_name = getattr(page, "page_name", page_name)
sdk_path = "\\sdk\\" if sys.platform.startswith("win") else "/sdk/"
url_prefix = (
f"/api/{API_VERSION}" if sdk_path in path else f"/{API_VERSION}/{page_name}"
)
app.register_blueprint(page.manager, url_prefix=url_prefix)
return url_prefix
@ -91,30 +130,31 @@ def register_page(page_path):
pages_dir = [
Path(__file__).parent,
Path(__file__).parent.parent / 'api' / 'apps', # FIXME: ragflow/api/api/apps, can be remove?
Path(__file__).parent.parent / "api" / "apps",
Path(__file__).parent.parent / "api" / "apps" / "sdk",
]
client_urls_prefix = [
register_page(path)
for dir in pages_dir
for path in search_pages_path(dir)
register_page(path) for dir in pages_dir for path in search_pages_path(dir)
]
@login_manager.request_loader
def load_user(web_request):
jwt = Serializer(secret_key=SECRET_KEY)
jwt = Serializer(secret_key=settings.SECRET_KEY)
authorization = web_request.headers.get("Authorization")
if authorization:
try:
access_token = str(jwt.loads(authorization))
user = UserService.query(access_token=access_token, status=StatusEnum.VALID.value)
user = UserService.query(
access_token=access_token, status=StatusEnum.VALID.value
)
if user:
return user[0]
else:
return None
except Exception as e:
stat_logger.exception(e)
logging.warning(f"load_user got exception {e}")
return None
else:
return None
@ -122,4 +162,4 @@ def load_user(web_request):
@app.teardown_request
def _db_close(exc):
close_connection()
close_connection()

View File

@ -22,7 +22,7 @@ from api.db.services.llm_service import TenantLLMService
from flask_login import login_required, current_user
from api.db import FileType, LLMType, ParserType, FileSource
from api.db.db_models import APIToken, API4Conversation, Task, File
from api.db.db_models import APIToken, Task, File
from api.db.services import duplicate_name
from api.db.services.api_service import APITokenService, API4ConversationService
from api.db.services.dialog_service import DialogService, chat
@ -32,33 +32,29 @@ from api.db.services.file_service import FileService
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.task_service import queue_tasks, TaskService
from api.db.services.user_service import UserTenantService
from api.settings import RetCode, retrievaler
from api import settings
from api.utils import get_uuid, current_timestamp, datetime_format
from api.utils.api_utils import server_error_response, get_data_error_result, get_json_result, validate_request
from itsdangerous import URLSafeTimedSerializer
from api.utils.api_utils import server_error_response, get_data_error_result, get_json_result, validate_request, \
generate_confirmation_token
from api.utils.file_utils import filename_type, thumbnail
from rag.nlp import keyword_extraction
from rag.utils.minio_conn import MINIO
from rag.app.tag import label_question
from rag.prompts import keyword_extraction
from rag.utils.storage_factory import STORAGE_IMPL
from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService
from api.db.services.canvas_service import UserCanvasService
from agent.canvas import Canvas
from functools import partial
def generate_confirmation_token(tenent_id):
serializer = URLSafeTimedSerializer(tenent_id)
return "ragflow-" + serializer.dumps(get_uuid(), salt=tenent_id)[2:34]
@manager.route('/new_token', methods=['POST'])
@manager.route('/new_token', methods=['POST']) # noqa: F821
@login_required
def new_token():
req = request.json
try:
tenants = UserTenantService.query(user_id=current_user.id)
if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
tenant_id = tenants[0].tenant_id
obj = {"tenant_id": tenant_id, "token": generate_confirmation_token(tenant_id),
@ -74,20 +70,20 @@ def new_token():
obj["dialog_id"] = req["dialog_id"]
if not APITokenService.save(**obj):
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_data_error_result(message="Fail to new a dialog!")
return get_json_result(data=obj)
except Exception as e:
return server_error_response(e)
@manager.route('/token_list', methods=['GET'])
@manager.route('/token_list', methods=['GET']) # noqa: F821
@login_required
def token_list():
try:
tenants = UserTenantService.query(user_id=current_user.id)
if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
id = request.args["dialog_id"] if "dialog_id" in request.args else request.args["canvas_id"]
objs = APITokenService.query(tenant_id=tenants[0].tenant_id, dialog_id=id)
@ -96,7 +92,7 @@ def token_list():
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@validate_request("tokens", "tenant_id")
@login_required
def rm():
@ -110,13 +106,13 @@ def rm():
return server_error_response(e)
@manager.route('/stats', methods=['GET'])
@manager.route('/stats', methods=['GET']) # noqa: F821
@login_required
def stats():
try:
tenants = UserTenantService.query(user_id=current_user.id)
if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
objs = API4ConversationService.stats(
tenants[0].tenant_id,
request.args.get(
@ -141,24 +137,26 @@ def stats():
return server_error_response(e)
@manager.route('/new_conversation', methods=['GET'])
@manager.route('/new_conversation', methods=['GET']) # noqa: F821
def set_conversation():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
req = request.json
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
try:
if objs[0].source == "agent":
e, c = UserCanvasService.get_by_id(objs[0].dialog_id)
e, cvs = UserCanvasService.get_by_id(objs[0].dialog_id)
if not e:
return server_error_response("canvas not found.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
canvas = Canvas(cvs.dsl, objs[0].tenant_id)
conv = {
"id": get_uuid(),
"dialog_id": c.id,
"dialog_id": cvs.id,
"user_id": request.args.get("user_id", ""),
"message": [{"role": "assistant", "content": "Hi there!"}],
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
@ -166,7 +164,7 @@ def set_conversation():
else:
e, dia = DialogService.get_by_id(objs[0].dialog_id)
if not e:
return get_data_error_result(retmsg="Dialog not found")
return get_data_error_result(message="Dialog not found")
conv = {
"id": get_uuid(),
"dialog_id": dia.id,
@ -179,19 +177,20 @@ def set_conversation():
return server_error_response(e)
@manager.route('/completion', methods=['POST'])
@manager.route('/completion', methods=['POST']) # noqa: F821
@validate_request("conversation_id", "messages")
def completion():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
req = request.json
e, conv = API4ConversationService.get_by_id(req["conversation_id"])
if not e:
return get_data_error_result(retmsg="Conversation not found!")
if "quote" not in req: req["quote"] = False
return get_data_error_result(message="Conversation not found!")
if "quote" not in req:
req["quote"] = False
msg = []
for m in req["messages"]:
@ -199,15 +198,19 @@ def completion():
continue
if m["role"] == "assistant" and not msg:
continue
msg.append({"role": m["role"], "content": m["content"]})
msg.append(m)
if not msg[-1].get("id"):
msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
def fillin_conv(ans):
nonlocal conv
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"]}
conv.message[-1] = {"role": "assistant", "content": ans["answer"], "id": message_id}
ans["id"] = message_id
def rename_field(ans):
reference = ans['reference']
@ -233,7 +236,7 @@ def completion():
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": ""})
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
final_ans = {"reference": [], "content": ""}
@ -257,19 +260,20 @@ def completion():
ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
fillin_conv(ans)
rename_field(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans},
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans},
ensure_ascii=False) + "\n\n"
canvas.messages.append({"role": "assistant", "content": final_ans["content"]})
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
canvas.history.append(("assistant", final_ans["content"]))
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
@ -279,7 +283,7 @@ def completion():
return resp
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"]})
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
@ -289,18 +293,18 @@ def completion():
API4ConversationService.append_message(conv.id, conv.to_dict())
rename_field(result)
return get_json_result(data=result)
#******************For dialog******************
# ******************For dialog******************
conv.message.append(msg[-1])
e, dia = DialogService.get_by_id(conv.dialog_id)
if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"]
del req["messages"]
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": ""})
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
def stream():
@ -309,14 +313,14 @@ def completion():
for ans in chat(dia, msg, True, **req):
fillin_conv(ans)
rename_field(ans)
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans},
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans},
ensure_ascii=False) + "\n\n"
API4ConversationService.append_message(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream")
@ -325,7 +329,7 @@ def completion():
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
answer = None
for ans in chat(dia, msg, **req):
answer = ans
@ -339,15 +343,25 @@ def completion():
return server_error_response(e)
@manager.route('/conversation/<conversation_id>', methods=['GET'])
@manager.route('/conversation/<conversation_id>', methods=['GET']) # noqa: F821
# @login_required
def get(conversation_id):
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
try:
e, conv = API4ConversationService.get_by_id(conversation_id)
if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
conv = conv.to_dict()
if token != APIToken.query(dialog_id=conv['dialog_id'])[0].token:
return get_json_result(data=False, message='Authentication error: API key is invalid for this conversation_id!"',
code=settings.RetCode.AUTHENTICATION_ERROR)
for referenct_i in conv['reference']:
if referenct_i is None or len(referenct_i) == 0:
continue
@ -360,14 +374,14 @@ def get(conversation_id):
return server_error_response(e)
@manager.route('/document/upload', methods=['POST'])
@manager.route('/document/upload', methods=['POST']) # noqa: F821
@validate_request("kb_name")
def upload():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
kb_name = request.form.get("kb_name").strip()
tenant_id = objs[0].tenant_id
@ -376,19 +390,19 @@ def upload():
e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id)
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
kb_id = kb.id
except Exception as e:
return server_error_response(e)
if 'file' not in request.files:
return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file = request.files['file']
if file.filename == '':
return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=settings.RetCode.ARGUMENT_ERROR)
root_folder = FileService.get_root_folder(tenant_id)
pf_id = root_folder["id"]
@ -399,7 +413,7 @@ def upload():
try:
if DocumentService.get_doc_count(kb.tenant_id) >= int(os.environ.get('MAX_FILE_NUM_PER_USER', 8192)):
return get_data_error_result(
retmsg="Exceed the maximum file number of a free user!")
message="Exceed the maximum file number of a free user!")
filename = duplicate_name(
DocumentService.query,
@ -408,13 +422,13 @@ def upload():
filetype = filename_type(filename)
if not filetype:
return get_data_error_result(
retmsg="This type of file has not been supported yet!")
message="This type of file has not been supported yet!")
location = filename
while MINIO.obj_exist(kb_id, location):
while STORAGE_IMPL.obj_exist(kb_id, location):
location += "_"
blob = request.files['file'].read()
MINIO.put(kb_id, location, blob)
STORAGE_IMPL.put(kb_id, location, blob)
doc = {
"id": get_uuid(),
"kb_id": kb.id,
@ -438,6 +452,8 @@ def upload():
doc["parser_id"] = ParserType.AUDIO.value
if re.search(r"\.(ppt|pptx|pages)$", filename):
doc["parser_id"] = ParserType.PRESENTATION.value
if re.search(r"\.(eml)$", filename):
doc["parser_id"] = ParserType.EMAIL.value
doc_result = DocumentService.insert(doc)
FileService.add_file_from_kb(doc, kb_folder["id"], kb.tenant_id)
@ -455,52 +471,52 @@ def upload():
# if str(req["run"]) == TaskStatus.CANCEL.value:
tenant_id = DocumentService.get_tenant_id(doc["id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
# e, doc = DocumentService.get_by_id(doc["id"])
TaskService.filter_delete([Task.doc_id == doc["id"]])
e, doc = DocumentService.get_by_id(doc["id"])
doc = doc.to_dict()
doc["tenant_id"] = tenant_id
bucket, name = File2DocumentService.get_minio_address(doc_id=doc["id"])
queue_tasks(doc, bucket, name)
bucket, name = File2DocumentService.get_storage_address(doc_id=doc["id"])
queue_tasks(doc, bucket, name, 0)
except Exception as e:
return server_error_response(e)
return get_json_result(data=doc_result.to_json())
@manager.route('/document/upload_and_parse', methods=['POST'])
@manager.route('/document/upload_and_parse', methods=['POST']) # noqa: F821
@validate_request("conversation_id")
def upload_parse():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
if 'file' not in request.files:
return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file')
for file_obj in file_objs:
if file_obj.filename == '':
return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=settings.RetCode.ARGUMENT_ERROR)
doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, objs[0].tenant_id)
return get_json_result(data=doc_ids)
@manager.route('/list_chunks', methods=['POST'])
@manager.route('/list_chunks', methods=['POST']) # noqa: F821
# @login_required
def list_chunks():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
req = request.json
@ -514,15 +530,16 @@ def list_chunks():
doc_id = req['doc_id']
else:
return get_json_result(
data=False, retmsg="Can't find doc_name or doc_id"
data=False, message="Can't find doc_name or doc_id"
)
kb_ids = KnowledgebaseService.get_kb_ids(tenant_id)
res = retrievaler.chunk_list(doc_id=doc_id, tenant_id=tenant_id)
res = settings.retrievaler.chunk_list(doc_id, tenant_id, kb_ids)
res = [
{
"content": res_item["content_with_weight"],
"doc_name": res_item["docnm_kwd"],
"img_id": res_item["img_id"]
"image_id": res_item["img_id"]
} for res_item in res
]
@ -532,14 +549,14 @@ def list_chunks():
return get_json_result(data=res)
@manager.route('/list_kb_docs', methods=['POST'])
@manager.route('/list_kb_docs', methods=['POST']) # noqa: F821
# @login_required
def list_kb_docs():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
req = request.json
tenant_id = objs[0].tenant_id
@ -549,7 +566,7 @@ def list_kb_docs():
e, kb = KnowledgebaseService.get_by_name(kb_name, tenant_id)
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
kb_id = kb.id
except Exception as e:
@ -571,28 +588,29 @@ def list_kb_docs():
except Exception as e:
return server_error_response(e)
@manager.route('/document/infos', methods=['POST'])
@manager.route('/document/infos', methods=['POST']) # noqa: F821
@validate_request("doc_ids")
def docinfos():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
req = request.json
doc_ids = req["doc_ids"]
docs = DocumentService.get_by_ids(doc_ids)
return get_json_result(data=list(docs.dicts()))
@manager.route('/document', methods=['DELETE'])
@manager.route('/document', methods=['DELETE']) # noqa: F821
# @login_required
def document_rm():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
tenant_id = objs[0].tenant_id
req = request.json
@ -604,7 +622,7 @@ def document_rm():
if not doc_ids:
return get_json_result(
data=False, retmsg="Can't find doc_names or doc_ids"
data=False, message="Can't find doc_names or doc_ids"
)
except Exception as e:
@ -619,32 +637,32 @@ def document_rm():
try:
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
b, n = File2DocumentService.get_minio_address(doc_id=doc_id)
b, n = File2DocumentService.get_storage_address(doc_id=doc_id)
if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
f2d = File2DocumentService.get_by_document_id(doc_id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
File2DocumentService.delete_by_document_id(doc_id)
MINIO.rm(b, n)
STORAGE_IMPL.rm(b, n)
except Exception as e:
errors += str(e)
if errors:
return get_json_result(data=False, retmsg=errors, retcode=RetCode.SERVER_ERROR)
return get_json_result(data=False, message=errors, code=settings.RetCode.SERVER_ERROR)
return get_json_result(data=True)
@manager.route('/completion_aibotk', methods=['POST'])
@manager.route('/completion_aibotk', methods=['POST']) # noqa: F821
@validate_request("Authorization", "conversation_id", "word")
def completion_faq():
import base64
@ -654,36 +672,101 @@ def completion_faq():
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
e, conv = API4ConversationService.get_by_id(req["conversation_id"])
if not e:
return get_data_error_result(retmsg="Conversation not found!")
if "quote" not in req: req["quote"] = True
return get_data_error_result(message="Conversation not found!")
if "quote" not in req:
req["quote"] = True
msg = []
msg.append({"role": "user", "content": req["word"]})
if not msg[-1].get("id"):
msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
def fillin_conv(ans):
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"], "id": message_id}
ans["id"] = message_id
try:
if conv.source == "agent":
conv.message.append(msg[-1])
e, cvs = UserCanvasService.get_by_id(conv.dialog_id)
if not e:
return server_error_response("canvas not found.")
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
final_ans = {"reference": [], "doc_aggs": []}
canvas = Canvas(cvs.dsl, objs[0].tenant_id)
canvas.messages.append(msg[-1])
canvas.add_user_input(msg[-1]["content"])
answer = canvas.run(stream=False)
assert answer is not None, "Nothing. Is it over?"
data_type_picture = {
"type": 3,
"url": "base64 content"
}
data = [
{
"type": 1,
"content": ""
}
]
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
ans = {"answer": final_ans["content"], "reference": final_ans.get("reference", [])}
data[0]["content"] += re.sub(r'##\d\$\$', '', ans["answer"])
fillin_conv(ans)
API4ConversationService.append_message(conv.id, conv.to_dict())
chunk_idxs = [int(match[2]) for match in re.findall(r'##\d\$\$', ans["answer"])]
for chunk_idx in chunk_idxs[:1]:
if ans["reference"]["chunks"][chunk_idx]["img_id"]:
try:
bkt, nm = ans["reference"]["chunks"][chunk_idx]["img_id"].split("-")
response = STORAGE_IMPL.get(bkt, nm)
data_type_picture["url"] = base64.b64encode(response).decode('utf-8')
data.append(data_type_picture)
break
except Exception as e:
return server_error_response(e)
response = {"code": 200, "msg": "success", "data": data}
return response
# ******************For dialog******************
conv.message.append(msg[-1])
e, dia = DialogService.get_by_id(conv.dialog_id)
if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"]
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": ""})
conv.message.append({"role": "assistant", "content": "", "id": message_id})
conv.reference.append({"chunks": [], "doc_aggs": []})
def fillin_conv(ans):
nonlocal conv
if not conv.reference:
conv.reference.append(ans["reference"])
else:
conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"]}
data_type_picture = {
"type": 3,
"url": "base64 content"
@ -707,7 +790,7 @@ def completion_faq():
if ans["reference"]["chunks"][chunk_idx]["img_id"]:
try:
bkt, nm = ans["reference"]["chunks"][chunk_idx]["img_id"].split("-")
response = MINIO.get(bkt, nm)
response = STORAGE_IMPL.get(bkt, nm)
data_type_picture["url"] = base64.b64encode(response).decode('utf-8')
data.append(data_type_picture)
break
@ -721,17 +804,17 @@ def completion_faq():
return server_error_response(e)
@manager.route('/retrieval', methods=['POST'])
@manager.route('/retrieval', methods=['POST']) # noqa: F821
@validate_request("kb_id", "question")
def retrieval():
token = request.headers.get('Authorization').split()[1]
objs = APIToken.query(token=token)
if not objs:
return get_json_result(
data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Authentication error: API key is invalid!"', code=settings.RetCode.AUTHENTICATION_ERROR)
req = request.json
kb_ids = req.get("kb_id",[])
kb_ids = req.get("kb_id", [])
doc_ids = req.get("doc_ids", [])
question = req.get("question")
page = int(req.get("page", 1))
@ -745,26 +828,27 @@ def retrieval():
embd_nms = list(set([kb.embd_id for kb in kbs]))
if len(embd_nms) != 1:
return get_json_result(
data=False, retmsg='Knowledge bases use different embedding models or does not exist."', retcode=RetCode.AUTHENTICATION_ERROR)
data=False, message='Knowledge bases use different embedding models or does not exist."',
code=settings.RetCode.AUTHENTICATION_ERROR)
embd_mdl = TenantLLMService.model_instance(
kbs[0].tenant_id, LLMType.EMBEDDING.value, llm_name=kbs[0].embd_id)
rerank_mdl = None
if req.get("rerank_id"):
rerank_mdl = TenantLLMService.model_instance(
kbs[0].tenant_id, LLMType.RERANK.value, llm_name=req["rerank_id"])
kbs[0].tenant_id, LLMType.RERANK.value, llm_name=req["rerank_id"])
if req.get("keyword", False):
chat_mdl = TenantLLMService.model_instance(kbs[0].tenant_id, LLMType.CHAT)
question += keyword_extraction(chat_mdl, question)
ranks = retrievaler.retrieval(question, embd_mdl, kbs[0].tenant_id, kb_ids, page, size,
similarity_threshold, vector_similarity_weight, top,
doc_ids, rerank_mdl=rerank_mdl)
ranks = settings.retrievaler.retrieval(question, embd_mdl, kbs[0].tenant_id, kb_ids, page, size,
similarity_threshold, vector_similarity_weight, top,
doc_ids, rerank_mdl=rerank_mdl,
rank_feature=label_question(question, kbs))
for c in ranks["chunks"]:
if "vector" in c:
del c["vector"]
c.pop("vector", None)
return get_json_result(data=ranks)
except Exception as e:
if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found! Check the chunk status please!',
retcode=RetCode.DATA_ERROR)
return server_error_response(e)
return get_json_result(data=False, message='No chunk found! Check the chunk status please!',
code=settings.RetCode.DATA_ERROR)
return server_error_response(e)

View File

@ -14,23 +14,28 @@
# limitations under the License.
#
import json
from functools import partial
import traceback
from flask import request, Response
from flask_login import login_required, current_user
from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService
from api.db.services.user_service import TenantService
from api.db.services.user_canvas_version import UserCanvasVersionService
from api.settings import RetCode
from api.utils import get_uuid
from api.utils.api_utils import get_json_result, server_error_response, validate_request
from api.utils.api_utils import get_json_result, server_error_response, validate_request, get_data_error_result
from agent.canvas import Canvas
from peewee import MySQLDatabase, PostgresqlDatabase
from api.db.db_models import APIToken
import logging
import time
@manager.route('/templates', methods=['GET'])
@manager.route('/templates', methods=['GET']) # noqa: F821
@login_required
def templates():
return get_json_result(data=[c.to_dict() for c in CanvasTemplateService.get_all()])
@manager.route('/list', methods=['GET'])
@manager.route('/list', methods=['GET']) # noqa: F821
@login_required
def canvas_list():
return get_json_result(data=sorted([c.to_dict() for c in \
@ -38,46 +43,73 @@ def canvas_list():
)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@validate_request("canvas_ids")
@login_required
def rm():
for i in request.json["canvas_ids"]:
if not UserCanvasService.query(user_id=current_user.id,id=i):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
UserCanvasService.delete_by_id(i)
return get_json_result(data=True)
@manager.route('/set', methods=['POST'])
@manager.route('/set', methods=['POST']) # noqa: F821
@validate_request("dsl", "title")
@login_required
def save():
req = request.json
req["user_id"] = current_user.id
if not isinstance(req["dsl"], str): req["dsl"] = json.dumps(req["dsl"], ensure_ascii=False)
if not isinstance(req["dsl"], str):
req["dsl"] = json.dumps(req["dsl"], ensure_ascii=False)
req["dsl"] = json.loads(req["dsl"])
if "id" not in req:
if UserCanvasService.query(user_id=current_user.id, title=req["title"].strip()):
return server_error_response(ValueError("Duplicated title."))
return get_data_error_result(message=f"{req['title'].strip()} already exists.")
req["id"] = get_uuid()
if not UserCanvasService.save(**req):
return server_error_response("Fail to save canvas.")
return get_data_error_result(message="Fail to save canvas.")
else:
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
UserCanvasService.update_by_id(req["id"], req)
# save version
UserCanvasVersionService.insert( user_canvas_id=req["id"], dsl=req["dsl"], title="{0}_{1}".format(req["title"], time.strftime("%Y_%m_%d_%H_%M_%S")))
UserCanvasVersionService.delete_all_versions(req["id"])
return get_json_result(data=req)
@manager.route('/get/<canvas_id>', methods=['GET'])
@manager.route('/get/<canvas_id>', methods=['GET']) # noqa: F821
@login_required
def get(canvas_id):
e, c = UserCanvasService.get_by_tenant_id(canvas_id)
logging.info(f"get canvas_id: {canvas_id} c: {c}")
if not e:
return get_data_error_result(message="canvas not found.")
return get_json_result(data=c)
@manager.route('/getsse/<canvas_id>', methods=['GET']) # type: ignore # noqa: F821
def getsse(canvas_id):
token = request.headers.get('Authorization').split()
if len(token) != 2:
return get_data_error_result(message='Authorization is not valid!"')
token = token[1]
objs = APIToken.query(beta=token)
if not objs:
return get_data_error_result(message='Authentication error: API key is invalid!"')
e, c = UserCanvasService.get_by_id(canvas_id)
if not e:
return server_error_response("canvas not found.")
return get_data_error_result(message="canvas not found.")
return get_json_result(data=c.to_dict())
@manager.route('/completion', methods=['POST'])
@manager.route('/completion', methods=['POST']) # noqa: F821
@validate_request("id")
@login_required
def run():
@ -85,46 +117,59 @@ def run():
stream = req.get("stream", True)
e, cvs = UserCanvasService.get_by_id(req["id"])
if not e:
return server_error_response("canvas not found.")
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
final_ans = {"reference": [], "content": ""}
message_id = req.get("message_id", get_uuid())
try:
canvas = Canvas(cvs.dsl, current_user.id)
if "message" in req:
canvas.messages.append({"role": "user", "content": req["message"]})
canvas.messages.append({"role": "user", "content": req["message"], "id": message_id})
canvas.add_user_input(req["message"])
answer = canvas.run(stream=stream)
print(canvas)
except Exception as e:
return server_error_response(e)
assert answer is not None, "Nothing. Is it over?"
if stream:
assert isinstance(answer, partial), "Nothing. Is it over?"
def sse():
nonlocal answer, cvs
try:
for ans in answer():
for ans in canvas.run(stream=True):
if ans.get("running_status"):
yield "data:" + json.dumps({"code": 0, "message": "",
"data": {"answer": ans["content"],
"running_status": True}},
ensure_ascii=False) + "\n\n"
continue
for k in ans.keys():
final_ans[k] = ans[k]
ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
canvas.messages.append({"role": "assistant", "content": final_ans["content"]})
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
canvas.history.append(("assistant", final_ans["content"]))
if not canvas.path[-1]:
canvas.path.pop(-1)
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
UserCanvasService.update_by_id(req["id"], cvs.to_dict())
except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
cvs.dsl = json.loads(str(canvas))
if not canvas.path[-1]:
canvas.path.pop(-1)
UserCanvasService.update_by_id(req["id"], cvs.to_dict())
traceback.print_exc()
yield "data:" + json.dumps({"code": 500, "message": str(e),
"data": {"answer": "**ERROR**: " + str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
resp = Response(sse(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
@ -133,16 +178,19 @@ def run():
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"]})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
UserCanvasService.update_by_id(req["id"], cvs.to_dict())
return get_json_result(data={"answer": final_ans["content"], "reference": final_ans.get("reference", [])})
for answer in canvas.run(stream=False):
if answer.get("running_status"):
continue
final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
if final_ans.get("reference"):
canvas.reference.append(final_ans["reference"])
cvs.dsl = json.loads(str(canvas))
UserCanvasService.update_by_id(req["id"], cvs.to_dict())
return get_json_result(data={"answer": final_ans["content"], "reference": final_ans.get("reference", [])})
@manager.route('/reset', methods=['POST'])
@manager.route('/reset', methods=['POST']) # noqa: F821
@validate_request("id")
@login_required
def reset():
@ -150,7 +198,11 @@ def reset():
try:
e, user_canvas = UserCanvasService.get_by_id(req["id"])
if not e:
return server_error_response("canvas not found.")
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
canvas.reset()
@ -161,7 +213,51 @@ def reset():
return server_error_response(e)
@manager.route('/test_db_connect', methods=['POST'])
@manager.route('/input_elements', methods=['GET']) # noqa: F821
@login_required
def input_elements():
cvs_id = request.args.get("id")
cpn_id = request.args.get("component_id")
try:
e, user_canvas = UserCanvasService.get_by_id(cvs_id)
if not e:
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=cvs_id):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
return get_json_result(data=canvas.get_component_input_elements(cpn_id))
except Exception as e:
return server_error_response(e)
@manager.route('/debug', methods=['POST']) # noqa: F821
@validate_request("id", "component_id", "params")
@login_required
def debug():
req = request.json
for p in req["params"]:
assert p.get("key")
try:
e, user_canvas = UserCanvasService.get_by_id(req["id"])
if not e:
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
canvas.get_component(req["component_id"])["obj"]._param.debug_inputs = req["params"]
df = canvas.get_component(req["component_id"])["obj"].debug()
return get_json_result(data=df.to_dict(orient="records"))
except Exception as e:
return server_error_response(e)
@manager.route('/test_db_connect', methods=['POST']) # noqa: F821
@validate_request("db_type", "database", "username", "host", "port", "password")
@login_required
def test_db_connect():
@ -173,8 +269,84 @@ def test_db_connect():
elif req["db_type"] == 'postgresql':
db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
password=req["password"])
db.connect()
elif req["db_type"] == 'mssql':
import pyodbc
connection_string = (
f"DRIVER={{ODBC Driver 17 for SQL Server}};"
f"SERVER={req['host']},{req['port']};"
f"DATABASE={req['database']};"
f"UID={req['username']};"
f"PWD={req['password']};"
)
db = pyodbc.connect(connection_string)
cursor = db.cursor()
cursor.execute("SELECT 1")
cursor.close()
else:
return server_error_response("Unsupported database type.")
if req["db_type"] != 'mssql':
db.connect()
db.close()
return get_json_result(data="Database Connection Successful!")
except Exception as e:
return server_error_response(e)
#api get list version dsl of canvas
@manager.route('/getlistversion/<canvas_id>', methods=['GET']) # noqa: F821
@login_required
def getlistversion(canvas_id):
try:
list =sorted([c.to_dict() for c in UserCanvasVersionService.list_by_canvas_id(canvas_id)], key=lambda x: x["update_time"]*-1)
return get_json_result(data=list)
except Exception as e:
return get_data_error_result(message=f"Error getting history files: {e}")
#api get version dsl of canvas
@manager.route('/getversion/<version_id>', methods=['GET']) # noqa: F821
@login_required
def getversion( version_id):
try:
e, version = UserCanvasVersionService.get_by_id(version_id)
if version:
return get_json_result(data=version.to_dict())
except Exception as e:
return get_json_result(data=f"Error getting history file: {e}")
@manager.route('/listteam', methods=['GET']) # noqa: F821
@login_required
def list_kbs():
keywords = request.args.get("keywords", "")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 150))
orderby = request.args.get("orderby", "create_time")
desc = request.args.get("desc", True)
try:
tenants = TenantService.get_joined_tenants_by_user_id(current_user.id)
kbs, total = UserCanvasService.get_by_tenant_ids(
[m["tenant_id"] for m in tenants], current_user.id, page_number,
items_per_page, orderby, desc, keywords)
return get_json_result(data={"kbs": kbs, "total": total})
except Exception as e:
return server_error_response(e)
@manager.route('/setting', methods=['POST']) # noqa: F821
@validate_request("id", "title", "permission")
@login_required
def setting():
req = request.json
req["user_id"] = current_user.id
e,flow = UserCanvasService.get_by_id(req["id"])
if not e:
return get_data_error_result(message="canvas not found.")
flow = flow.to_dict()
flow["title"] = req["title"]
if req["description"]:
flow["description"] = req["description"]
if req["permission"]:
flow["permission"] = req["permission"]
if req["avatar"]:
flow["avatar"] = req["avatar"]
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
num= UserCanvasService.update_by_id(req["id"], flow)
return get_json_result(data=num)

View File

@ -15,29 +15,29 @@
#
import datetime
import json
import traceback
from flask import request
from flask_login import login_required, current_user
from elasticsearch_dsl import Q
from rag.app.qa import rmPrefix, beAdoc
from rag.nlp import search, rag_tokenizer, keyword_extraction
from rag.utils.es_conn import ELASTICSEARCH
from rag.app.tag import label_question
from rag.nlp import search, rag_tokenizer
from rag.prompts import keyword_extraction
from rag.settings import PAGERANK_FLD
from rag.utils import rmSpace
from api.db import LLMType, ParserType
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import TenantLLMService
from api.db.services.llm_service import LLMBundle
from api.db.services.user_service import UserTenantService
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.db.services.document_service import DocumentService
from api.settings import RetCode, retrievaler, kg_retrievaler
from api import settings
from api.utils.api_utils import get_json_result
import hashlib
import xxhash
import re
@manager.route('/list', methods=['POST'])
@manager.route('/list', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id")
def list_chunk():
@ -49,16 +49,17 @@ def list_chunk():
try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
kb_ids = KnowledgebaseService.get_kb_ids(tenant_id)
query = {
"doc_ids": [doc_id], "page": page, "size": size, "question": question, "sort": True
}
if "available_int" in req:
query["available_int"] = int(req["available_int"])
sres = retrievaler.search(query, search.index_name(tenant_id))
sres = settings.retrievaler.search(query, search.index_name(tenant_id), kb_ids, highlight=True)
res = {"total": sres.total, "chunks": [], "doc": doc.to_dict()}
for id in sres.ids:
d = {
@ -69,60 +70,56 @@ def list_chunk():
"doc_id": sres.field[id]["doc_id"],
"docnm_kwd": sres.field[id]["docnm_kwd"],
"important_kwd": sres.field[id].get("important_kwd", []),
"img_id": sres.field[id].get("img_id", ""),
"available_int": sres.field[id].get("available_int", 1),
"positions": sres.field[id].get("position_int", "").split("\t")
"question_kwd": sres.field[id].get("question_kwd", []),
"image_id": sres.field[id].get("img_id", ""),
"available_int": int(sres.field[id].get("available_int", 1)),
"positions": sres.field[id].get("position_int", []),
}
if len(d["positions"]) % 5 == 0:
poss = []
for i in range(0, len(d["positions"]), 5):
poss.append([float(d["positions"][i]), float(d["positions"][i + 1]), float(d["positions"][i + 2]),
float(d["positions"][i + 3]), float(d["positions"][i + 4])])
d["positions"] = poss
assert isinstance(d["positions"], list)
assert len(d["positions"]) == 0 or (isinstance(d["positions"][0], list) and len(d["positions"][0]) == 5)
res["chunks"].append(d)
return get_json_result(data=res)
except Exception as e:
if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='No chunk found!',
code=settings.RetCode.DATA_ERROR)
return server_error_response(e)
@manager.route('/get', methods=['GET'])
@manager.route('/get', methods=['GET']) # noqa: F821
@login_required
def get():
chunk_id = request.args["chunk_id"]
try:
tenants = UserTenantService.query(user_id=current_user.id)
if not tenants:
return get_data_error_result(retmsg="Tenant not found!")
res = ELASTICSEARCH.get(
chunk_id, search.index_name(
tenants[0].tenant_id))
if not res.get("found"):
return server_error_response("Chunk not found")
id = res["_id"]
res = res["_source"]
res["chunk_id"] = id
return get_data_error_result(message="Tenant not found!")
for tenant in tenants:
kb_ids = KnowledgebaseService.get_kb_ids(tenant.tenant_id)
chunk = settings.docStoreConn.get(chunk_id, search.index_name(tenant.tenant_id), kb_ids)
if chunk:
break
if chunk is None:
return server_error_response(Exception("Chunk not found"))
k = []
for n in res.keys():
for n in chunk.keys():
if re.search(r"(_vec$|_sm_|_tks|_ltks)", n):
k.append(n)
for n in k:
del res[n]
del chunk[n]
return get_json_result(data=res)
return get_json_result(data=chunk)
except Exception as e:
if str(e).find("NotFoundError") >= 0:
return get_json_result(data=False, retmsg=f'Chunk not found!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='Chunk not found!',
code=settings.RetCode.DATA_ERROR)
return server_error_response(e)
@manager.route('/set', methods=['POST'])
@manager.route('/set', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "chunk_id", "content_with_weight",
"important_kwd")
@validate_request("doc_id", "chunk_id", "content_with_weight")
def set():
req = request.json
d = {
@ -130,74 +127,80 @@ def set():
"content_with_weight": req["content_with_weight"]}
d["content_ltks"] = rag_tokenizer.tokenize(req["content_with_weight"])
d["content_sm_ltks"] = rag_tokenizer.fine_grained_tokenize(d["content_ltks"])
d["important_kwd"] = req["important_kwd"]
d["important_tks"] = rag_tokenizer.tokenize(" ".join(req["important_kwd"]))
if "important_kwd" in req:
d["important_kwd"] = req["important_kwd"]
d["important_tks"] = rag_tokenizer.tokenize(" ".join(req["important_kwd"]))
if "question_kwd" in req:
d["question_kwd"] = req["question_kwd"]
d["question_tks"] = rag_tokenizer.tokenize("\n".join(req["question_kwd"]))
if "tag_kwd" in req:
d["tag_kwd"] = req["tag_kwd"]
if "tag_feas" in req:
d["tag_feas"] = req["tag_feas"]
if "available_int" in req:
d["available_int"] = req["available_int"]
try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
embd_id = DocumentService.get_embd_id(req["doc_id"])
embd_mdl = TenantLLMService.model_instance(
tenant_id, LLMType.EMBEDDING.value, embd_id)
embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING, embd_id)
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if doc.parser_id == ParserType.QA:
arr = [
t for t in re.split(
r"[\n\t]",
req["content_with_weight"]) if len(t) > 1]
if len(arr) != 2:
return get_data_error_result(
retmsg="Q&A must be separated by TAB/ENTER key.")
q, a = rmPrefix(arr[0]), rmPrefix(arr[1])
d = beAdoc(d, arr[0], arr[1], not any(
q, a = rmPrefix(arr[0]), rmPrefix("\n".join(arr[1:]))
d = beAdoc(d, q, a, not any(
[rag_tokenizer.is_chinese(t) for t in q + a]))
v, c = embd_mdl.encode([doc.name, req["content_with_weight"]])
v, c = embd_mdl.encode([doc.name, req["content_with_weight"] if not d.get("question_kwd") else "\n".join(d["question_kwd"])])
v = 0.1 * v[0] + 0.9 * v[1] if doc.parser_id != ParserType.QA else v[1]
d["q_%d_vec" % len(v)] = v.tolist()
ELASTICSEARCH.upsert([d], search.index_name(tenant_id))
settings.docStoreConn.update({"id": req["chunk_id"]}, d, search.index_name(tenant_id), doc.kb_id)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/switch', methods=['POST'])
@manager.route('/switch', methods=['POST']) # noqa: F821
@login_required
@validate_request("chunk_ids", "available_int", "doc_id")
def switch():
req = request.json
try:
tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
if not ELASTICSEARCH.upsert([{"id": i, "available_int": int(req["available_int"])} for i in req["chunk_ids"]],
search.index_name(tenant_id)):
return get_data_error_result(retmsg="Index updating failure")
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(message="Document not found!")
for cid in req["chunk_ids"]:
if not settings.docStoreConn.update({"id": cid},
{"available_int": int(req["available_int"])},
search.index_name(DocumentService.get_tenant_id(req["doc_id"])),
doc.kb_id):
return get_data_error_result(message="Index updating failure")
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@login_required
@validate_request("chunk_ids", "doc_id")
def rm():
req = request.json
try:
if not ELASTICSEARCH.deleteByQuery(
Q("ids", values=req["chunk_ids"]), search.index_name(current_user.id)):
return get_data_error_result(retmsg="Index updating failure")
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if not settings.docStoreConn.delete({"id": req["chunk_ids"]}, search.index_name(current_user.id), doc.kb_id):
return get_data_error_result(message="Index updating failure")
deleted_chunk_ids = req["chunk_ids"]
chunk_number = len(deleted_chunk_ids)
DocumentService.decrement_chunk_num(doc.id, doc.kb_id, 1, chunk_number, 0)
@ -206,42 +209,48 @@ def rm():
return server_error_response(e)
@manager.route('/create', methods=['POST'])
@manager.route('/create', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "content_with_weight")
def create():
req = request.json
md5 = hashlib.md5()
md5.update((req["content_with_weight"] + req["doc_id"]).encode("utf-8"))
chunck_id = md5.hexdigest()
chunck_id = xxhash.xxh64((req["content_with_weight"] + req["doc_id"]).encode("utf-8")).hexdigest()
d = {"id": chunck_id, "content_ltks": rag_tokenizer.tokenize(req["content_with_weight"]),
"content_with_weight": req["content_with_weight"]}
d["content_sm_ltks"] = rag_tokenizer.fine_grained_tokenize(d["content_ltks"])
d["important_kwd"] = req.get("important_kwd", [])
d["important_tks"] = rag_tokenizer.tokenize(" ".join(req.get("important_kwd", [])))
d["question_kwd"] = req.get("question_kwd", [])
d["question_tks"] = rag_tokenizer.tokenize("\n".join(req.get("question_kwd", [])))
d["create_time"] = str(datetime.datetime.now()).replace("T", " ")[:19]
d["create_timestamp_flt"] = datetime.datetime.now().timestamp()
try:
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
d["kb_id"] = [doc.kb_id]
d["docnm_kwd"] = doc.name
d["title_tks"] = rag_tokenizer.tokenize(doc.name)
d["doc_id"] = doc.id
tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
e, kb = KnowledgebaseService.get_by_id(doc.kb_id)
if not e:
return get_data_error_result(message="Knowledgebase not found!")
if kb.pagerank:
d[PAGERANK_FLD] = kb.pagerank
embd_id = DocumentService.get_embd_id(req["doc_id"])
embd_mdl = TenantLLMService.model_instance(
tenant_id, LLMType.EMBEDDING.value, embd_id)
embd_mdl = LLMBundle(tenant_id, LLMType.EMBEDDING.value, embd_id)
v, c = embd_mdl.encode([doc.name, req["content_with_weight"]])
v, c = embd_mdl.encode([doc.name, req["content_with_weight"] if not d["question_kwd"] else "\n".join(d["question_kwd"])])
v = 0.1 * v[0] + 0.9 * v[1]
d["q_%d_vec" % len(v)] = v.tolist()
ELASTICSEARCH.upsert([d], search.index_name(tenant_id))
settings.docStoreConn.insert([d], search.index_name(tenant_id), doc.kb_id)
DocumentService.increment_chunk_num(
doc.id, doc.kb_id, c, 1, 0)
@ -250,7 +259,7 @@ def create():
return server_error_response(e)
@manager.route('/retrieval_test', methods=['POST'])
@manager.route('/retrieval_test', methods=['POST']) # noqa: F821
@login_required
@validate_request("kb_id", "question")
def retrieval_test():
@ -258,61 +267,106 @@ def retrieval_test():
page = int(req.get("page", 1))
size = int(req.get("size", 30))
question = req["question"]
kb_id = req["kb_id"]
kb_ids = req["kb_id"]
if isinstance(kb_ids, str):
kb_ids = [kb_ids]
doc_ids = req.get("doc_ids", [])
similarity_threshold = float(req.get("similarity_threshold", 0.2))
similarity_threshold = float(req.get("similarity_threshold", 0.0))
vector_similarity_weight = float(req.get("vector_similarity_weight", 0.3))
use_kg = req.get("use_kg", False)
top = int(req.get("top_k", 1024))
try:
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
return get_data_error_result(retmsg="Knowledgebase not found!")
tenant_ids = []
embd_mdl = TenantLLMService.model_instance(
kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)
try:
tenants = UserTenantService.query(user_id=current_user.id)
for kb_id in kb_ids:
for tenant in tenants:
if KnowledgebaseService.query(
tenant_id=tenant.tenant_id, id=kb_id):
tenant_ids.append(tenant.tenant_id)
break
else:
return get_json_result(
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
e, kb = KnowledgebaseService.get_by_id(kb_ids[0])
if not e:
return get_data_error_result(message="Knowledgebase not found!")
embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)
rerank_mdl = None
if req.get("rerank_id"):
rerank_mdl = TenantLLMService.model_instance(
kb.tenant_id, LLMType.RERANK.value, llm_name=req["rerank_id"])
rerank_mdl = LLMBundle(kb.tenant_id, LLMType.RERANK.value, llm_name=req["rerank_id"])
if req.get("keyword", False):
chat_mdl = TenantLLMService.model_instance(kb.tenant_id, LLMType.CHAT)
chat_mdl = LLMBundle(kb.tenant_id, LLMType.CHAT)
question += keyword_extraction(chat_mdl, question)
retr = retrievaler if kb.parser_id != ParserType.KG else kg_retrievaler
ranks = retr.retrieval(question, embd_mdl, kb.tenant_id, [kb_id], page, size,
labels = label_question(question, [kb])
ranks = settings.retrievaler.retrieval(question, embd_mdl, tenant_ids, kb_ids, page, size,
similarity_threshold, vector_similarity_weight, top,
doc_ids, rerank_mdl=rerank_mdl)
doc_ids, rerank_mdl=rerank_mdl, highlight=req.get("highlight"),
rank_feature=labels
)
if use_kg:
ck = settings.kg_retrievaler.retrieval(question,
tenant_ids,
kb_ids,
embd_mdl,
LLMBundle(kb.tenant_id, LLMType.CHAT))
if ck["content_with_weight"]:
ranks["chunks"].insert(0, ck)
for c in ranks["chunks"]:
if "vector" in c:
del c["vector"]
c.pop("vector", None)
ranks["labels"] = labels
return get_json_result(data=ranks)
except Exception as e:
if str(e).find("not_found") > 0:
return get_json_result(data=False, retmsg=f'No chunk found! Check the chunk status please!',
retcode=RetCode.DATA_ERROR)
return get_json_result(data=False, message='No chunk found! Check the chunk status please!',
code=settings.RetCode.DATA_ERROR)
return server_error_response(e)
@manager.route('/knowledge_graph', methods=['GET'])
@manager.route('/knowledge_graph', methods=['GET']) # noqa: F821
@login_required
def knowledge_graph():
doc_id = request.args["doc_id"]
tenant_id = DocumentService.get_tenant_id(doc_id)
kb_ids = KnowledgebaseService.get_kb_ids(tenant_id)
req = {
"doc_ids":[doc_id],
"doc_ids": [doc_id],
"knowledge_graph_kwd": ["graph", "mind_map"]
}
tenant_id = DocumentService.get_tenant_id(doc_id)
sres = retrievaler.search(req, search.index_name(tenant_id))
sres = settings.retrievaler.search(req, search.index_name(tenant_id), kb_ids)
obj = {"graph": {}, "mind_map": {}}
for id in sres.ids[:2]:
ty = sres.field[id]["knowledge_graph_kwd"]
try:
obj[ty] = json.loads(sres.field[id]["content_with_weight"])
except Exception as e:
print(traceback.format_exc(), flush=True)
content_json = json.loads(sres.field[id]["content_with_weight"])
except Exception:
continue
if ty == 'mind_map':
node_dict = {}
def repeat_deal(content_json, node_dict):
if 'id' in content_json:
if content_json['id'] in node_dict:
node_name = content_json['id']
content_json['id'] += f"({node_dict[content_json['id']]})"
node_dict[node_name] += 1
else:
node_dict[content_json['id']] = 1
if 'children' in content_json and content_json['children']:
for item in content_json['children']:
repeat_deal(item, node_dict)
repeat_deal(content_json, node_dict)
obj[ty] = content_json
return get_json_result(data=obj)

View File

@ -13,30 +13,43 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
from copy import deepcopy
from flask import request, Response
from flask_login import login_required
from api.db.services.dialog_service import DialogService, ConversationService, chat
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.utils import get_uuid
from api.utils.api_utils import get_json_result
import json
import re
import traceback
from copy import deepcopy
import trio
from flask import Response, request
from flask_login import current_user, login_required
from api import settings
from api.db import LLMType
from api.db.db_models import APIToken
from api.db.services.conversation_service import ConversationService, structure_answer
from api.db.services.dialog_service import DialogService, ask, chat
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import LLMBundle, TenantService
from api.db.services.user_service import UserTenantService
from api.utils.api_utils import get_data_error_result, get_json_result, server_error_response, validate_request
from graphrag.general.mind_map_extractor import MindMapExtractor
from rag.app.tag import label_question
@manager.route('/set', methods=['POST'])
@manager.route("/set", methods=["POST"]) # noqa: F821
@login_required
def set_conversation():
req = request.json
conv_id = req.get("conversation_id")
if conv_id:
is_new = req.get("is_new")
del req["is_new"]
if not is_new:
del req["conversation_id"]
try:
if not ConversationService.update_by_id(conv_id, req):
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
e, conv = ConversationService.get_by_id(conv_id)
if not e:
return get_data_error_result(
retmsg="Fail to update a conversation!")
return get_data_error_result(message="Fail to update a conversation!")
conv = conv.to_dict()
return get_json_result(data=conv)
except Exception as e:
@ -45,116 +58,177 @@ def set_conversation():
try:
e, dia = DialogService.get_by_id(req["dialog_id"])
if not e:
return get_data_error_result(retmsg="Dialog not found")
conv = {
"id": get_uuid(),
"dialog_id": req["dialog_id"],
"name": req.get("name", "New conversation"),
"message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}]
}
return get_data_error_result(message="Dialog not found")
conv = {"id": conv_id, "dialog_id": req["dialog_id"], "name": req.get("name", "New conversation"), "message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}]}
ConversationService.save(**conv)
e, conv = ConversationService.get_by_id(conv["id"])
if not e:
return get_data_error_result(retmsg="Fail to new a conversation!")
conv = conv.to_dict()
return get_json_result(data=conv)
except Exception as e:
return server_error_response(e)
@manager.route('/get', methods=['GET'])
@manager.route("/get", methods=["GET"]) # noqa: F821
@login_required
def get():
conv_id = request.args["conversation_id"]
try:
e, conv = ConversationService.get_by_id(conv_id)
if not e:
return get_data_error_result(retmsg="Conversation not found!")
return get_data_error_result(message="Conversation not found!")
tenants = UserTenantService.query(user_id=current_user.id)
avatar = None
for tenant in tenants:
dialog = DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id)
if dialog and len(dialog) > 0:
avatar = dialog[0].icon
break
else:
return get_json_result(data=False, message="Only owner of conversation authorized for this operation.", code=settings.RetCode.OPERATING_ERROR)
def get_value(d, k1, k2):
return d.get(k1, d.get(k2))
for ref in conv.reference:
if isinstance(ref, list):
continue
ref["chunks"] = [
{
"id": get_value(ck, "chunk_id", "id"),
"content": get_value(ck, "content", "content_with_weight"),
"document_id": get_value(ck, "doc_id", "document_id"),
"document_name": get_value(ck, "docnm_kwd", "document_name"),
"dataset_id": get_value(ck, "kb_id", "dataset_id"),
"image_id": get_value(ck, "image_id", "img_id"),
"positions": get_value(ck, "positions", "position_int"),
}
for ck in ref.get("chunks", [])
]
conv = conv.to_dict()
conv["avatar"] = avatar
return get_json_result(data=conv)
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route("/getsse/<dialog_id>", methods=["GET"]) # type: ignore # noqa: F821
def getsse(dialog_id):
token = request.headers.get("Authorization").split()
if len(token) != 2:
return get_data_error_result(message='Authorization is not valid!"')
token = token[1]
objs = APIToken.query(beta=token)
if not objs:
return get_data_error_result(message='Authentication error: API key is invalid!"')
try:
e, conv = DialogService.get_by_id(dialog_id)
if not e:
return get_data_error_result(message="Dialog not found!")
conv = conv.to_dict()
conv["avatar"] = conv["icon"]
del conv["icon"]
return get_json_result(data=conv)
except Exception as e:
return server_error_response(e)
@manager.route("/rm", methods=["POST"]) # noqa: F821
@login_required
def rm():
conv_ids = request.json["conversation_ids"]
try:
for cid in conv_ids:
exist, conv = ConversationService.get_by_id(cid)
if not exist:
return get_data_error_result(message="Conversation not found!")
tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants:
if DialogService.query(tenant_id=tenant.tenant_id, id=conv.dialog_id):
break
else:
return get_json_result(data=False, message="Only owner of conversation authorized for this operation.", code=settings.RetCode.OPERATING_ERROR)
ConversationService.delete_by_id(cid)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/list', methods=['GET'])
@manager.route("/list", methods=["GET"]) # noqa: F821
@login_required
def list_convsersation():
dialog_id = request.args["dialog_id"]
try:
convs = ConversationService.query(
dialog_id=dialog_id,
order_by=ConversationService.model.create_time,
reverse=True)
if not DialogService.query(tenant_id=current_user.id, id=dialog_id):
return get_json_result(data=False, message="Only owner of dialog authorized for this operation.", code=settings.RetCode.OPERATING_ERROR)
convs = ConversationService.query(dialog_id=dialog_id, order_by=ConversationService.model.create_time, reverse=True)
convs = [d.to_dict() for d in convs]
return get_json_result(data=convs)
except Exception as e:
return server_error_response(e)
@manager.route('/completion', methods=['POST'])
@manager.route("/completion", methods=["POST"]) # noqa: F821
@login_required
#@validate_request("conversation_id", "messages")
@validate_request("conversation_id", "messages")
def completion():
req = request.json
#req = {"conversation_id": "9aaaca4c11d311efa461fa163e197198", "messages": [
# {"role": "user", "content": "上海有吗?"}
#]}
msg = []
for m in req["messages"]:
if m["role"] == "system":
continue
if m["role"] == "assistant" and not msg:
continue
msg.append({"role": m["role"], "content": m["content"]})
if "doc_ids" in m:
msg[-1]["doc_ids"] = m["doc_ids"]
msg.append(m)
message_id = msg[-1].get("id")
try:
e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e:
return get_data_error_result(retmsg="Conversation not found!")
conv.message.append(deepcopy(msg[-1]))
return get_data_error_result(message="Conversation not found!")
conv.message = deepcopy(req["messages"])
e, dia = DialogService.get_by_id(conv.dialog_id)
if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
del req["conversation_id"]
del req["messages"]
if not conv.reference:
conv.reference = []
conv.message.append({"role": "assistant", "content": ""})
conv.reference.append({"chunks": [], "doc_aggs": []})
else:
def fillin_conv(ans):
nonlocal conv
if not conv.reference:
conv.reference.append(ans["reference"])
else: conv.reference[-1] = ans["reference"]
conv.message[-1] = {"role": "assistant", "content": ans["answer"]}
def get_value(d, k1, k2):
return d.get(k1, d.get(k2))
for ref in conv.reference:
if isinstance(ref, list):
continue
ref["chunks"] = [
{
"id": get_value(ck, "chunk_id", "id"),
"content": get_value(ck, "content", "content_with_weight"),
"document_id": get_value(ck, "doc_id", "document_id"),
"document_name": get_value(ck, "docnm_kwd", "document_name"),
"dataset_id": get_value(ck, "kb_id", "dataset_id"),
"image_id": get_value(ck, "image_id", "img_id"),
"positions": get_value(ck, "positions", "position_int"),
}
for ck in ref.get("chunks", [])
]
if not conv.reference:
conv.reference = []
conv.reference.append({"chunks": [], "doc_aggs": []})
def stream():
nonlocal dia, msg, req, conv
try:
for ans in chat(dia, msg, True, **req):
fillin_conv(ans)
yield "data:"+json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n"
ans = structure_answer(conv, ans, message_id, conv.id)
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
ConversationService.update_by_id(conv.id, conv.to_dict())
except Exception as e:
yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e),
"data": {"answer": "**ERROR**: "+str(e), "reference": []}},
ensure_ascii=False) + "\n\n"
yield "data:"+json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n"
traceback.print_exc()
yield "data:" + json.dumps({"code": 500, "message": str(e), "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
if req.get("stream", True):
resp = Response(stream(), mimetype="text/event-stream")
@ -167,11 +241,193 @@ def completion():
else:
answer = None
for ans in chat(dia, msg, **req):
answer = ans
fillin_conv(ans)
answer = structure_answer(conv, ans, message_id, req["conversation_id"])
ConversationService.update_by_id(conv.id, conv.to_dict())
break
return get_json_result(data=answer)
except Exception as e:
return server_error_response(e)
@manager.route("/tts", methods=["POST"]) # noqa: F821
@login_required
def tts():
req = request.json
text = req["text"]
tenants = TenantService.get_info_by(current_user.id)
if not tenants:
return get_data_error_result(message="Tenant not found!")
tts_id = tenants[0]["tts_id"]
if not tts_id:
return get_data_error_result(message="No default TTS model is set")
tts_mdl = LLMBundle(tenants[0]["tenant_id"], LLMType.TTS, tts_id)
def stream_audio():
try:
for txt in re.split(r"[,。/《》?;:!\n\r:;]+", text):
for chunk in tts_mdl.tts(txt):
yield chunk
except Exception as e:
yield ("data:" + json.dumps({"code": 500, "message": str(e), "data": {"answer": "**ERROR**: " + str(e)}}, ensure_ascii=False)).encode("utf-8")
resp = Response(stream_audio(), mimetype="audio/mpeg")
resp.headers.add_header("Cache-Control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
return resp
@manager.route("/delete_msg", methods=["POST"]) # noqa: F821
@login_required
@validate_request("conversation_id", "message_id")
def delete_msg():
req = request.json
e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e:
return get_data_error_result(message="Conversation not found!")
conv = conv.to_dict()
for i, msg in enumerate(conv["message"]):
if req["message_id"] != msg.get("id", ""):
continue
assert conv["message"][i + 1]["id"] == req["message_id"]
conv["message"].pop(i)
conv["message"].pop(i)
conv["reference"].pop(max(0, i // 2 - 1))
break
ConversationService.update_by_id(conv["id"], conv)
return get_json_result(data=conv)
@manager.route("/thumbup", methods=["POST"]) # noqa: F821
@login_required
@validate_request("conversation_id", "message_id")
def thumbup():
req = request.json
e, conv = ConversationService.get_by_id(req["conversation_id"])
if not e:
return get_data_error_result(message="Conversation not found!")
up_down = req.get("thumbup")
feedback = req.get("feedback", "")
conv = conv.to_dict()
for i, msg in enumerate(conv["message"]):
if req["message_id"] == msg.get("id", "") and msg.get("role", "") == "assistant":
if up_down:
msg["thumbup"] = True
if "feedback" in msg:
del msg["feedback"]
else:
msg["thumbup"] = False
if feedback:
msg["feedback"] = feedback
break
ConversationService.update_by_id(conv["id"], conv)
return get_json_result(data=conv)
@manager.route("/ask", methods=["POST"]) # noqa: F821
@login_required
@validate_request("question", "kb_ids")
def ask_about():
req = request.json
uid = current_user.id
def stream():
nonlocal req, uid
try:
for ans in ask(req["question"], req["kb_ids"], uid):
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
except Exception as e:
yield "data:" + json.dumps({"code": 500, "message": str(e), "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, ensure_ascii=False) + "\n\n"
yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
resp = Response(stream(), mimetype="text/event-stream")
resp.headers.add_header("Cache-control", "no-cache")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp
@manager.route("/mindmap", methods=["POST"]) # noqa: F821
@login_required
@validate_request("question", "kb_ids")
def mindmap():
req = request.json
kb_ids = req["kb_ids"]
e, kb = KnowledgebaseService.get_by_id(kb_ids[0])
if not e:
return get_data_error_result(message="Knowledgebase not found!")
embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING, llm_name=kb.embd_id)
chat_mdl = LLMBundle(current_user.id, LLMType.CHAT)
question = req["question"]
ranks = settings.retrievaler.retrieval(question, embd_mdl, kb.tenant_id, kb_ids, 1, 12, 0.3, 0.3, aggs=False, rank_feature=label_question(question, [kb]))
mindmap = MindMapExtractor(chat_mdl)
mind_map = trio.run(mindmap, [c["content_with_weight"] for c in ranks["chunks"]])
mind_map = mind_map.output
if "error" in mind_map:
return server_error_response(Exception(mind_map["error"]))
return get_json_result(data=mind_map)
@manager.route("/related_questions", methods=["POST"]) # noqa: F821
@login_required
@validate_request("question")
def related_questions():
req = request.json
question = req["question"]
chat_mdl = LLMBundle(current_user.id, LLMType.CHAT)
prompt = """
Role: You are an AI language model assistant tasked with generating 5-10 related questions based on a users original query. These questions should help expand the search query scope and improve search relevance.
Instructions:
Input: You are provided with a users question.
Output: Generate 5-10 alternative questions that are related to the original user question. These alternatives should help retrieve a broader range of relevant documents from a vector database.
Context: Focus on rephrasing the original question in different ways, making sure the alternative questions are diverse but still connected to the topic of the original query. Do not create overly obscure, irrelevant, or unrelated questions.
Fallback: If you cannot generate any relevant alternatives, do not return any questions.
Guidance:
1. Each alternative should be unique but still relevant to the original query.
2. Keep the phrasing clear, concise, and easy to understand.
3. Avoid overly technical jargon or specialized terms unless directly relevant.
4. Ensure that each question contributes towards improving search results by broadening the search angle, not narrowing it.
Example:
Original Question: What are the benefits of electric vehicles?
Alternative Questions:
1. How do electric vehicles impact the environment?
2. What are the advantages of owning an electric car?
3. What is the cost-effectiveness of electric vehicles?
4. How do electric vehicles compare to traditional cars in terms of fuel efficiency?
5. What are the environmental benefits of switching to electric cars?
6. How do electric vehicles help reduce carbon emissions?
7. Why are electric vehicles becoming more popular?
8. What are the long-term savings of using electric vehicles?
9. How do electric vehicles contribute to sustainability?
10. What are the key benefits of electric vehicles for consumers?
Reason:
Rephrasing the original query into multiple alternative questions helps the user explore different aspects of their search topic, improving the quality of search results.
These questions guide the search engine to provide a more comprehensive set of relevant documents.
"""
ans = chat_mdl.chat(
prompt,
[
{
"role": "user",
"content": f"""
Keywords: {question}
Related search terms:
""",
}
],
{"temperature": 0.9},
)
return get_json_result(data=[re.sub(r"^[0-9]\. ", "", a) for a in ans.split("\n") if re.match(r"^[0-9]\. ", a)])

View File

@ -1,878 +0,0 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import pathlib
import re
import warnings
from functools import partial
from io import BytesIO
from elasticsearch_dsl import Q
from flask import request, send_file
from flask_login import login_required, current_user
from httpx import HTTPError
from api.contants import NAME_LENGTH_LIMIT
from api.db import FileType, ParserType, FileSource, TaskStatus
from api.db import StatusEnum
from api.db.db_models import File
from api.db.services import duplicate_name
from api.db.services.document_service import DocumentService
from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.user_service import TenantService
from api.settings import RetCode
from api.utils import get_uuid
from api.utils.api_utils import construct_json_result, construct_error_response
from api.utils.api_utils import construct_result, validate_request
from api.utils.file_utils import filename_type, thumbnail
from rag.app import book, laws, manual, naive, one, paper, presentation, qa, resume, table, picture, audio, email
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
from rag.utils.minio_conn import MINIO
MAXIMUM_OF_UPLOADING_FILES = 256
# ------------------------------ create a dataset ---------------------------------------
@manager.route("/", methods=["POST"])
@login_required # use login
@validate_request("name") # check name key
def create_dataset():
# Check if Authorization header is present
authorization_token = request.headers.get("Authorization")
if not authorization_token:
return construct_json_result(code=RetCode.AUTHENTICATION_ERROR, message="Authorization header is missing.")
# TODO: Login or API key
# objs = APIToken.query(token=authorization_token)
#
# # Authorization error
# if not objs:
# return construct_json_result(code=RetCode.AUTHENTICATION_ERROR, message="Token is invalid.")
#
# tenant_id = objs[0].tenant_id
tenant_id = current_user.id
request_body = request.json
# In case that there's no name
if "name" not in request_body:
return construct_json_result(code=RetCode.DATA_ERROR, message="Expected 'name' field in request body")
dataset_name = request_body["name"]
# empty dataset_name
if not dataset_name:
return construct_json_result(code=RetCode.DATA_ERROR, message="Empty dataset name")
# In case that there's space in the head or the tail
dataset_name = dataset_name.strip()
# In case that the length of the name exceeds the limit
dataset_name_length = len(dataset_name)
if dataset_name_length > NAME_LENGTH_LIMIT:
return construct_json_result(
code=RetCode.DATA_ERROR,
message=f"Dataset name: {dataset_name} with length {dataset_name_length} exceeds {NAME_LENGTH_LIMIT}!")
# In case that there are other fields in the data-binary
if len(request_body.keys()) > 1:
name_list = []
for key_name in request_body.keys():
if key_name != "name":
name_list.append(key_name)
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"fields: {name_list}, are not allowed in request body.")
# If there is a duplicate name, it will modify it to make it unique
request_body["name"] = duplicate_name(
KnowledgebaseService.query,
name=dataset_name,
tenant_id=tenant_id,
status=StatusEnum.VALID.value)
try:
request_body["id"] = get_uuid()
request_body["tenant_id"] = tenant_id
request_body["created_by"] = tenant_id
exist, t = TenantService.get_by_id(tenant_id)
if not exist:
return construct_result(code=RetCode.AUTHENTICATION_ERROR, message="Tenant not found.")
request_body["embd_id"] = t.embd_id
if not KnowledgebaseService.save(**request_body):
# failed to create new dataset
return construct_result()
return construct_json_result(code=RetCode.SUCCESS,
data={"dataset_name": request_body["name"], "dataset_id": request_body["id"]})
except Exception as e:
return construct_error_response(e)
# -----------------------------list datasets-------------------------------------------------------
@manager.route("/", methods=["GET"])
@login_required
def list_datasets():
offset = request.args.get("offset", 0)
count = request.args.get("count", -1)
orderby = request.args.get("orderby", "create_time")
desc = request.args.get("desc", True)
try:
tenants = TenantService.get_joined_tenants_by_user_id(current_user.id)
datasets = KnowledgebaseService.get_by_tenant_ids_by_offset(
[m["tenant_id"] for m in tenants], current_user.id, int(offset), int(count), orderby, desc)
return construct_json_result(data=datasets, code=RetCode.SUCCESS, message=f"List datasets successfully!")
except Exception as e:
return construct_error_response(e)
except HTTPError as http_err:
return construct_json_result(http_err)
# ---------------------------------delete a dataset ----------------------------
@manager.route("/<dataset_id>", methods=["DELETE"])
@login_required
def remove_dataset(dataset_id):
try:
datasets = KnowledgebaseService.query(created_by=current_user.id, id=dataset_id)
# according to the id, searching for the dataset
if not datasets:
return construct_json_result(message=f"The dataset cannot be found for your current account.",
code=RetCode.OPERATING_ERROR)
# Iterating the documents inside the dataset
for doc in DocumentService.query(kb_id=dataset_id):
if not DocumentService.remove_document(doc, datasets[0].tenant_id):
# the process of deleting failed
return construct_json_result(code=RetCode.DATA_ERROR,
message="There was an error during the document removal process. "
"Please check the status of the RAGFlow server and try the removal again.")
# delete the other files
f2d = File2DocumentService.get_by_document_id(doc.id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
File2DocumentService.delete_by_document_id(doc.id)
# delete the dataset
if not KnowledgebaseService.delete_by_id(dataset_id):
return construct_json_result(code=RetCode.DATA_ERROR,
message="There was an error during the dataset removal process. "
"Please check the status of the RAGFlow server and try the removal again.")
# success
return construct_json_result(code=RetCode.SUCCESS, message=f"Remove dataset: {dataset_id} successfully")
except Exception as e:
return construct_error_response(e)
# ------------------------------ get details of a dataset ----------------------------------------
@manager.route("/<dataset_id>", methods=["GET"])
@login_required
def get_dataset(dataset_id):
try:
dataset = KnowledgebaseService.get_detail(dataset_id)
if not dataset:
return construct_json_result(code=RetCode.DATA_ERROR, message="Can't find this dataset!")
return construct_json_result(data=dataset, code=RetCode.SUCCESS)
except Exception as e:
return construct_json_result(e)
# ------------------------------ update a dataset --------------------------------------------
@manager.route("/<dataset_id>", methods=["PUT"])
@login_required
def update_dataset(dataset_id):
req = request.json
try:
# the request cannot be empty
if not req:
return construct_json_result(code=RetCode.DATA_ERROR, message="Please input at least one parameter that "
"you want to update!")
# check whether the dataset can be found
if not KnowledgebaseService.query(created_by=current_user.id, id=dataset_id):
return construct_json_result(message=f"Only the owner of knowledgebase is authorized for this operation!",
code=RetCode.OPERATING_ERROR)
exist, dataset = KnowledgebaseService.get_by_id(dataset_id)
# check whether there is this dataset
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR, message="This dataset cannot be found!")
if "name" in req:
name = req["name"].strip()
# check whether there is duplicate name
if name.lower() != dataset.name.lower() \
and len(KnowledgebaseService.query(name=name, tenant_id=current_user.id,
status=StatusEnum.VALID.value)) > 1:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"The name: {name.lower()} is already used by other "
f"datasets. Please choose a different name.")
dataset_updating_data = {}
chunk_num = req.get("chunk_num")
# modify the value of 11 parameters
# 2 parameters: embedding id and chunk method
# only if chunk_num is 0, the user can update the embedding id
if req.get("embedding_model_id"):
if chunk_num == 0:
dataset_updating_data["embd_id"] = req["embedding_model_id"]
else:
return construct_json_result(code=RetCode.DATA_ERROR,
message="You have already parsed the document in this "
"dataset, so you cannot change the embedding "
"model.")
# only if chunk_num is 0, the user can update the chunk_method
if "chunk_method" in req:
type_value = req["chunk_method"]
if is_illegal_value_for_enum(type_value, ParserType):
return construct_json_result(message=f"Illegal value {type_value} for 'chunk_method' field.",
code=RetCode.DATA_ERROR)
if chunk_num != 0:
construct_json_result(code=RetCode.DATA_ERROR, message="You have already parsed the document "
"in this dataset, so you cannot "
"change the chunk method.")
dataset_updating_data["parser_id"] = req["template_type"]
# convert the photo parameter to avatar
if req.get("photo"):
dataset_updating_data["avatar"] = req["photo"]
# layout_recognize
if "layout_recognize" in req:
if "parser_config" not in dataset_updating_data:
dataset_updating_data['parser_config'] = {}
dataset_updating_data['parser_config']['layout_recognize'] = req['layout_recognize']
# TODO: updating use_raptor needs to construct a class
# 6 parameters
for key in ["name", "language", "description", "permission", "id", "token_num"]:
if key in req:
dataset_updating_data[key] = req.get(key)
# update
if not KnowledgebaseService.update_by_id(dataset.id, dataset_updating_data):
return construct_json_result(code=RetCode.OPERATING_ERROR, message="Failed to update! "
"Please check the status of RAGFlow "
"server and try again!")
exist, dataset = KnowledgebaseService.get_by_id(dataset.id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR, message="Failed to get the dataset "
"using the dataset ID.")
return construct_json_result(data=dataset.to_json(), code=RetCode.SUCCESS)
except Exception as e:
return construct_error_response(e)
# --------------------------------content management ----------------------------------------------
# ----------------------------upload files-----------------------------------------------------
@manager.route("/<dataset_id>/documents/", methods=["POST"])
@login_required
def upload_documents(dataset_id):
# no files
if not request.files:
return construct_json_result(
message="There is no file!", code=RetCode.ARGUMENT_ERROR)
# the number of uploading files exceeds the limit
file_objs = request.files.getlist("file")
num_file_objs = len(file_objs)
if num_file_objs > MAXIMUM_OF_UPLOADING_FILES:
return construct_json_result(code=RetCode.DATA_ERROR, message=f"You try to upload {num_file_objs} files, "
f"which exceeds the maximum number of uploading files: {MAXIMUM_OF_UPLOADING_FILES}")
# no dataset
exist, dataset = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(message="Can't find this dataset", code=RetCode.DATA_ERROR)
for file_obj in file_objs:
file_name = file_obj.filename
# no name
if not file_name:
return construct_json_result(
message="There is a file without name!", code=RetCode.ARGUMENT_ERROR)
# TODO: support the remote files
if 'http' in file_name:
return construct_json_result(code=RetCode.ARGUMENT_ERROR, message="Remote files have not unsupported.")
# get the root_folder
root_folder = FileService.get_root_folder(current_user.id)
# get the id of the root_folder
parent_file_id = root_folder["id"] # document id
# this is for the new user, create '.knowledgebase' file
FileService.init_knowledgebase_docs(parent_file_id, current_user.id)
# go inside this folder, get the kb_root_folder
kb_root_folder = FileService.get_kb_folder(current_user.id)
# link the file management to the kb_folder
kb_folder = FileService.new_a_file_from_kb(dataset.tenant_id, dataset.name, kb_root_folder["id"])
# grab all the errs
err = []
MAX_FILE_NUM_PER_USER = int(os.environ.get("MAX_FILE_NUM_PER_USER", 0))
uploaded_docs_json = []
for file in file_objs:
try:
# TODO: get this value from the database as some tenants have this limit while others don't
if MAX_FILE_NUM_PER_USER > 0 and DocumentService.get_doc_count(dataset.tenant_id) >= MAX_FILE_NUM_PER_USER:
return construct_json_result(code=RetCode.DATA_ERROR,
message="Exceed the maximum file number of a free user!")
# deal with the duplicate name
filename = duplicate_name(
DocumentService.query,
name=file.filename,
kb_id=dataset.id)
# deal with the unsupported type
filetype = filename_type(filename)
if filetype == FileType.OTHER.value:
return construct_json_result(code=RetCode.DATA_ERROR,
message="This type of file has not been supported yet!")
# upload to the minio
location = filename
while MINIO.obj_exist(dataset_id, location):
location += "_"
blob = file.read()
# the content is empty, raising a warning
if blob == b'':
warnings.warn(f"[WARNING]: The content of the file {filename} is empty.")
MINIO.put(dataset_id, location, blob)
doc = {
"id": get_uuid(),
"kb_id": dataset.id,
"parser_id": dataset.parser_id,
"parser_config": dataset.parser_config,
"created_by": current_user.id,
"type": filetype,
"name": filename,
"location": location,
"size": len(blob),
"thumbnail": thumbnail(filename, blob)
}
if doc["type"] == FileType.VISUAL:
doc["parser_id"] = ParserType.PICTURE.value
if doc["type"] == FileType.AURAL:
doc["parser_id"] = ParserType.AUDIO.value
if re.search(r"\.(ppt|pptx|pages)$", filename):
doc["parser_id"] = ParserType.PRESENTATION.value
DocumentService.insert(doc)
FileService.add_file_from_kb(doc, kb_folder["id"], dataset.tenant_id)
uploaded_docs_json.append(doc)
except Exception as e:
err.append(file.filename + ": " + str(e))
if err:
# return all the errors
return construct_json_result(message="\n".join(err), code=RetCode.SERVER_ERROR)
# success
return construct_json_result(data=uploaded_docs_json, code=RetCode.SUCCESS)
# ----------------------------delete a file-----------------------------------------------------
@manager.route("/<dataset_id>/documents/<document_id>", methods=["DELETE"])
@login_required
def delete_document(document_id, dataset_id): # string
# get the root folder
root_folder = FileService.get_root_folder(current_user.id)
# parent file's id
parent_file_id = root_folder["id"]
# consider the new user
FileService.init_knowledgebase_docs(parent_file_id, current_user.id)
# store all the errors that may have
errors = ""
try:
# whether there is this document
exist, doc = DocumentService.get_by_id(document_id)
if not exist:
return construct_json_result(message=f"Document {document_id} not found!", code=RetCode.DATA_ERROR)
# whether this doc is authorized by this tenant
tenant_id = DocumentService.get_tenant_id(document_id)
if not tenant_id:
return construct_json_result(
message=f"You cannot delete this document {document_id} due to the authorization"
f" reason!", code=RetCode.AUTHENTICATION_ERROR)
# get the doc's id and location
real_dataset_id, location = File2DocumentService.get_minio_address(doc_id=document_id)
if real_dataset_id != dataset_id:
return construct_json_result(message=f"The document {document_id} is not in the dataset: {dataset_id}, "
f"but in the dataset: {real_dataset_id}.", code=RetCode.ARGUMENT_ERROR)
# there is an issue when removing
if not DocumentService.remove_document(doc, tenant_id):
return construct_json_result(
message="There was an error during the document removal process. Please check the status of the "
"RAGFlow server and try the removal again.", code=RetCode.OPERATING_ERROR)
# fetch the File2Document record associated with the provided document ID.
file_to_doc = File2DocumentService.get_by_document_id(document_id)
# delete the associated File record.
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == file_to_doc[0].file_id])
# delete the File2Document record itself using the document ID. This removes the
# association between the document and the file after the File record has been deleted.
File2DocumentService.delete_by_document_id(document_id)
# delete it from minio
MINIO.rm(dataset_id, location)
except Exception as e:
errors += str(e)
if errors:
return construct_json_result(data=False, message=errors, code=RetCode.SERVER_ERROR)
return construct_json_result(data=True, code=RetCode.SUCCESS)
# ----------------------------list files-----------------------------------------------------
@manager.route('/<dataset_id>/documents/', methods=['GET'])
@login_required
def list_documents(dataset_id):
if not dataset_id:
return construct_json_result(
data=False, message="Lack of 'dataset_id'", code=RetCode.ARGUMENT_ERROR)
# searching keywords
keywords = request.args.get("keywords", "")
offset = request.args.get("offset", 0)
count = request.args.get("count", -1)
order_by = request.args.get("order_by", "create_time")
descend = request.args.get("descend", True)
try:
docs, total = DocumentService.list_documents_in_dataset(dataset_id, int(offset), int(count), order_by,
descend, keywords)
return construct_json_result(data={"total": total, "docs": docs}, message=RetCode.SUCCESS)
except Exception as e:
return construct_error_response(e)
# ----------------------------update: enable rename-----------------------------------------------------
@manager.route("/<dataset_id>/documents/<document_id>", methods=["PUT"])
@login_required
def update_document(dataset_id, document_id):
req = request.json
try:
legal_parameters = set()
legal_parameters.add("name")
legal_parameters.add("enable")
legal_parameters.add("template_type")
for key in req.keys():
if key not in legal_parameters:
return construct_json_result(code=RetCode.ARGUMENT_ERROR, message=f"{key} is an illegal parameter.")
# The request body cannot be empty
if not req:
return construct_json_result(
code=RetCode.DATA_ERROR,
message="Please input at least one parameter that you want to update!")
# Check whether there is this dataset
exist, dataset = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR, message=f"This dataset {dataset_id} cannot be found!")
# The document does not exist
exist, document = DocumentService.get_by_id(document_id)
if not exist:
return construct_json_result(message=f"This document {document_id} cannot be found!",
code=RetCode.ARGUMENT_ERROR)
# Deal with the different keys
updating_data = {}
if "name" in req:
new_name = req["name"]
updating_data["name"] = new_name
# Check whether the new_name is suitable
# 1. no name value
if not new_name:
return construct_json_result(code=RetCode.DATA_ERROR, message="There is no new name.")
# 2. In case that there's space in the head or the tail
new_name = new_name.strip()
# 3. Check whether the new_name has the same extension of file as before
if pathlib.Path(new_name.lower()).suffix != pathlib.Path(
document.name.lower()).suffix:
return construct_json_result(
data=False,
message="The extension of file cannot be changed",
code=RetCode.ARGUMENT_ERROR)
# 4. Check whether the new name has already been occupied by other file
for d in DocumentService.query(name=new_name, kb_id=document.kb_id):
if d.name == new_name:
return construct_json_result(
message="Duplicated document name in the same dataset.",
code=RetCode.ARGUMENT_ERROR)
if "enable" in req:
enable_value = req["enable"]
if is_illegal_value_for_enum(enable_value, StatusEnum):
return construct_json_result(message=f"Illegal value {enable_value} for 'enable' field.",
code=RetCode.DATA_ERROR)
updating_data["status"] = enable_value
# TODO: Chunk-method - update parameters inside the json object parser_config
if "template_type" in req:
type_value = req["template_type"]
if is_illegal_value_for_enum(type_value, ParserType):
return construct_json_result(message=f"Illegal value {type_value} for 'template_type' field.",
code=RetCode.DATA_ERROR)
updating_data["parser_id"] = req["template_type"]
# The process of updating
if not DocumentService.update_by_id(document_id, updating_data):
return construct_json_result(
code=RetCode.OPERATING_ERROR,
message="Failed to update document in the database! "
"Please check the status of RAGFlow server and try again!")
# name part: file service
if "name" in req:
# Get file by document id
file_information = File2DocumentService.get_by_document_id(document_id)
if file_information:
exist, file = FileService.get_by_id(file_information[0].file_id)
FileService.update_by_id(file.id, {"name": req["name"]})
exist, document = DocumentService.get_by_id(document_id)
# Success
return construct_json_result(data=document.to_json(), message="Success", code=RetCode.SUCCESS)
except Exception as e:
return construct_error_response(e)
# Helper method to judge whether it's an illegal value
def is_illegal_value_for_enum(value, enum_class):
return value not in enum_class.__members__.values()
# ----------------------------download a file-----------------------------------------------------
@manager.route("/<dataset_id>/documents/<document_id>", methods=["GET"])
@login_required
def download_document(dataset_id, document_id):
try:
# Check whether there is this dataset
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset '{dataset_id}' cannot be found!")
# Check whether there is this document
exist, document = DocumentService.get_by_id(document_id)
if not exist:
return construct_json_result(message=f"This document '{document_id}' cannot be found!",
code=RetCode.ARGUMENT_ERROR)
# The process of downloading
doc_id, doc_location = File2DocumentService.get_minio_address(doc_id=document_id) # minio address
file_stream = MINIO.get(doc_id, doc_location)
if not file_stream:
return construct_json_result(message="This file is empty.", code=RetCode.DATA_ERROR)
file = BytesIO(file_stream)
# Use send_file with a proper filename and MIME type
return send_file(
file,
as_attachment=True,
download_name=document.name,
mimetype='application/octet-stream' # Set a default MIME type
)
# Error
except Exception as e:
return construct_error_response(e)
# ----------------------------start parsing a document-----------------------------------------------------
# helper method for parsing
# callback method
def doc_parse_callback(doc_id, prog=None, msg=""):
cancel = DocumentService.do_cancel(doc_id)
if cancel:
raise Exception("The parsing process has been cancelled!")
"""
def doc_parse(binary, doc_name, parser_name, tenant_id, doc_id):
match parser_name:
case "book":
book.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "laws":
laws.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "manual":
manual.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "naive":
# It's the mode by default, which is general in the front-end
naive.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "one":
one.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "paper":
paper.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "picture":
picture.chunk(doc_name, binary=binary, tenant_id=tenant_id, lang="Chinese",
callback=partial(doc_parse_callback, doc_id))
case "presentation":
presentation.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "qa":
qa.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "resume":
resume.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "table":
table.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "audio":
audio.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case "email":
email.chunk(doc_name, binary=binary, callback=partial(doc_parse_callback, doc_id))
case _:
return False
return True
"""
@manager.route("/<dataset_id>/documents/<document_id>/status", methods=["POST"])
@login_required
def parse_document(dataset_id, document_id):
try:
# valid dataset
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset '{dataset_id}' cannot be found!")
return parsing_document_internal(document_id)
except Exception as e:
return construct_error_response(e)
# ----------------------------start parsing documents-----------------------------------------------------
@manager.route("/<dataset_id>/documents/status", methods=["POST"])
@login_required
def parse_documents(dataset_id):
doc_ids = request.json["doc_ids"]
try:
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset '{dataset_id}' cannot be found!")
# two conditions
if not doc_ids:
# documents inside the dataset
docs, total = DocumentService.list_documents_in_dataset(dataset_id, 0, -1, "create_time",
True, "")
doc_ids = [doc["id"] for doc in docs]
message = ""
# for loop
for id in doc_ids:
res = parsing_document_internal(id)
res_body = res.json
if res_body["code"] == RetCode.SUCCESS:
message += res_body["message"]
else:
return res
return construct_json_result(data=True, code=RetCode.SUCCESS, message=message)
except Exception as e:
return construct_error_response(e)
# helper method for parsing the document
def parsing_document_internal(id):
message = ""
try:
# Check whether there is this document
exist, document = DocumentService.get_by_id(id)
if not exist:
return construct_json_result(message=f"This document '{id}' cannot be found!",
code=RetCode.ARGUMENT_ERROR)
tenant_id = DocumentService.get_tenant_id(id)
if not tenant_id:
return construct_json_result(message="Tenant not found!", code=RetCode.AUTHENTICATION_ERROR)
info = {"run": "1", "progress": 0}
info["progress_msg"] = ""
info["chunk_num"] = 0
info["token_num"] = 0
DocumentService.update_by_id(id, info)
ELASTICSEARCH.deleteByQuery(Q("match", doc_id=id), idxnm=search.index_name(tenant_id))
_, doc_attributes = DocumentService.get_by_id(id)
doc_attributes = doc_attributes.to_dict()
doc_id = doc_attributes["id"]
bucket, doc_name = File2DocumentService.get_minio_address(doc_id=doc_id)
binary = MINIO.get(bucket, doc_name)
parser_name = doc_attributes["parser_id"]
if binary:
res = doc_parse(binary, doc_name, parser_name, tenant_id, doc_id)
if res is False:
message += f"The parser id: {parser_name} of the document {doc_id} is not supported; "
else:
message += f"Empty data in the document: {doc_name}; "
# failed in parsing
if doc_attributes["status"] == TaskStatus.FAIL.value:
message += f"Failed in parsing the document: {doc_id}; "
return construct_json_result(code=RetCode.SUCCESS, message=message)
except Exception as e:
return construct_error_response(e)
# ----------------------------stop parsing a doc-----------------------------------------------------
@manager.route("<dataset_id>/documents/<document_id>/status", methods=["DELETE"])
@login_required
def stop_parsing_document(dataset_id, document_id):
try:
# valid dataset
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset '{dataset_id}' cannot be found!")
return stop_parsing_document_internal(document_id)
except Exception as e:
return construct_error_response(e)
# ----------------------------stop parsing docs-----------------------------------------------------
@manager.route("<dataset_id>/documents/status", methods=["DELETE"])
@login_required
def stop_parsing_documents(dataset_id):
doc_ids = request.json["doc_ids"]
try:
# valid dataset?
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset '{dataset_id}' cannot be found!")
if not doc_ids:
# documents inside the dataset
docs, total = DocumentService.list_documents_in_dataset(dataset_id, 0, -1, "create_time",
True, "")
doc_ids = [doc["id"] for doc in docs]
message = ""
# for loop
for id in doc_ids:
res = stop_parsing_document_internal(id)
res_body = res.json
if res_body["code"] == RetCode.SUCCESS:
message += res_body["message"]
else:
return res
return construct_json_result(data=True, code=RetCode.SUCCESS, message=message)
except Exception as e:
return construct_error_response(e)
# Helper method
def stop_parsing_document_internal(document_id):
try:
# valid doc?
exist, doc = DocumentService.get_by_id(document_id)
if not exist:
return construct_json_result(message=f"This document '{document_id}' cannot be found!",
code=RetCode.ARGUMENT_ERROR)
doc_attributes = doc.to_dict()
# only when the status is parsing, we need to stop it
if doc_attributes["status"] == TaskStatus.RUNNING.value:
tenant_id = DocumentService.get_tenant_id(document_id)
if not tenant_id:
return construct_json_result(message="Tenant not found!", code=RetCode.AUTHENTICATION_ERROR)
# update successfully?
if not DocumentService.update_by_id(document_id, {"status": "2"}): # cancel
return construct_json_result(
code=RetCode.OPERATING_ERROR,
message="There was an error during the stopping parsing the document process. "
"Please check the status of the RAGFlow server and try the update again."
)
_, doc_attributes = DocumentService.get_by_id(document_id)
doc_attributes = doc_attributes.to_dict()
# failed in stop parsing
if doc_attributes["status"] == TaskStatus.RUNNING.value:
return construct_json_result(message=f"Failed in parsing the document: {document_id}; ", code=RetCode.SUCCESS)
return construct_json_result(code=RetCode.SUCCESS, message="")
except Exception as e:
return construct_error_response(e)
# ----------------------------show the status of the file-----------------------------------------------------
@manager.route("/<dataset_id>/documents/<document_id>/status", methods=["GET"])
@login_required
def show_parsing_status(dataset_id, document_id):
try:
# valid dataset
exist, _ = KnowledgebaseService.get_by_id(dataset_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This dataset: '{dataset_id}' cannot be found!")
# valid document
exist, _ = DocumentService.get_by_id(document_id)
if not exist:
return construct_json_result(code=RetCode.DATA_ERROR,
message=f"This document: '{document_id}' is not a valid document.")
_, doc = DocumentService.get_by_id(document_id) # get doc object
doc_attributes = doc.to_dict()
return construct_json_result(
data={"progress": doc_attributes["progress"], "status": TaskStatus(doc_attributes["status"]).name},
code=RetCode.SUCCESS
)
except Exception as e:
return construct_error_response(e)
# ----------------------------list the chunks of the file-----------------------------------------------------
# -- --------------------------delete the chunk-----------------------------------------------------
# ----------------------------edit the status of the chunk-----------------------------------------------------
# ----------------------------insert a new chunk-----------------------------------------------------
# ----------------------------upload a file-----------------------------------------------------
# ----------------------------get a specific chunk-----------------------------------------------------
# ----------------------------retrieval test-----------------------------------------------------

View File

@ -18,28 +18,30 @@ from flask import request
from flask_login import login_required, current_user
from api.db.services.dialog_service import DialogService
from api.db import StatusEnum
from api.db.services.llm_service import TenantLLMService
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.user_service import TenantService
from api.db.services.user_service import TenantService, UserTenantService
from api import settings
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.utils import get_uuid
from api.utils.api_utils import get_json_result
@manager.route('/set', methods=['POST'])
@manager.route('/set', methods=['POST']) # noqa: F821
@login_required
def set_dialog():
req = request.json
dialog_id = req.get("dialog_id")
name = req.get("name", "New Dialog")
description = req.get("description", "A helpful Dialog")
description = req.get("description", "A helpful dialog")
icon = req.get("icon", "")
top_n = req.get("top_n", 6)
top_k = req.get("top_k", 1024)
rerank_id = req.get("rerank_id", "")
if not rerank_id: req["rerank_id"] = ""
if not rerank_id:
req["rerank_id"] = ""
similarity_threshold = req.get("similarity_threshold", 0.1)
vector_similarity_weight = req.get("vector_similarity_weight", 0.3)
if vector_similarity_weight is None: vector_similarity_weight = 0.3
llm_setting = req.get("llm_setting", {})
default_prompt = {
"system": """你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。
@ -56,33 +58,31 @@ def set_dialog():
if not prompt_config["system"]:
prompt_config["system"] = default_prompt["system"]
# if len(prompt_config["parameters"]) < 1:
# prompt_config["parameters"] = default_prompt["parameters"]
# for p in prompt_config["parameters"]:
# if p["key"] == "knowledge":break
# else: prompt_config["parameters"].append(default_prompt["parameters"][0])
for p in prompt_config["parameters"]:
if p["optional"]:
continue
if prompt_config["system"].find("{%s}" % p["key"]) < 0:
return get_data_error_result(
retmsg="Parameter '{}' is not used".format(p["key"]))
message="Parameter '{}' is not used".format(p["key"]))
try:
e, tenant = TenantService.get_by_id(current_user.id)
if not e:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
kbs = KnowledgebaseService.get_by_ids(req.get("kb_ids", []))
embd_ids = [TenantLLMService.split_model_name_and_factory(kb.embd_id)[0] for kb in kbs] # remove vendor suffix for comparison
embd_count = len(set(embd_ids))
if embd_count > 1:
return get_data_error_result(message=f'Datasets use different embedding models: {[kb.embd_id for kb in kbs]}"')
llm_id = req.get("llm_id", tenant.llm_id)
if not dialog_id:
if not req.get("kb_ids"):
return get_data_error_result(
retmsg="Fail! Please select knowledgebase!")
dia = {
"id": get_uuid(),
"tenant_id": current_user.id,
"name": name,
"kb_ids": req["kb_ids"],
"kb_ids": req.get("kb_ids", []),
"description": description,
"llm_id": llm_id,
"llm_setting": llm_setting,
@ -95,35 +95,33 @@ def set_dialog():
"icon": icon
}
if not DialogService.save(**dia):
return get_data_error_result(retmsg="Fail to new a dialog!")
e, dia = DialogService.get_by_id(dia["id"])
if not e:
return get_data_error_result(retmsg="Fail to new a dialog!")
return get_json_result(data=dia.to_json())
return get_data_error_result(message="Fail to new a dialog!")
return get_json_result(data=dia)
else:
del req["dialog_id"]
if "kb_names" in req:
del req["kb_names"]
if not DialogService.update_by_id(dialog_id, req):
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
e, dia = DialogService.get_by_id(dialog_id)
if not e:
return get_data_error_result(retmsg="Fail to update a dialog!")
return get_data_error_result(message="Fail to update a dialog!")
dia = dia.to_dict()
dia.update(req)
dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"])
return get_json_result(data=dia)
except Exception as e:
return server_error_response(e)
@manager.route('/get', methods=['GET'])
@manager.route('/get', methods=['GET']) # noqa: F821
@login_required
def get():
dialog_id = request.args["dialog_id"]
try:
e, dia = DialogService.get_by_id(dialog_id)
if not e:
return get_data_error_result(retmsg="Dialog not found!")
return get_data_error_result(message="Dialog not found!")
dia = dia.to_dict()
dia["kb_ids"], dia["kb_names"] = get_kb_names(dia["kb_ids"])
return get_json_result(data=dia)
@ -142,7 +140,7 @@ def get_kb_names(kb_ids):
return ids, nms
@manager.route('/list', methods=['GET'])
@manager.route('/list', methods=['GET']) # noqa: F821
@login_required
def list_dialogs():
try:
@ -159,14 +157,24 @@ def list_dialogs():
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@login_required
@validate_request("dialog_ids")
def rm():
req = request.json
dialog_list=[]
tenants = UserTenantService.query(user_id=current_user.id)
try:
DialogService.update_many_by_id(
[{"id": id, "status": StatusEnum.INVALID.value} for id in req["dialog_ids"]])
for id in req["dialog_ids"]:
for tenant in tenants:
if DialogService.query(tenant_id=tenant.tenant_id, id=id):
break
else:
return get_json_result(
data=False, message='Only owner of dialog authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
dialog_list.append({"id": id,"status":StatusEnum.INVALID.value})
DialogService.update_many_by_id(dialog_list)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)

View File

@ -13,94 +13,93 @@
# See the License for the specific language governing permissions and
# limitations under the License
#
import datetime
import hashlib
import json
import os
import os.path
import pathlib
import re
import traceback
from concurrent.futures import ThreadPoolExecutor
from copy import deepcopy
from io import BytesIO
import flask
from elasticsearch_dsl import Q
from flask import request
from flask_login import login_required, current_user
from api.db.db_models import Task, File
from api.db.services.dialog_service import DialogService, ConversationService
from deepdoc.parser.html_parser import RAGFlowHtmlParser
from rag.nlp import search
from api.db import FileType, TaskStatus, ParserType, FileSource
from api.db.db_models import File, Task
from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService
from api.db.services.llm_service import LLMBundle
from api.db.services.task_service import TaskService, queue_tasks
from api.db.services.user_service import TenantService
from graphrag.mind_map_extractor import MindMapExtractor
from rag.app import naive
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
from api.db.services.task_service import queue_tasks
from api.db.services.user_service import UserTenantService
from api.db.services import duplicate_name
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.utils import get_uuid
from api.db import FileType, TaskStatus, ParserType, FileSource, LLMType
from api.db.services.task_service import TaskService
from api.db.services.document_service import DocumentService, doc_upload_and_parse
from api.settings import RetCode, stat_logger
from api.utils.api_utils import (
server_error_response,
get_data_error_result,
validate_request,
)
from api.utils import get_uuid
from api import settings
from api.utils.api_utils import get_json_result
from rag.utils.minio_conn import MINIO
from rag.utils.storage_factory import STORAGE_IMPL
from api.utils.file_utils import filename_type, thumbnail, get_project_base_directory
from api.utils.web_utils import html2pdf, is_valid_url
from api.constants import IMG_BASE64_PREFIX
@manager.route('/upload', methods=['POST'])
@manager.route('/upload', methods=['POST']) # noqa: F821
@login_required
@validate_request("kb_id")
def upload():
kb_id = request.form.get("kb_id")
if not kb_id:
return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=settings.RetCode.ARGUMENT_ERROR)
if 'file' not in request.files:
return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file')
for file_obj in file_objs:
if file_obj.filename == '':
return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=settings.RetCode.ARGUMENT_ERROR)
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
raise LookupError("Can't find this knowledgebase!")
err, _ = FileService.upload_document(kb, file_objs, current_user.id)
err, files = FileService.upload_document(kb, file_objs, current_user.id)
files = [f[0] for f in files] # remove the blob
if err:
return get_json_result(
data=False, retmsg="\n".join(err), retcode=RetCode.SERVER_ERROR)
return get_json_result(data=True)
data=files, message="\n".join(err), code=settings.RetCode.SERVER_ERROR)
return get_json_result(data=files)
@manager.route('/web_crawl', methods=['POST'])
@manager.route('/web_crawl', methods=['POST']) # noqa: F821
@login_required
@validate_request("kb_id", "name", "url")
def web_crawl():
kb_id = request.form.get("kb_id")
if not kb_id:
return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=settings.RetCode.ARGUMENT_ERROR)
name = request.form.get("name")
url = request.form.get("url")
if not is_valid_url(url):
return get_json_result(
data=False, retmsg='The URL format is invalid', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='The URL format is invalid', code=settings.RetCode.ARGUMENT_ERROR)
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
raise LookupError("Can't find this knowledgebase!")
blob = html2pdf(url)
if not blob: return server_error_response(ValueError("Download failure."))
if not blob:
return server_error_response(ValueError("Download failure."))
root_folder = FileService.get_root_folder(current_user.id)
pf_id = root_folder["id"]
@ -118,9 +117,9 @@ def web_crawl():
raise RuntimeError("This type of file has not been supported yet!")
location = filename
while MINIO.obj_exist(kb_id, location):
while STORAGE_IMPL.obj_exist(kb_id, location):
location += "_"
MINIO.put(kb_id, location, blob)
STORAGE_IMPL.put(kb_id, location, blob)
doc = {
"id": get_uuid(),
"kb_id": kb.id,
@ -139,6 +138,8 @@ def web_crawl():
doc["parser_id"] = ParserType.AUDIO.value
if re.search(r"\.(ppt|pptx|pages)$", filename):
doc["parser_id"] = ParserType.PRESENTATION.value
if re.search(r"\.(eml)$", filename):
doc["parser_id"] = ParserType.EMAIL.value
DocumentService.insert(doc)
FileService.add_file_from_kb(doc, kb_folder["id"], kb.tenant_id)
except Exception as e:
@ -146,7 +147,7 @@ def web_crawl():
return get_json_result(data=True)
@manager.route('/create', methods=['POST'])
@manager.route('/create', methods=['POST']) # noqa: F821
@login_required
@validate_request("name", "kb_id")
def create():
@ -154,17 +155,17 @@ def create():
kb_id = req["kb_id"]
if not kb_id:
return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=settings.RetCode.ARGUMENT_ERROR)
try:
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
if DocumentService.query(name=req["name"], kb_id=kb_id):
return get_data_error_result(
retmsg="Duplicated document name in the same knowledgebase.")
message="Duplicated document name in the same knowledgebase.")
doc = DocumentService.insert({
"id": get_uuid(),
@ -182,13 +183,22 @@ def create():
return server_error_response(e)
@manager.route('/list', methods=['GET'])
@manager.route('/list', methods=['GET']) # noqa: F821
@login_required
def list_docs():
kb_id = request.args.get("kb_id")
if not kb_id:
return get_json_result(
data=False, retmsg='Lack of "KB ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "KB ID"', code=settings.RetCode.ARGUMENT_ERROR)
tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants:
if KnowledgebaseService.query(
tenant_id=tenant.tenant_id, id=kb_id):
break
else:
return get_json_result(
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
keywords = request.args.get("keywords", "")
page_number = int(request.args.get("page", 1))
@ -198,83 +208,108 @@ def list_docs():
try:
docs, tol = DocumentService.get_by_kb_id(
kb_id, page_number, items_per_page, orderby, desc, keywords)
for doc_item in docs:
if doc_item['thumbnail'] and not doc_item['thumbnail'].startswith(IMG_BASE64_PREFIX):
doc_item['thumbnail'] = f"/v1/document/image/{kb_id}-{doc_item['thumbnail']}"
return get_json_result(data={"total": tol, "docs": docs})
except Exception as e:
return server_error_response(e)
@manager.route('/infos', methods=['POST'])
@manager.route('/infos', methods=['POST']) # noqa: F821
@login_required
def docinfos():
req = request.json
doc_ids = req["doc_ids"]
for doc_id in doc_ids:
if not DocumentService.accessible(doc_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
docs = DocumentService.get_by_ids(doc_ids)
return get_json_result(data=list(docs.dicts()))
@manager.route('/thumbnails', methods=['GET'])
#@login_required
@manager.route('/thumbnails', methods=['GET']) # noqa: F821
# @login_required
def thumbnails():
doc_ids = request.args.get("doc_ids").split(",")
if not doc_ids:
return get_json_result(
data=False, retmsg='Lack of "Document ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "Document ID"', code=settings.RetCode.ARGUMENT_ERROR)
try:
docs = DocumentService.get_thumbnails(doc_ids)
for doc_item in docs:
if doc_item['thumbnail'] and not doc_item['thumbnail'].startswith(IMG_BASE64_PREFIX):
doc_item['thumbnail'] = f"/v1/document/image/{doc_item['kb_id']}-{doc_item['thumbnail']}"
return get_json_result(data={d["id"]: d["thumbnail"] for d in docs})
except Exception as e:
return server_error_response(e)
@manager.route('/change_status', methods=['POST'])
@manager.route('/change_status', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "status")
def change_status():
req = request.json
if str(req["status"]) not in ["0", "1"]:
get_json_result(
return get_json_result(
data=False,
retmsg='"Status" must be either 0 or 1!',
retcode=RetCode.ARGUMENT_ERROR)
message='"Status" must be either 0 or 1!',
code=settings.RetCode.ARGUMENT_ERROR)
if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR)
try:
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
e, kb = KnowledgebaseService.get_by_id(doc.kb_id)
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
if not DocumentService.update_by_id(
req["doc_id"], {"status": str(req["status"])}):
return get_data_error_result(
retmsg="Database error (Document update)!")
message="Database error (Document update)!")
if str(req["status"]) == "0":
ELASTICSEARCH.updateScriptByQuery(Q("term", doc_id=req["doc_id"]),
scripts="ctx._source.available_int=0;",
idxnm=search.index_name(
kb.tenant_id)
)
else:
ELASTICSEARCH.updateScriptByQuery(Q("term", doc_id=req["doc_id"]),
scripts="ctx._source.available_int=1;",
idxnm=search.index_name(
kb.tenant_id)
)
status = int(req["status"])
settings.docStoreConn.update({"doc_id": req["doc_id"]}, {"available_int": status},
search.index_name(kb.tenant_id), doc.kb_id)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id")
def rm():
req = request.json
doc_ids = req["doc_id"]
if isinstance(doc_ids, str): doc_ids = [doc_ids]
if isinstance(doc_ids, str):
doc_ids = [doc_ids]
for doc_id in doc_ids:
if not DocumentService.accessible4deletion(doc_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
root_folder = FileService.get_root_folder(current_user.id)
pf_id = root_folder["id"]
FileService.init_knowledgebase_docs(pf_id, current_user.id)
@ -283,88 +318,105 @@ def rm():
try:
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
b, n = File2DocumentService.get_minio_address(doc_id=doc_id)
b, n = File2DocumentService.get_storage_address(doc_id=doc_id)
TaskService.filter_delete([Task.doc_id == doc_id])
if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
f2d = File2DocumentService.get_by_document_id(doc_id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
deleted_file_count = FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
File2DocumentService.delete_by_document_id(doc_id)
MINIO.rm(b, n)
if deleted_file_count > 0:
STORAGE_IMPL.rm(b, n)
except Exception as e:
errors += str(e)
if errors:
return get_json_result(data=False, retmsg=errors, retcode=RetCode.SERVER_ERROR)
return get_json_result(data=False, message=errors, code=settings.RetCode.SERVER_ERROR)
return get_json_result(data=True)
@manager.route('/run', methods=['POST'])
@manager.route('/run', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_ids", "run")
def run():
def run():
req = request.json
for doc_id in req["doc_ids"]:
if not DocumentService.accessible(doc_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
for id in req["doc_ids"]:
info = {"run": str(req["run"]), "progress": 0}
if str(req["run"]) == TaskStatus.RUNNING.value:
if str(req["run"]) == TaskStatus.RUNNING.value and req.get("delete", False):
info["progress_msg"] = ""
info["chunk_num"] = 0
info["token_num"] = 0
DocumentService.update_by_id(id, info)
# if str(req["run"]) == TaskStatus.CANCEL.value:
tenant_id = DocumentService.get_tenant_id(id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
ELASTICSEARCH.deleteByQuery(
Q("match", doc_id=id), idxnm=search.index_name(tenant_id))
return get_data_error_result(message="Tenant not found!")
e, doc = DocumentService.get_by_id(id)
if not e:
return get_data_error_result(message="Document not found!")
if req.get("delete", False):
TaskService.filter_delete([Task.doc_id == id])
if settings.docStoreConn.indexExist(search.index_name(tenant_id), doc.kb_id):
settings.docStoreConn.delete({"doc_id": id}, search.index_name(tenant_id), doc.kb_id)
if str(req["run"]) == TaskStatus.RUNNING.value:
TaskService.filter_delete([Task.doc_id == id])
e, doc = DocumentService.get_by_id(id)
doc = doc.to_dict()
doc["tenant_id"] = tenant_id
bucket, name = File2DocumentService.get_minio_address(doc_id=doc["id"])
queue_tasks(doc, bucket, name)
bucket, name = File2DocumentService.get_storage_address(doc_id=doc["id"])
queue_tasks(doc, bucket, name, 0)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/rename', methods=['POST'])
@manager.route('/rename', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "name")
def rename():
req = request.json
if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if pathlib.Path(req["name"].lower()).suffix != pathlib.Path(
doc.name.lower()).suffix:
return get_json_result(
data=False,
retmsg="The extension of file can't be changed",
retcode=RetCode.ARGUMENT_ERROR)
message="The extension of file can't be changed",
code=settings.RetCode.ARGUMENT_ERROR)
for d in DocumentService.query(name=req["name"], kb_id=doc.kb_id):
if d.name == req["name"]:
return get_data_error_result(
retmsg="Duplicated document name in the same knowledgebase.")
message="Duplicated document name in the same knowledgebase.")
if not DocumentService.update_by_id(
req["doc_id"], {"name": req["name"]}):
return get_data_error_result(
retmsg="Database error (Document rename)!")
message="Database error (Document rename)!")
informs = File2DocumentService.get_by_document_id(req["doc_id"])
if informs:
@ -376,16 +428,16 @@ def rename():
return server_error_response(e)
@manager.route('/get/<doc_id>', methods=['GET'])
@manager.route('/get/<doc_id>', methods=['GET']) # noqa: F821
# @login_required
def get(doc_id):
try:
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
b, n = File2DocumentService.get_minio_address(doc_id=doc_id)
response = flask.make_response(MINIO.get(b, n))
b, n = File2DocumentService.get_storage_address(doc_id=doc_id)
response = flask.make_response(STORAGE_IMPL.get(b, n))
ext = re.search(r"\.([^.]+)$", doc.name)
if ext:
@ -401,15 +453,22 @@ def get(doc_id):
return server_error_response(e)
@manager.route('/change_parser', methods=['POST'])
@manager.route('/change_parser', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "parser_id")
def change_parser():
req = request.json
if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if doc.parser_id.lower() == req["parser_id"].lower():
if "parser_config" in req:
if req["parser_config"] == doc.parser_config:
@ -417,59 +476,158 @@ def change_parser():
else:
return get_json_result(data=True)
if doc.type == FileType.VISUAL or re.search(
r"\.(ppt|pptx|pages)$", doc.name):
return get_data_error_result(retmsg="Not supported yet!")
if ((doc.type == FileType.VISUAL and req["parser_id"] != "picture")
or (re.search(
r"\.(ppt|pptx|pages)$", doc.name) and req["parser_id"] != "presentation")):
return get_data_error_result(message="Not supported yet!")
e = DocumentService.update_by_id(doc.id,
{"parser_id": req["parser_id"], "progress": 0, "progress_msg": "",
"run": TaskStatus.UNSTART.value})
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
if "parser_config" in req:
DocumentService.update_parser_config(doc.id, req["parser_config"])
if doc.token_num > 0:
e = DocumentService.increment_chunk_num(doc.id, doc.kb_id, doc.token_num * -1, doc.chunk_num * -1,
doc.process_duation * -1)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(req["doc_id"])
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
ELASTICSEARCH.deleteByQuery(
Q("match", doc_id=doc.id), idxnm=search.index_name(tenant_id))
return get_data_error_result(message="Tenant not found!")
if settings.docStoreConn.indexExist(search.index_name(tenant_id), doc.kb_id):
settings.docStoreConn.delete({"doc_id": doc.id}, search.index_name(tenant_id), doc.kb_id)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/image/<image_id>', methods=['GET'])
@manager.route('/image/<image_id>', methods=['GET']) # noqa: F821
# @login_required
def get_image(image_id):
try:
arr = image_id.split("-")
if len(arr) != 2:
return get_data_error_result(message="Image not found.")
bkt, nm = image_id.split("-")
response = flask.make_response(MINIO.get(bkt, nm))
response = flask.make_response(STORAGE_IMPL.get(bkt, nm))
response.headers.set('Content-Type', 'image/JPEG')
return response
except Exception as e:
return server_error_response(e)
@manager.route('/upload_and_parse', methods=['POST'])
@manager.route('/upload_and_parse', methods=['POST']) # noqa: F821
@login_required
@validate_request("conversation_id")
def upload_and_parse():
if 'file' not in request.files:
return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file')
for file_obj in file_objs:
if file_obj.filename == '':
return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=settings.RetCode.ARGUMENT_ERROR)
doc_ids = doc_upload_and_parse(request.form.get("conversation_id"), file_objs, current_user.id)
return get_json_result(data=doc_ids)
@manager.route('/parse', methods=['POST']) # noqa: F821
@login_required
def parse():
url = request.json.get("url") if request.json else ""
if url:
if not is_valid_url(url):
return get_json_result(
data=False, message='The URL format is invalid', code=settings.RetCode.ARGUMENT_ERROR)
download_path = os.path.join(get_project_base_directory(), "logs/downloads")
os.makedirs(download_path, exist_ok=True)
from seleniumwire.webdriver import Chrome, ChromeOptions
options = ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_experimental_option('prefs', {
'download.default_directory': download_path,
'download.prompt_for_download': False,
'download.directory_upgrade': True,
'safebrowsing.enabled': True
})
driver = Chrome(options=options)
driver.get(url)
res_headers = [r.response.headers for r in driver.requests if r and r.response]
if len(res_headers) > 1:
sections = RAGFlowHtmlParser().parser_txt(driver.page_source)
driver.quit()
return get_json_result(data="\n".join(sections))
class File:
filename: str
filepath: str
def __init__(self, filename, filepath):
self.filename = filename
self.filepath = filepath
def read(self):
with open(self.filepath, "rb") as f:
return f.read()
r = re.search(r"filename=\"([^\"]+)\"", str(res_headers))
if not r or not r.group(1):
return get_json_result(
data=False, message="Can't not identify downloaded file", code=settings.RetCode.ARGUMENT_ERROR)
f = File(r.group(1), os.path.join(download_path, r.group(1)))
txt = FileService.parse_docs([f], current_user.id)
return get_json_result(data=txt)
if 'file' not in request.files:
return get_json_result(
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file')
txt = FileService.parse_docs(file_objs, current_user.id)
return get_json_result(data=txt)
@manager.route('/set_meta', methods=['POST']) # noqa: F821
@login_required
@validate_request("doc_id", "meta")
def set_meta():
req = request.json
if not DocumentService.accessible(req["doc_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
meta = json.loads(req["meta"])
except Exception as e:
return get_json_result(
data=False, message=f'Json syntax error: {e}', code=settings.RetCode.ARGUMENT_ERROR)
if not isinstance(meta, dict):
return get_json_result(
data=False, message='Meta data should be in Json map format, like {"key": "value"}', code=settings.RetCode.ARGUMENT_ERROR)
try:
e, doc = DocumentService.get_by_id(req["doc_id"])
if not e:
return get_data_error_result(message="Document not found!")
if not DocumentService.update_by_id(
req["doc_id"], {"meta_fields": meta}):
return get_data_error_result(
message="Database error (meta updates)!")
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)

View File

@ -13,9 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License
#
from elasticsearch_dsl import Q
from api.db.db_models import File2Document
from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService
@ -26,13 +24,11 @@ from api.utils.api_utils import server_error_response, get_data_error_result, va
from api.utils import get_uuid
from api.db import FileType
from api.db.services.document_service import DocumentService
from api.settings import RetCode
from api import settings
from api.utils.api_utils import get_json_result
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
@manager.route('/convert', methods=['POST'])
@manager.route('/convert', methods=['POST']) # noqa: F821
@login_required
@validate_request("file_ids", "kb_ids")
def convert():
@ -42,8 +38,12 @@ def convert():
file2documents = []
try:
files = FileService.get_by_ids(file_ids)
files_set = dict({file.id: file for file in files})
for file_id in file_ids:
e, file = FileService.get_by_id(file_id)
file = files_set[file_id]
if not file:
return get_data_error_result(message="File not found!")
file_ids_list = [file_id]
if file.type == FileType.FOLDER.value:
file_ids_list = FileService.get_all_innermost_file_ids(file_id, [])
@ -54,13 +54,13 @@ def convert():
doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
File2DocumentService.delete_by_file_id(id)
# insert
@ -68,16 +68,16 @@ def convert():
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
e, file = FileService.get_by_id(id)
if not e:
return get_data_error_result(
retmsg="Can't find this file!")
message="Can't find this file!")
doc = DocumentService.insert({
"id": get_uuid(),
"kb_id": kb.id,
"parser_id": kb.parser_id,
"parser_id": FileService.get_parser(file.type, file.name, kb.parser_id),
"parser_config": kb.parser_config,
"created_by": current_user.id,
"type": file.type,
@ -90,13 +90,14 @@ def convert():
"file_id": id,
"document_id": doc.id,
})
file2documents.append(file2document.to_json())
return get_json_result(data=file2documents)
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@login_required
@validate_request("file_ids")
def rm():
@ -104,26 +105,26 @@ def rm():
file_ids = req["file_ids"]
if not file_ids:
return get_json_result(
data=False, retmsg='Lack of "Files ID"', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='Lack of "Files ID"', code=settings.RetCode.ARGUMENT_ERROR)
try:
for file_id in file_ids:
informs = File2DocumentService.get_by_file_id(file_id)
if not informs:
return get_data_error_result(retmsg="Inform not found!")
return get_data_error_result(message="Inform not found!")
for inform in informs:
if not inform:
return get_data_error_result(retmsg="Inform not found!")
return get_data_error_result(message="Inform not found!")
File2DocumentService.delete_by_file_id(file_id)
doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)

View File

@ -18,7 +18,6 @@ import pathlib
import re
import flask
from elasticsearch_dsl import Q
from flask import request
from flask_login import login_required, current_user
@ -29,15 +28,13 @@ from api.utils import get_uuid
from api.db import FileType, FileSource
from api.db.services import duplicate_name
from api.db.services.file_service import FileService
from api.settings import RetCode
from api import settings
from api.utils.api_utils import get_json_result
from api.utils.file_utils import filename_type
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
from rag.utils.minio_conn import MINIO
from rag.utils.storage_factory import STORAGE_IMPL
@manager.route('/upload', methods=['POST'])
@manager.route('/upload', methods=['POST']) # noqa: F821
@login_required
# @validate_request("parent_id")
def upload():
@ -49,29 +46,26 @@ def upload():
if 'file' not in request.files:
return get_json_result(
data=False, retmsg='No file part!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file part!', code=settings.RetCode.ARGUMENT_ERROR)
file_objs = request.files.getlist('file')
for file_obj in file_objs:
if file_obj.filename == '':
return get_json_result(
data=False, retmsg='No file selected!', retcode=RetCode.ARGUMENT_ERROR)
data=False, message='No file selected!', code=settings.RetCode.ARGUMENT_ERROR)
file_res = []
try:
e, pf_folder = FileService.get_by_id(pf_id)
if not e:
return get_data_error_result( message="Can't find this folder!")
for file_obj in file_objs:
e, file = FileService.get_by_id(pf_id)
if not e:
return get_data_error_result(
retmsg="Can't find this folder!")
MAX_FILE_NUM_PER_USER = int(os.environ.get('MAX_FILE_NUM_PER_USER', 0))
if MAX_FILE_NUM_PER_USER > 0 and DocumentService.get_doc_count(current_user.id) >= MAX_FILE_NUM_PER_USER:
return get_data_error_result(
retmsg="Exceed the maximum file number of a free user!")
return get_data_error_result( message="Exceed the maximum file number of a free user!")
# split file name path
if not file_obj.filename:
e, file = FileService.get_by_id(pf_id)
file_obj_names = [file.name, file_obj.filename]
file_obj_names = [pf_folder.name, file_obj.filename]
else:
full_path = '/' + file_obj.filename
file_obj_names = full_path.split('/')
@ -85,20 +79,20 @@ def upload():
if file_len != len_id_list:
e, file = FileService.get_by_id(file_id_list[len_id_list - 1])
if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
last_folder = FileService.create_folder(file, file_id_list[len_id_list - 1], file_obj_names,
len_id_list)
else:
e, file = FileService.get_by_id(file_id_list[len_id_list - 2])
if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
last_folder = FileService.create_folder(file, file_id_list[len_id_list - 2], file_obj_names,
len_id_list)
# file type
filetype = filename_type(file_obj_names[file_len - 1])
location = file_obj_names[file_len - 1]
while MINIO.obj_exist(last_folder.id, location):
while STORAGE_IMPL.obj_exist(last_folder.id, location):
location += "_"
blob = file_obj.read()
filename = duplicate_name(
@ -116,14 +110,14 @@ def upload():
"size": len(blob),
}
file = FileService.insert(file)
MINIO.put(last_folder.id, location, blob)
STORAGE_IMPL.put(last_folder.id, location, blob)
file_res.append(file.to_json())
return get_json_result(data=file_res)
except Exception as e:
return server_error_response(e)
@manager.route('/create', methods=['POST'])
@manager.route('/create', methods=['POST']) # noqa: F821
@login_required
@validate_request("name")
def create():
@ -137,10 +131,10 @@ def create():
try:
if not FileService.is_parent_folder_exist(pf_id):
return get_json_result(
data=False, retmsg="Parent Folder Doesn't Exist!", retcode=RetCode.OPERATING_ERROR)
data=False, message="Parent Folder Doesn't Exist!", code=settings.RetCode.OPERATING_ERROR)
if FileService.query(name=req["name"], parent_id=pf_id):
return get_data_error_result(
retmsg="Duplicated folder name in the same folder.")
message="Duplicated folder name in the same folder.")
if input_file_type == FileType.FOLDER.value:
file_type = FileType.FOLDER.value
@ -163,7 +157,7 @@ def create():
return server_error_response(e)
@manager.route('/list', methods=['GET'])
@manager.route('/list', methods=['GET']) # noqa: F821
@login_required
def list_files():
pf_id = request.args.get("parent_id")
@ -181,21 +175,21 @@ def list_files():
try:
e, file = FileService.get_by_id(pf_id)
if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
files, total = FileService.get_by_pf_id(
current_user.id, pf_id, page_number, items_per_page, orderby, desc, keywords)
parent_folder = FileService.get_parent_folder(pf_id)
if not FileService.get_parent_folder(pf_id):
return get_json_result(retmsg="File not found!")
if not parent_folder:
return get_json_result(message="File not found!")
return get_json_result(data={"total": total, "files": files, "parent_folder": parent_folder.to_json()})
except Exception as e:
return server_error_response(e)
@manager.route('/root_folder', methods=['GET'])
@manager.route('/root_folder', methods=['GET']) # noqa: F821
@login_required
def get_root_folder():
try:
@ -205,14 +199,14 @@ def get_root_folder():
return server_error_response(e)
@manager.route('/parent_folder', methods=['GET'])
@manager.route('/parent_folder', methods=['GET']) # noqa: F821
@login_required
def get_parent_folder():
file_id = request.args.get("file_id")
try:
e, file = FileService.get_by_id(file_id)
if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
parent_folder = FileService.get_parent_folder(file_id)
return get_json_result(data={"parent_folder": parent_folder.to_json()})
@ -220,14 +214,14 @@ def get_parent_folder():
return server_error_response(e)
@manager.route('/all_parent_folder', methods=['GET'])
@manager.route('/all_parent_folder', methods=['GET']) # noqa: F821
@login_required
def get_all_parent_folders():
file_id = request.args.get("file_id")
try:
e, file = FileService.get_by_id(file_id)
if not e:
return get_data_error_result(retmsg="Folder not found!")
return get_data_error_result(message="Folder not found!")
parent_folders = FileService.get_all_parent_folders(file_id)
parent_folders_res = []
@ -238,7 +232,7 @@ def get_all_parent_folders():
return server_error_response(e)
@manager.route('/rm', methods=['POST'])
@manager.route('/rm', methods=['POST']) # noqa: F821
@login_required
@validate_request("file_ids")
def rm():
@ -248,9 +242,9 @@ def rm():
for file_id in file_ids:
e, file = FileService.get_by_id(file_id)
if not e:
return get_data_error_result(retmsg="File or Folder not found!")
return get_data_error_result(message="File or Folder not found!")
if not file.tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if file.source_type == FileSource.KNOWLEDGEBASE:
continue
@ -259,13 +253,13 @@ def rm():
for inner_file_id in file_id_list:
e, file = FileService.get_by_id(inner_file_id)
if not e:
return get_data_error_result(retmsg="File not found!")
MINIO.rm(file.parent_id, file.location)
return get_data_error_result(message="File not found!")
STORAGE_IMPL.rm(file.parent_id, file.location)
FileService.delete_folder_by_pf_id(current_user.id, file_id)
else:
if not FileService.delete(file):
return get_data_error_result(
retmsg="Database error (File removal)!")
message="Database error (File removal)!")
# delete file2document
informs = File2DocumentService.get_by_file_id(file_id)
@ -273,13 +267,13 @@ def rm():
doc_id = inform.document_id
e, doc = DocumentService.get_by_id(doc_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
return get_data_error_result(message="Document not found!")
tenant_id = DocumentService.get_tenant_id(doc_id)
if not tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
if not DocumentService.remove_document(doc, tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
File2DocumentService.delete_by_file_id(file_id)
return get_json_result(data=True)
@ -287,7 +281,7 @@ def rm():
return server_error_response(e)
@manager.route('/rename', methods=['POST'])
@manager.route('/rename', methods=['POST']) # noqa: F821
@login_required
@validate_request("file_id", "name")
def rename():
@ -295,44 +289,50 @@ def rename():
try:
e, file = FileService.get_by_id(req["file_id"])
if not e:
return get_data_error_result(retmsg="File not found!")
if pathlib.Path(req["name"].lower()).suffix != pathlib.Path(
return get_data_error_result(message="File not found!")
if file.type != FileType.FOLDER.value \
and pathlib.Path(req["name"].lower()).suffix != pathlib.Path(
file.name.lower()).suffix:
return get_json_result(
data=False,
retmsg="The extension of file can't be changed",
retcode=RetCode.ARGUMENT_ERROR)
message="The extension of file can't be changed",
code=settings.RetCode.ARGUMENT_ERROR)
for file in FileService.query(name=req["name"], pf_id=file.parent_id):
if file.name == req["name"]:
return get_data_error_result(
retmsg="Duplicated file name in the same folder.")
message="Duplicated file name in the same folder.")
if not FileService.update_by_id(
req["file_id"], {"name": req["name"]}):
return get_data_error_result(
retmsg="Database error (File rename)!")
message="Database error (File rename)!")
informs = File2DocumentService.get_by_file_id(req["file_id"])
if informs:
if not DocumentService.update_by_id(
informs[0].document_id, {"name": req["name"]}):
return get_data_error_result(
retmsg="Database error (Document rename)!")
message="Database error (Document rename)!")
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/get/<file_id>', methods=['GET'])
# @login_required
@manager.route('/get/<file_id>', methods=['GET']) # noqa: F821
@login_required
def get(file_id):
try:
e, file = FileService.get_by_id(file_id)
if not e:
return get_data_error_result(retmsg="Document not found!")
b, n = File2DocumentService.get_minio_address(file_id=file_id)
response = flask.make_response(MINIO.get(b, n))
return get_data_error_result(message="Document not found!")
blob = STORAGE_IMPL.get(file.parent_id, file.location)
if not blob:
b, n = File2DocumentService.get_storage_address(file_id=file_id)
blob = STORAGE_IMPL.get(b, n)
response = flask.make_response(blob)
ext = re.search(r"\.([^.]+)$", file.name)
if ext:
if file.type == FileType.VISUAL.value:
@ -347,7 +347,7 @@ def get(file_id):
return server_error_response(e)
@manager.route('/mv', methods=['POST'])
@manager.route('/mv', methods=['POST']) # noqa: F821
@login_required
@validate_request("src_file_ids", "dest_file_id")
def move():
@ -355,15 +355,20 @@ def move():
try:
file_ids = req["src_file_ids"]
parent_id = req["dest_file_id"]
files = FileService.get_by_ids(file_ids)
files_dict = {}
for file in files:
files_dict[file.id] = file
for file_id in file_ids:
e, file = FileService.get_by_id(file_id)
if not e:
return get_data_error_result(retmsg="File or Folder not found!")
file = files_dict[file_id]
if not file:
return get_data_error_result(message="File or Folder not found!")
if not file.tenant_id:
return get_data_error_result(retmsg="Tenant not found!")
return get_data_error_result(message="Tenant not found!")
fe, _ = FileService.get_by_id(parent_id)
if not fe:
return get_data_error_result(retmsg="Parent Folder not found!")
return get_data_error_result(message="Parent Folder not found!")
FileService.move_file(file_ids, parent_id)
return get_json_result(data=True)
except Exception as e:

View File

@ -13,7 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
from elasticsearch_dsl import Q
import json
import os
from flask import request
from flask_login import login_required, current_user
@ -22,26 +24,36 @@ from api.db.services.document_service import DocumentService
from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService
from api.db.services.user_service import TenantService, UserTenantService
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.utils import get_uuid, get_format_time
from api.db import StatusEnum, UserTenantRole, FileSource
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request, not_allowed_parameters
from api.utils import get_uuid
from api.db import StatusEnum, FileSource
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.db_models import Knowledgebase, File
from api.settings import stat_logger, RetCode
from api.db.db_models import File
from api.utils.api_utils import get_json_result
from api import settings
from rag.nlp import search
from rag.utils.es_conn import ELASTICSEARCH
from api.constants import DATASET_NAME_LIMIT
from rag.settings import PAGERANK_FLD
@manager.route('/create', methods=['post'])
@manager.route('/create', methods=['post']) # noqa: F821
@login_required
@validate_request("name")
def create():
req = request.json
req["name"] = req["name"].strip()
req["name"] = duplicate_name(
dataset_name = req["name"]
if not isinstance(dataset_name, str):
return get_data_error_result(message="Dataset name must be string.")
if dataset_name == "":
return get_data_error_result(message="Dataset name can't be empty.")
if len(dataset_name) >= DATASET_NAME_LIMIT:
return get_data_error_result(
message=f"Dataset name length is {len(dataset_name)} which is large than {DATASET_NAME_LIMIT}")
dataset_name = dataset_name.strip()
dataset_name = duplicate_name(
KnowledgebaseService.query,
name=req["name"],
name=dataset_name,
tenant_id=current_user.id,
status=StatusEnum.VALID.value)
try:
@ -50,7 +62,7 @@ def create():
req["created_by"] = current_user.id
e, t = TenantService.get_by_id(current_user.id)
if not e:
return get_data_error_result(retmsg="Tenant not found.")
return get_data_error_result(message="Tenant not found.")
req["embd_id"] = t.embd_id
if not KnowledgebaseService.save(**req):
return get_data_error_result()
@ -59,95 +71,282 @@ def create():
return server_error_response(e)
@manager.route('/update', methods=['post'])
@manager.route('/update', methods=['post']) # noqa: F821
@login_required
@validate_request("kb_id", "name", "description", "permission", "parser_id")
@validate_request("kb_id", "name", "description", "parser_id")
@not_allowed_parameters("id", "tenant_id", "created_by", "create_time", "update_time", "create_date", "update_date", "created_by")
def update():
req = request.json
req["name"] = req["name"].strip()
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
if not KnowledgebaseService.query(
created_by=current_user.id, id=req["kb_id"]):
return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
e, kb = KnowledgebaseService.get_by_id(req["kb_id"])
if not e:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
message="Can't find this knowledgebase!")
if req.get("parser_id", "") == "tag" and os.environ.get('DOC_ENGINE', "elasticsearch") == "infinity":
return get_json_result(
data=False,
message='The chunk method Tag has not been supported by Infinity yet.',
code=settings.RetCode.OPERATING_ERROR
)
if req["name"].lower() != kb.name.lower() \
and len(KnowledgebaseService.query(name=req["name"], tenant_id=current_user.id, status=StatusEnum.VALID.value)) > 1:
and len(
KnowledgebaseService.query(name=req["name"], tenant_id=current_user.id, status=StatusEnum.VALID.value)) > 1:
return get_data_error_result(
retmsg="Duplicated knowledgebase name.")
message="Duplicated knowledgebase name.")
del req["kb_id"]
if not KnowledgebaseService.update_by_id(kb.id, req):
return get_data_error_result()
if kb.pagerank != req.get("pagerank", 0):
if req.get("pagerank", 0) > 0:
settings.docStoreConn.update({"kb_id": kb.id}, {PAGERANK_FLD: req["pagerank"]},
search.index_name(kb.tenant_id), kb.id)
else:
# Elasticsearch requires PAGERANK_FLD be non-zero!
settings.docStoreConn.update({"exists": PAGERANK_FLD}, {"remove": PAGERANK_FLD},
search.index_name(kb.tenant_id), kb.id)
e, kb = KnowledgebaseService.get_by_id(kb.id)
if not e:
return get_data_error_result(
retmsg="Database error (Knowledgebase rename)!")
message="Database error (Knowledgebase rename)!")
kb = kb.to_dict()
kb.update(req)
return get_json_result(data=kb.to_json())
except Exception as e:
return server_error_response(e)
@manager.route('/detail', methods=['GET'])
@login_required
def detail():
kb_id = request.args["kb_id"]
try:
kb = KnowledgebaseService.get_detail(kb_id)
if not kb:
return get_data_error_result(
retmsg="Can't find this knowledgebase!")
return get_json_result(data=kb)
except Exception as e:
return server_error_response(e)
@manager.route('/list', methods=['GET'])
@manager.route('/detail', methods=['GET']) # noqa: F821
@login_required
def list_kbs():
page_number = request.args.get("page", 1)
items_per_page = request.args.get("page_size", 150)
orderby = request.args.get("orderby", "create_time")
desc = request.args.get("desc", True)
def detail():
kb_id = request.args["kb_id"]
try:
tenants = TenantService.get_joined_tenants_by_user_id(current_user.id)
kbs = KnowledgebaseService.get_by_tenant_ids(
[m["tenant_id"] for m in tenants], current_user.id, page_number, items_per_page, orderby, desc)
return get_json_result(data=kbs)
tenants = UserTenantService.query(user_id=current_user.id)
for tenant in tenants:
if KnowledgebaseService.query(
tenant_id=tenant.tenant_id, id=kb_id):
break
else:
return get_json_result(
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
kb = KnowledgebaseService.get_detail(kb_id)
if not kb:
return get_data_error_result(
message="Can't find this knowledgebase!")
return get_json_result(data=kb)
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['post'])
@manager.route('/list', methods=['POST']) # noqa: F821
@login_required
def list_kbs():
keywords = request.args.get("keywords", "")
page_number = int(request.args.get("page", 0))
items_per_page = int(request.args.get("page_size", 0))
parser_id = request.args.get("parser_id")
orderby = request.args.get("orderby", "create_time")
desc = request.args.get("desc", True)
req = request.get_json()
owner_ids = req.get("owner_ids", [])
try:
if not owner_ids:
tenants = TenantService.get_joined_tenants_by_user_id(current_user.id)
tenants = [m["tenant_id"] for m in tenants]
kbs, total = KnowledgebaseService.get_by_tenant_ids(
tenants, current_user.id, page_number,
items_per_page, orderby, desc, keywords, parser_id)
else:
tenants = owner_ids
kbs, total = KnowledgebaseService.get_by_tenant_ids(
tenants, current_user.id, 0,
0, orderby, desc, keywords, parser_id)
kbs = [kb for kb in kbs if kb["tenant_id"] in tenants]
if page_number and items_per_page:
kbs = kbs[(page_number-1)*items_per_page:page_number*items_per_page]
total = len(kbs)
return get_json_result(data={"kbs": kbs, "total": total})
except Exception as e:
return server_error_response(e)
@manager.route('/rm', methods=['post']) # noqa: F821
@login_required
@validate_request("kb_id")
def rm():
req = request.json
if not KnowledgebaseService.accessible4deletion(req["kb_id"], current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
try:
kbs = KnowledgebaseService.query(
created_by=current_user.id, id=req["kb_id"])
created_by=current_user.id, id=req["kb_id"])
if not kbs:
return get_json_result(
data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
data=False, message='Only owner of knowledgebase authorized for this operation.',
code=settings.RetCode.OPERATING_ERROR)
for doc in DocumentService.query(kb_id=req["kb_id"]):
if not DocumentService.remove_document(doc, kbs[0].tenant_id):
return get_data_error_result(
retmsg="Database error (Document removal)!")
message="Database error (Document removal)!")
f2d = File2DocumentService.get_by_document_id(doc.id)
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
if f2d:
FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])
File2DocumentService.delete_by_document_id(doc.id)
FileService.filter_delete(
[File.source_type == FileSource.KNOWLEDGEBASE, File.type == "folder", File.name == kbs[0].name])
if not KnowledgebaseService.delete_by_id(req["kb_id"]):
return get_data_error_result(
retmsg="Database error (Knowledgebase removal)!")
message="Database error (Knowledgebase removal)!")
for kb in kbs:
settings.docStoreConn.delete({"kb_id": kb.id}, search.index_name(kb.tenant_id), kb.id)
settings.docStoreConn.deleteIdx(search.index_name(kb.tenant_id), kb.id)
return get_json_result(data=True)
except Exception as e:
return server_error_response(e)
@manager.route('/<kb_id>/tags', methods=['GET']) # noqa: F821
@login_required
def list_tags(kb_id):
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
tags = settings.retrievaler.all_tags(current_user.id, [kb_id])
return get_json_result(data=tags)
@manager.route('/tags', methods=['GET']) # noqa: F821
@login_required
def list_tags_from_kbs():
kb_ids = request.args.get("kb_ids", "").split(",")
for kb_id in kb_ids:
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
tags = settings.retrievaler.all_tags(current_user.id, kb_ids)
return get_json_result(data=tags)
@manager.route('/<kb_id>/rm_tags', methods=['POST']) # noqa: F821
@login_required
def rm_tags(kb_id):
req = request.json
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
e, kb = KnowledgebaseService.get_by_id(kb_id)
for t in req["tags"]:
settings.docStoreConn.update({"tag_kwd": t, "kb_id": [kb_id]},
{"remove": {"tag_kwd": t}},
search.index_name(kb.tenant_id),
kb_id)
return get_json_result(data=True)
@manager.route('/<kb_id>/rename_tag', methods=['POST']) # noqa: F821
@login_required
def rename_tags(kb_id):
req = request.json
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
e, kb = KnowledgebaseService.get_by_id(kb_id)
settings.docStoreConn.update({"tag_kwd": req["from_tag"], "kb_id": [kb_id]},
{"remove": {"tag_kwd": req["from_tag"].strip()}, "add": {"tag_kwd": req["to_tag"]}},
search.index_name(kb.tenant_id),
kb_id)
return get_json_result(data=True)
@manager.route('/<kb_id>/knowledge_graph', methods=['GET']) # noqa: F821
@login_required
def knowledge_graph(kb_id):
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
_, kb = KnowledgebaseService.get_by_id(kb_id)
req = {
"kb_id": [kb_id],
"knowledge_graph_kwd": ["graph"]
}
obj = {"graph": {}, "mind_map": {}}
if not settings.docStoreConn.indexExist(search.index_name(kb.tenant_id), kb_id):
return get_json_result(data=obj)
sres = settings.retrievaler.search(req, search.index_name(kb.tenant_id), [kb_id])
if not len(sres.ids):
return get_json_result(data=obj)
for id in sres.ids[:1]:
ty = sres.field[id]["knowledge_graph_kwd"]
try:
content_json = json.loads(sres.field[id]["content_with_weight"])
except Exception:
continue
obj[ty] = content_json
if "nodes" in obj["graph"]:
obj["graph"]["nodes"] = sorted(obj["graph"]["nodes"], key=lambda x: x.get("pagerank", 0), reverse=True)[:256]
if "edges" in obj["graph"]:
node_id_set = { o["id"] for o in obj["graph"]["nodes"] }
filtered_edges = [o for o in obj["graph"]["edges"] if o["source"] != o["target"] and o["source"] in node_id_set and o["target"] in node_id_set]
obj["graph"]["edges"] = sorted(filtered_edges, key=lambda x: x.get("weight", 0), reverse=True)[:128]
return get_json_result(data=obj)
@manager.route('/<kb_id>/knowledge_graph', methods=['DELETE']) # noqa: F821
@login_required
def delete_knowledge_graph(kb_id):
if not KnowledgebaseService.accessible(kb_id, current_user.id):
return get_json_result(
data=False,
message='No authorization.',
code=settings.RetCode.AUTHENTICATION_ERROR
)
_, kb = KnowledgebaseService.get_by_id(kb_id)
settings.docStoreConn.delete({"knowledge_graph_kwd": ["graph", "subgraph", "entity", "relation"]}, search.index_name(kb.tenant_id), kb_id)
return get_json_result(data=True)

97
api/apps/langfuse_app.py Normal file
View File

@ -0,0 +1,97 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from flask import request
from flask_login import current_user, login_required
from langfuse import Langfuse
from api.db.db_models import DB
from api.db.services.langfuse_service import TenantLangfuseService
from api.utils.api_utils import get_error_data_result, get_json_result, server_error_response, validate_request
@manager.route("/api_key", methods=["POST", "PUT"]) # noqa: F821
@login_required
@validate_request("secret_key", "public_key", "host")
def set_api_key():
req = request.get_json()
secret_key = req.get("secret_key", "")
public_key = req.get("public_key", "")
host = req.get("host", "")
if not all([secret_key, public_key, host]):
return get_error_data_result(message="Missing required fields")
langfuse_keys = dict(
tenant_id=current_user.id,
secret_key=secret_key,
public_key=public_key,
host=host,
)
langfuse = Langfuse(public_key=langfuse_keys["public_key"], secret_key=langfuse_keys["secret_key"], host=langfuse_keys["host"])
if not langfuse.auth_check():
return get_error_data_result(message="Invalid Langfuse keys")
langfuse_entry = TenantLangfuseService.filter_by_tenant(tenant_id=current_user.id)
with DB.atomic():
try:
if not langfuse_entry:
TenantLangfuseService.save(**langfuse_keys)
else:
TenantLangfuseService.update_by_tenant(tenant_id=current_user.id, langfuse_keys=langfuse_keys)
return get_json_result(data=langfuse_keys)
except Exception as e:
server_error_response(e)
@manager.route("/api_key", methods=["GET"]) # noqa: F821
@login_required
@validate_request()
def get_api_key():
langfuse_entry = TenantLangfuseService.filter_by_tenant_with_info(tenant_id=current_user.id)
if not langfuse_entry:
return get_json_result(message="Have not record any Langfuse keys.")
langfuse = Langfuse(public_key=langfuse_entry["public_key"], secret_key=langfuse_entry["secret_key"], host=langfuse_entry["host"])
try:
if not langfuse.auth_check():
return get_error_data_result(message="Invalid Langfuse keys loaded")
except langfuse.api.core.api_error.ApiError as api_err:
return get_json_result(message=f"Error from Langfuse: {api_err}")
except Exception as e:
server_error_response(e)
langfuse_entry["project_id"] = langfuse.api.projects.get().dict()["data"][0]["id"]
langfuse_entry["project_name"] = langfuse.api.projects.get().dict()["data"][0]["name"]
return get_json_result(data=langfuse_entry)
@manager.route("/api_key", methods=["DELETE"]) # noqa: F821
@login_required
@validate_request()
def delete_api_key():
langfuse_entry = TenantLangfuseService.filter_by_tenant(tenant_id=current_user.id)
if not langfuse_entry:
return get_json_result(message="Have not record any Langfuse keys.")
with DB.atomic():
try:
TenantLangfuseService.delete_model(langfuse_entry)
return get_json_result(data=True)
except Exception as e:
server_error_response(e)

View File

@ -13,28 +13,44 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import json
import os
from flask import request
from flask_login import login_required, current_user
from api.db.services.llm_service import LLMFactoriesService, TenantLLMService, LLMService
from api import settings
from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
from api.db import StatusEnum, LLMType
from api.db.db_models import TenantLLM
from api.utils.api_utils import get_json_result
from rag.llm import EmbeddingModel, ChatModel, RerankModel,CvModel
import requests
import ast
from api.utils.file_utils import get_project_base_directory
from rag.llm import EmbeddingModel, ChatModel, RerankModel, CvModel, TTSModel
@manager.route('/factories', methods=['GET'])
@manager.route('/factories', methods=['GET']) # noqa: F821
@login_required
def factories():
try:
fac = LLMFactoriesService.get_all()
return get_json_result(data=[f.to_dict() for f in fac if f.name not in ["Youdao", "FastEmbed", "BAAI"]])
fac = [f.to_dict() for f in fac if f.name not in ["Youdao", "FastEmbed", "BAAI"]]
llms = LLMService.get_all()
mdl_types = {}
for m in llms:
if m.status != StatusEnum.VALID.value:
continue
if m.fid not in mdl_types:
mdl_types[m.fid] = set([])
mdl_types[m.fid].add(m.model_type)
for f in fac:
f["model_types"] = list(mdl_types.get(f["name"], [LLMType.CHAT, LLMType.EMBEDDING, LLMType.RERANK,
LLMType.IMAGE2TEXT, LLMType.SPEECH2TEXT, LLMType.TTS]))
return get_json_result(data=fac)
except Exception as e:
return server_error_response(e)
@manager.route('/set_api_key', methods=['POST'])
@manager.route('/set_api_key', methods=['POST']) # noqa: F821
@login_required
@validate_request("llm_factory", "api_key")
def set_api_key():
@ -45,6 +61,7 @@ def set_api_key():
msg = ""
for llm in LLMService.query(fid=factory):
if not embd_passed and llm.model_type == LLMType.EMBEDDING.value:
assert factory in EmbeddingModel, f"Embedding model from {factory} is not supported yet."
mdl = EmbeddingModel[factory](
req["api_key"], llm.llm_name, base_url=req.get("base_url"))
try:
@ -55,99 +72,126 @@ def set_api_key():
except Exception as e:
msg += f"\nFail to access embedding model({llm.llm_name}) using this api key." + str(e)
elif not chat_passed and llm.model_type == LLMType.CHAT.value:
assert factory in ChatModel, f"Chat model from {factory} is not supported yet."
mdl = ChatModel[factory](
req["api_key"], llm.llm_name, base_url=req.get("base_url"))
try:
m, tc = mdl.chat(None, [{"role": "user", "content": "Hello! How are you doing!"}],
{"temperature": 0.9,'max_tokens':50})
if m.find("**ERROR**") >=0:
m, tc = mdl.chat(None, [{"role": "user", "content": "Hello! How are you doing!"}],
{"temperature": 0.9, 'max_tokens': 50})
if m.find("**ERROR**") >= 0:
raise Exception(m)
chat_passed = True
except Exception as e:
msg += f"\nFail to access model({llm.llm_name}) using this api key." + str(
e)
chat_passed = True
elif not rerank_passed and llm.model_type == LLMType.RERANK:
assert factory in RerankModel, f"Re-rank model from {factory} is not supported yet."
mdl = RerankModel[factory](
req["api_key"], llm.llm_name, base_url=req.get("base_url"))
try:
arr, tc = mdl.similarity("What's the weather?", ["Is it sunny today?"])
if len(arr) == 0 or tc == 0:
raise Exception("Fail")
rerank_passed = True
logging.debug(f'passed model rerank {llm.llm_name}')
except Exception as e:
msg += f"\nFail to access model({llm.llm_name}) using this api key." + str(
e)
rerank_passed = True
if any([embd_passed, chat_passed, rerank_passed]):
msg = ''
break
if msg:
return get_data_error_result(retmsg=msg)
return get_data_error_result(message=msg)
llm = {
llm_config = {
"api_key": req["api_key"],
"api_base": req.get("base_url", "")
}
for n in ["model_type", "llm_name"]:
if n in req:
llm[n] = req[n]
llm_config[n] = req[n]
if not TenantLLMService.filter_update(
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == factory], llm):
for llm in LLMService.query(fid=factory):
for llm in LLMService.query(fid=factory):
llm_config["max_tokens"]=llm.max_tokens
if not TenantLLMService.filter_update(
[TenantLLM.tenant_id == current_user.id,
TenantLLM.llm_factory == factory,
TenantLLM.llm_name == llm.llm_name],
llm_config):
TenantLLMService.save(
tenant_id=current_user.id,
llm_factory=factory,
llm_name=llm.llm_name,
model_type=llm.model_type,
api_key=req["api_key"],
api_base=req.get("base_url", "")
api_key=llm_config["api_key"],
api_base=llm_config["api_base"],
max_tokens=llm_config["max_tokens"]
)
return get_json_result(data=True)
@manager.route('/add_llm', methods=['POST'])
@manager.route('/add_llm', methods=['POST']) # noqa: F821
@login_required
@validate_request("llm_factory")
def add_llm():
req = request.json
factory = req["llm_factory"]
api_key = req.get("api_key", "x")
llm_name = req.get("llm_name")
def apikey_json(keys):
nonlocal req
return json.dumps({k: req.get(k, "") for k in keys})
if factory == "VolcEngine":
# For VolcEngine, due to its special authentication method
# Assemble volc_ak, volc_sk, endpoint_id into api_key
temp = list(ast.literal_eval(req["llm_name"]).items())[0]
llm_name = temp[0]
endpoint_id = temp[1]
api_key = '{' + f'"volc_ak": "{req.get("volc_ak", "")}", ' \
f'"volc_sk": "{req.get("volc_sk", "")}", ' \
f'"ep_id": "{endpoint_id}", ' + '}'
# Assemble ark_api_key endpoint_id into api_key
api_key = apikey_json(["ark_api_key", "endpoint_id"])
elif factory == "Tencent Hunyuan":
api_key = '{' + f'"hunyuan_sid": "{req.get("hunyuan_sid", "")}", ' \
f'"hunyuan_sk": "{req.get("hunyuan_sk", "")}"' + '}'
req["api_key"] = api_key
req["api_key"] = apikey_json(["hunyuan_sid", "hunyuan_sk"])
return set_api_key()
elif factory == "Tencent Cloud":
req["api_key"] = apikey_json(["tencent_cloud_sid", "tencent_cloud_sk"])
return set_api_key()
elif factory == "Bedrock":
# For Bedrock, due to its special authentication method
# Assemble bedrock_ak, bedrock_sk, bedrock_region
llm_name = req["llm_name"]
api_key = '{' + f'"bedrock_ak": "{req.get("bedrock_ak", "")}", ' \
f'"bedrock_sk": "{req.get("bedrock_sk", "")}", ' \
f'"bedrock_region": "{req.get("bedrock_region", "")}", ' + '}'
api_key = apikey_json(["bedrock_ak", "bedrock_sk", "bedrock_region"])
elif factory == "LocalAI":
llm_name = req["llm_name"]+"___LocalAI"
api_key = "xxxxxxxxxxxxxxx"
llm_name += "___LocalAI"
elif factory == "HuggingFace":
llm_name += "___HuggingFace"
elif factory == "OpenAI-API-Compatible":
llm_name = req["llm_name"]+"___OpenAI-API"
api_key = req.get("api_key","xxxxxxxxxxxxxxx")
elif factory =="XunFei Spark":
llm_name = req["llm_name"]
api_key = req.get("spark_api_password","xxxxxxxxxxxxxxx")
llm_name += "___OpenAI-API"
elif factory == "VLLM":
llm_name += "___VLLM"
elif factory == "XunFei Spark":
if req["model_type"] == "chat":
api_key = req.get("spark_api_password", "")
elif req["model_type"] == "tts":
api_key = apikey_json(["spark_app_id", "spark_api_secret", "spark_api_key"])
elif factory == "BaiduYiyan":
llm_name = req["llm_name"]
api_key = '{' + f'"yiyan_ak": "{req.get("yiyan_ak", "")}", ' \
f'"yiyan_sk": "{req.get("yiyan_sk", "")}"' + '}'
else:
llm_name = req["llm_name"]
api_key = req.get("api_key","xxxxxxxxxxxxxxx")
api_key = apikey_json(["yiyan_ak", "yiyan_sk"])
elif factory == "Fish Audio":
api_key = apikey_json(["fish_audio_ak", "fish_audio_refid"])
elif factory == "Google Cloud":
api_key = apikey_json(["google_project_id", "google_region", "google_service_account_key"])
elif factory == "Azure-OpenAI":
api_key = apikey_json(["api_key", "api_version"])
llm = {
"tenant_id": current_user.id,
@ -155,94 +199,116 @@ def add_llm():
"model_type": req["model_type"],
"llm_name": llm_name,
"api_base": req.get("api_base", ""),
"api_key": api_key
"api_key": api_key,
"max_tokens": req.get("max_tokens")
}
msg = ""
mdl_nm = llm["llm_name"].split("___")[0]
if llm["model_type"] == LLMType.EMBEDDING.value:
assert factory in EmbeddingModel, f"Embedding model from {factory} is not supported yet."
mdl = EmbeddingModel[factory](
key=llm['api_key'],
model_name=llm["llm_name"],
model_name=mdl_nm,
base_url=llm["api_base"])
try:
arr, tc = mdl.encode(["Test if the api key is available"])
if len(arr[0]) == 0 or tc == 0:
if len(arr[0]) == 0:
raise Exception("Fail")
except Exception as e:
msg += f"\nFail to access embedding model({llm['llm_name']})." + str(e)
msg += f"\nFail to access embedding model({mdl_nm})." + str(e)
elif llm["model_type"] == LLMType.CHAT.value:
assert factory in ChatModel, f"Chat model from {factory} is not supported yet."
mdl = ChatModel[factory](
key=llm['api_key'],
model_name=llm["llm_name"],
model_name=mdl_nm,
base_url=llm["api_base"]
)
try:
m, tc = mdl.chat(None, [{"role": "user", "content": "Hello! How are you doing!"}], {
"temperature": 0.9})
if not tc:
"temperature": 0.9})
if not tc and m.find("**ERROR**:") >= 0:
raise Exception(m)
except Exception as e:
msg += f"\nFail to access model({llm['llm_name']})." + str(
msg += f"\nFail to access model({mdl_nm})." + str(
e)
elif llm["model_type"] == LLMType.RERANK:
mdl = RerankModel[factory](
key=llm["api_key"],
model_name=llm["llm_name"],
base_url=llm["api_base"]
)
assert factory in RerankModel, f"RE-rank model from {factory} is not supported yet."
try:
arr, tc = mdl.similarity("Hello~ Ragflower!", ["Hi, there!"])
if len(arr) == 0 or tc == 0:
mdl = RerankModel[factory](
key=llm["api_key"],
model_name=mdl_nm,
base_url=llm["api_base"]
)
arr, tc = mdl.similarity("Hello~ Ragflower!", ["Hi, there!", "Ohh, my friend!"])
if len(arr) == 0:
raise Exception("Not known.")
except KeyError:
msg += f"{factory} dose not support this model({mdl_nm})"
except Exception as e:
msg += f"\nFail to access model({llm['llm_name']})." + str(
msg += f"\nFail to access model({mdl_nm})." + str(
e)
elif llm["model_type"] == LLMType.IMAGE2TEXT.value:
assert factory in CvModel, f"Image to text model from {factory} is not supported yet."
mdl = CvModel[factory](
key=llm["api_key"],
model_name=llm["llm_name"],
key=llm["api_key"],
model_name=mdl_nm,
base_url=llm["api_base"]
)
try:
img_url = (
"https://upload.wikimedia.org/wikipedia/comm"
"ons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/256"
"0px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
)
res = requests.get(img_url)
if res.status_code == 200:
m, tc = mdl.describe(res.content)
if not tc:
with open(os.path.join(get_project_base_directory(), "web/src/assets/yay.jpg"), "rb") as f:
m, tc = mdl.describe(f.read())
if not m and not tc:
raise Exception(m)
else:
pass
except Exception as e:
msg += f"\nFail to access model({llm['llm_name']})." + str(e)
msg += f"\nFail to access model({mdl_nm})." + str(e)
elif llm["model_type"] == LLMType.TTS:
assert factory in TTSModel, f"TTS model from {factory} is not supported yet."
mdl = TTSModel[factory](
key=llm["api_key"], model_name=mdl_nm, base_url=llm["api_base"]
)
try:
for resp in mdl.tts("Hello~ Ragflower!"):
pass
except RuntimeError as e:
msg += f"\nFail to access model({mdl_nm})." + str(e)
else:
# TODO: check other type of models
pass
if msg:
return get_data_error_result(retmsg=msg)
return get_data_error_result(message=msg)
if not TenantLLMService.filter_update(
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == factory, TenantLLM.llm_name == llm["llm_name"]], llm):
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == factory,
TenantLLM.llm_name == llm["llm_name"]], llm):
TenantLLMService.save(**llm)
return get_json_result(data=True)
@manager.route('/delete_llm', methods=['POST'])
@manager.route('/delete_llm', methods=['POST']) # noqa: F821
@login_required
@validate_request("llm_factory", "llm_name")
def delete_llm():
req = request.json
TenantLLMService.filter_delete(
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == req["llm_factory"], TenantLLM.llm_name == req["llm_name"]])
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == req["llm_factory"],
TenantLLM.llm_name == req["llm_name"]])
return get_json_result(data=True)
@manager.route('/my_llms', methods=['GET'])
@manager.route('/delete_factory', methods=['POST']) # noqa: F821
@login_required
@validate_request("llm_factory")
def delete_factory():
req = request.json
TenantLLMService.filter_delete(
[TenantLLM.tenant_id == current_user.id, TenantLLM.llm_factory == req["llm_factory"]])
return get_json_result(data=True)
@manager.route('/my_llms', methods=['GET']) # noqa: F821
@login_required
def my_llms():
try:
@ -263,28 +329,30 @@ def my_llms():
return server_error_response(e)
@manager.route('/list', methods=['GET'])
@manager.route('/list', methods=['GET']) # noqa: F821
@login_required
def list_app():
self_deployed = ["Youdao", "FastEmbed", "BAAI", "Ollama", "Xinference", "LocalAI", "LM-Studio", "GPUStack"]
weighted = ["Youdao", "FastEmbed", "BAAI"] if settings.LIGHTEN != 0 else []
model_type = request.args.get("model_type")
try:
objs = TenantLLMService.query(tenant_id=current_user.id)
facts = set([o.to_dict()["llm_factory"] for o in objs if o.api_key])
llms = LLMService.get_all()
llms = [m.to_dict()
for m in llms if m.status == StatusEnum.VALID.value]
for m in llms if m.status == StatusEnum.VALID.value and m.fid not in weighted]
for m in llms:
m["available"] = m["fid"] in facts or m["llm_name"].lower() == "flag-embedding" or m["fid"] in ["Youdao","FastEmbed", "BAAI"]
m["available"] = m["fid"] in facts or m["llm_name"].lower() == "flag-embedding" or m["fid"] in self_deployed
llm_set = set([m["llm_name"] for m in llms])
llm_set = set([m["llm_name"] + "@" + m["fid"] for m in llms])
for o in objs:
if not o.api_key:continue
if o.llm_name in llm_set:continue
if o.llm_name + "@" + o.llm_factory in llm_set:
continue
llms.append({"llm_name": o.llm_name, "model_type": o.model_type, "fid": o.llm_factory, "available": True})
res = {}
for m in llms:
if model_type and m["model_type"].find(model_type)<0:
if model_type and m["model_type"].find(model_type) < 0:
continue
if m["fid"] not in res:
res[m["fid"]] = []

39
api/apps/sdk/agent.py Normal file
View File

@ -0,0 +1,39 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from api.db.services.canvas_service import UserCanvasService
from api.utils.api_utils import get_error_data_result, token_required
from api.utils.api_utils import get_result
from flask import request
@manager.route('/agents', methods=['GET']) # noqa: F821
@token_required
def list_agents(tenant_id):
id = request.args.get("id")
title = request.args.get("title")
if id or title:
canvas = UserCanvasService.query(id=id, title=title, user_id=tenant_id)
if not canvas:
return get_error_data_result("The agent doesn't exist.")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 30))
orderby = request.args.get("orderby", "update_time")
if request.args.get("desc") == "False" or request.args.get("desc") == "false":
desc = False
else:
desc = True
canvas = UserCanvasService.get_list(tenant_id,page_number,items_per_page,orderby,desc,id,title)
return get_result(data=canvas)

357
api/apps/sdk/chat.py Normal file
View File

@ -0,0 +1,357 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
from flask import request
from api import settings
from api.db import StatusEnum
from api.db.services.dialog_service import DialogService
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import TenantLLMService
from api.db.services.user_service import TenantService
from api.utils import get_uuid
from api.utils.api_utils import get_error_data_result, token_required, get_result, check_duplicate_ids
@manager.route('/chats', methods=['POST']) # noqa: F821
@token_required
def create(tenant_id):
req = request.json
ids = [i for i in req.get("dataset_ids", []) if i]
for kb_id in ids:
kbs = KnowledgebaseService.accessible(kb_id=kb_id, user_id=tenant_id)
if not kbs:
return get_error_data_result(f"You don't own the dataset {kb_id}")
kbs = KnowledgebaseService.query(id=kb_id)
kb = kbs[0]
if kb.chunk_num == 0:
return get_error_data_result(f"The dataset {kb_id} doesn't own parsed file")
kbs = KnowledgebaseService.get_by_ids(ids) if ids else []
embd_ids = [TenantLLMService.split_model_name_and_factory(kb.embd_id)[0] for kb in kbs] # remove vendor suffix for comparison
embd_count = list(set(embd_ids))
if len(embd_count) > 1:
return get_result(message='Datasets use different embedding models."',
code=settings.RetCode.AUTHENTICATION_ERROR)
req["kb_ids"] = ids
# llm
llm = req.get("llm")
if llm:
if "model_name" in llm:
req["llm_id"] = llm.pop("model_name")
if not TenantLLMService.query(tenant_id=tenant_id, llm_name=req["llm_id"], model_type="chat"):
return get_error_data_result(f"`model_name` {req.get('llm_id')} doesn't exist")
req["llm_setting"] = req.pop("llm")
e, tenant = TenantService.get_by_id(tenant_id)
if not e:
return get_error_data_result(message="Tenant not found!")
# prompt
prompt = req.get("prompt")
key_mapping = {"parameters": "variables",
"prologue": "opener",
"quote": "show_quote",
"system": "prompt",
"rerank_id": "rerank_model",
"vector_similarity_weight": "keywords_similarity_weight"}
key_list = ["similarity_threshold", "vector_similarity_weight", "top_n", "rerank_id","top_k"]
if prompt:
for new_key, old_key in key_mapping.items():
if old_key in prompt:
prompt[new_key] = prompt.pop(old_key)
for key in key_list:
if key in prompt:
req[key] = prompt.pop(key)
req["prompt_config"] = req.pop("prompt")
# init
req["id"] = get_uuid()
req["description"] = req.get("description", "A helpful Assistant")
req["icon"] = req.get("avatar", "")
req["top_n"] = req.get("top_n", 6)
req["top_k"] = req.get("top_k", 1024)
req["rerank_id"] = req.get("rerank_id", "")
if req.get("rerank_id"):
value_rerank_model = ["BAAI/bge-reranker-v2-m3", "maidalun1020/bce-reranker-base_v1"]
if req["rerank_id"] not in value_rerank_model and not TenantLLMService.query(tenant_id=tenant_id,
llm_name=req.get("rerank_id"),
model_type="rerank"):
return get_error_data_result(f"`rerank_model` {req.get('rerank_id')} doesn't exist")
if not req.get("llm_id"):
req["llm_id"] = tenant.llm_id
if not req.get("name"):
return get_error_data_result(message="`name` is required.")
if DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value):
return get_error_data_result(message="Duplicated chat name in creating chat.")
# tenant_id
if req.get("tenant_id"):
return get_error_data_result(message="`tenant_id` must not be provided.")
req["tenant_id"] = tenant_id
# prompt more parameter
default_prompt = {
"system": """You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.
Here is the knowledge base:
{knowledge}
The above is the knowledge base.""",
"prologue": "Hi! I'm your assistant, what can I do for you?",
"parameters": [
{"key": "knowledge", "optional": False}
],
"empty_response": "Sorry! No relevant content was found in the knowledge base!",
"quote": True,
"tts": False,
"refine_multiturn": True
}
key_list_2 = ["system", "prologue", "parameters", "empty_response", "quote", "tts", "refine_multiturn"]
if "prompt_config" not in req:
req['prompt_config'] = {}
for key in key_list_2:
temp = req['prompt_config'].get(key)
if (not temp and key == 'system') or (key not in req["prompt_config"]):
req['prompt_config'][key] = default_prompt[key]
for p in req['prompt_config']["parameters"]:
if p["optional"]:
continue
if req['prompt_config']["system"].find("{%s}" % p["key"]) < 0:
return get_error_data_result(
message="Parameter '{}' is not used".format(p["key"]))
# save
if not DialogService.save(**req):
return get_error_data_result(message="Fail to new a chat!")
# response
e, res = DialogService.get_by_id(req["id"])
if not e:
return get_error_data_result(message="Fail to new a chat!")
res = res.to_json()
renamed_dict = {}
for key, value in res["prompt_config"].items():
new_key = key_mapping.get(key, key)
renamed_dict[new_key] = value
res["prompt"] = renamed_dict
del res["prompt_config"]
new_dict = {"similarity_threshold": res["similarity_threshold"],
"keywords_similarity_weight": 1-res["vector_similarity_weight"],
"top_n": res["top_n"],
"rerank_model": res['rerank_id']}
res["prompt"].update(new_dict)
for key in key_list:
del res[key]
res["llm"] = res.pop("llm_setting")
res["llm"]["model_name"] = res.pop("llm_id")
del res["kb_ids"]
res["dataset_ids"] = req["dataset_ids"]
res["avatar"] = res.pop("icon")
return get_result(data=res)
@manager.route('/chats/<chat_id>', methods=['PUT']) # noqa: F821
@token_required
def update(tenant_id, chat_id):
if not DialogService.query(tenant_id=tenant_id, id=chat_id, status=StatusEnum.VALID.value):
return get_error_data_result(message='You do not own the chat')
req = request.json
ids = req.get("dataset_ids")
if "show_quotation" in req:
req["do_refer"] = req.pop("show_quotation")
if "dataset_ids" in req:
if not ids:
return get_error_data_result("`dataset_ids` can't be empty")
if ids:
for kb_id in ids:
kbs = KnowledgebaseService.accessible(kb_id=kb_id, user_id=tenant_id)
if not kbs:
return get_error_data_result(f"You don't own the dataset {kb_id}")
kbs = KnowledgebaseService.query(id=kb_id)
kb = kbs[0]
if kb.chunk_num == 0:
return get_error_data_result(f"The dataset {kb_id} doesn't own parsed file")
kbs = KnowledgebaseService.get_by_ids(ids)
embd_ids = [TenantLLMService.split_model_name_and_factory(kb.embd_id)[0] for kb in kbs] # remove vendor suffix for comparison
embd_count = list(set(embd_ids))
if len(embd_count) != 1:
return get_result(
message='Datasets use different embedding models."',
code=settings.RetCode.AUTHENTICATION_ERROR)
req["kb_ids"] = ids
llm = req.get("llm")
if llm:
if "model_name" in llm:
req["llm_id"] = llm.pop("model_name")
if not TenantLLMService.query(tenant_id=tenant_id, llm_name=req["llm_id"], model_type="chat"):
return get_error_data_result(f"`model_name` {req.get('llm_id')} doesn't exist")
req["llm_setting"] = req.pop("llm")
e, tenant = TenantService.get_by_id(tenant_id)
if not e:
return get_error_data_result(message="Tenant not found!")
# prompt
prompt = req.get("prompt")
key_mapping = {"parameters": "variables",
"prologue": "opener",
"quote": "show_quote",
"system": "prompt",
"rerank_id": "rerank_model",
"vector_similarity_weight": "keywords_similarity_weight"}
key_list = ["similarity_threshold", "vector_similarity_weight", "top_n", "rerank_id","top_k"]
if prompt:
for new_key, old_key in key_mapping.items():
if old_key in prompt:
prompt[new_key] = prompt.pop(old_key)
for key in key_list:
if key in prompt:
req[key] = prompt.pop(key)
req["prompt_config"] = req.pop("prompt")
e, res = DialogService.get_by_id(chat_id)
res = res.to_json()
if req.get("rerank_id"):
value_rerank_model = ["BAAI/bge-reranker-v2-m3", "maidalun1020/bce-reranker-base_v1"]
if req["rerank_id"] not in value_rerank_model and not TenantLLMService.query(tenant_id=tenant_id,
llm_name=req.get("rerank_id"),
model_type="rerank"):
return get_error_data_result(f"`rerank_model` {req.get('rerank_id')} doesn't exist")
if "name" in req:
if not req.get("name"):
return get_error_data_result(message="`name` cannot be empty.")
if req["name"].lower() != res["name"].lower() \
and len(
DialogService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value)) > 0:
return get_error_data_result(message="Duplicated chat name in updating chat.")
if "prompt_config" in req:
res["prompt_config"].update(req["prompt_config"])
for p in res["prompt_config"]["parameters"]:
if p["optional"]:
continue
if res["prompt_config"]["system"].find("{%s}" % p["key"]) < 0:
return get_error_data_result(message="Parameter '{}' is not used".format(p["key"]))
if "llm_setting" in req:
res["llm_setting"].update(req["llm_setting"])
req["prompt_config"] = res["prompt_config"]
req["llm_setting"] = res["llm_setting"]
# avatar
if "avatar" in req:
req["icon"] = req.pop("avatar")
if "dataset_ids" in req:
req.pop("dataset_ids")
if not DialogService.update_by_id(chat_id, req):
return get_error_data_result(message="Chat not found!")
return get_result()
@manager.route('/chats', methods=['DELETE']) # noqa: F821
@token_required
def delete(tenant_id):
errors = []
success_count = 0
req = request.json
if not req:
ids = None
else:
ids = req.get("ids")
if not ids:
id_list = []
dias = DialogService.query(tenant_id=tenant_id, status=StatusEnum.VALID.value)
for dia in dias:
id_list.append(dia.id)
else:
id_list = ids
unique_id_list, duplicate_messages = check_duplicate_ids(id_list, "assistant")
for id in unique_id_list:
if not DialogService.query(tenant_id=tenant_id, id=id, status=StatusEnum.VALID.value):
errors.append(f"Assistant({id}) not found.")
continue
temp_dict = {"status": StatusEnum.INVALID.value}
DialogService.update_by_id(id, temp_dict)
success_count += 1
if errors:
if success_count > 0:
return get_result(
data={"success_count": success_count, "errors": errors},
message=f"Partially deleted {success_count} chats with {len(errors)} errors"
)
else:
return get_error_data_result(message="; ".join(errors))
if duplicate_messages:
if success_count > 0:
return get_result(
message=f"Partially deleted {success_count} chats with {len(duplicate_messages)} errors",
data={"success_count": success_count, "errors": duplicate_messages}
)
else:
return get_error_data_result(message=";".join(duplicate_messages))
return get_result()
@manager.route('/chats', methods=['GET']) # noqa: F821
@token_required
def list_chat(tenant_id):
id = request.args.get("id")
name = request.args.get("name")
if id or name:
chat = DialogService.query(id=id, name=name, status=StatusEnum.VALID.value, tenant_id=tenant_id)
if not chat:
return get_error_data_result(message="The chat doesn't exist")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 30))
orderby = request.args.get("orderby", "create_time")
if request.args.get("desc") == "False" or request.args.get("desc") == "false":
desc = False
else:
desc = True
chats = DialogService.get_list(tenant_id, page_number, items_per_page, orderby, desc, id, name)
if not chats:
return get_result(data=[])
list_assts = []
key_mapping = {"parameters": "variables",
"prologue": "opener",
"quote": "show_quote",
"system": "prompt",
"rerank_id": "rerank_model",
"vector_similarity_weight": "keywords_similarity_weight",
"do_refer": "show_quotation"}
key_list = ["similarity_threshold", "vector_similarity_weight", "top_n", "rerank_id"]
for res in chats:
renamed_dict = {}
for key, value in res["prompt_config"].items():
new_key = key_mapping.get(key, key)
renamed_dict[new_key] = value
res["prompt"] = renamed_dict
del res["prompt_config"]
new_dict = {"similarity_threshold": res["similarity_threshold"],
"keywords_similarity_weight": 1-res["vector_similarity_weight"],
"top_n": res["top_n"],
"rerank_model": res['rerank_id']}
res["prompt"].update(new_dict)
for key in key_list:
del res[key]
res["llm"] = res.pop("llm_setting")
res["llm"]["model_name"] = res.pop("llm_id")
kb_list = []
for kb_id in res["kb_ids"]:
kb = KnowledgebaseService.query(id=kb_id)
if not kb:
logging.warning(f"The kb {kb_id} does not exist.")
continue
kb_list.append(kb[0].to_json())
del res["kb_ids"]
res["datasets"] = kb_list
res["avatar"] = res.pop("icon")
list_assts.append(res)
return get_result(data=list_assts)

554
api/apps/sdk/dataset.py Normal file
View File

@ -0,0 +1,554 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from flask import request
from api.db import StatusEnum, FileSource
from api.db.db_models import File
from api.db.services.document_service import DocumentService
from api.db.services.file2document_service import File2DocumentService
from api.db.services.file_service import FileService
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import TenantLLMService, LLMService
from api.db.services.user_service import TenantService
from api import settings
from api.utils import get_uuid
from api.utils.api_utils import (
get_result,
token_required,
get_error_data_result,
valid,
get_parser_config, valid_parser_config, dataset_readonly_fields,check_duplicate_ids
)
@manager.route("/datasets", methods=["POST"]) # noqa: F821
@token_required
def create(tenant_id):
"""
Create a new dataset.
---
tags:
- Datasets
security:
- ApiKeyAuth: []
parameters:
- in: header
name: Authorization
type: string
required: true
description: Bearer token for authentication.
- in: body
name: body
description: Dataset creation parameters.
required: true
schema:
type: object
required:
- name
properties:
name:
type: string
description: Name of the dataset.
permission:
type: string
enum: ['me', 'team']
description: Dataset permission.
chunk_method:
type: string
enum: ["naive", "manual", "qa", "table", "paper", "book", "laws",
"presentation", "picture", "one", "email", "tag"
]
description: Chunking method.
parser_config:
type: object
description: Parser configuration.
responses:
200:
description: Successful operation.
schema:
type: object
properties:
data:
type: object
"""
req = request.json
for k in req.keys():
if dataset_readonly_fields(k):
return get_result(code=settings.RetCode.ARGUMENT_ERROR, message=f"'{k}' is readonly.")
e, t = TenantService.get_by_id(tenant_id)
permission = req.get("permission")
chunk_method = req.get("chunk_method")
parser_config = req.get("parser_config")
valid_parser_config(parser_config)
valid_permission = ["me", "team"]
valid_chunk_method = [
"naive",
"manual",
"qa",
"table",
"paper",
"book",
"laws",
"presentation",
"picture",
"one",
"email",
"tag"
]
check_validation = valid(
permission,
valid_permission,
chunk_method,
valid_chunk_method,
)
if check_validation:
return check_validation
req["parser_config"] = get_parser_config(chunk_method, parser_config)
if "tenant_id" in req:
return get_error_data_result(message="`tenant_id` must not be provided")
if "chunk_count" in req or "document_count" in req:
return get_error_data_result(
message="`chunk_count` or `document_count` must not be provided"
)
if "name" not in req:
return get_error_data_result(message="`name` is not empty!")
req["id"] = get_uuid()
req["name"] = req["name"].strip()
if req["name"] == "":
return get_error_data_result(message="`name` is not empty string!")
if len(req["name"]) >= 128:
return get_error_data_result(
message="Dataset name should not be longer than 128 characters."
)
if KnowledgebaseService.query(
name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value
):
return get_error_data_result(
message="Duplicated dataset name in creating dataset."
)
req["tenant_id"] = tenant_id
req["created_by"] = tenant_id
if not req.get("embedding_model"):
req["embedding_model"] = t.embd_id
else:
valid_embedding_models = [
"BAAI/bge-large-zh-v1.5",
"maidalun1020/bce-embedding-base_v1",
]
embd_model = LLMService.query(
llm_name=req["embedding_model"], model_type="embedding"
)
if embd_model:
if req["embedding_model"] not in valid_embedding_models and not TenantLLMService.query(tenant_id=tenant_id,model_type="embedding",llm_name=req.get("embedding_model"),):
return get_error_data_result(f"`embedding_model` {req.get('embedding_model')} doesn't exist")
if not embd_model:
embd_model=TenantLLMService.query(tenant_id=tenant_id,model_type="embedding", llm_name=req.get("embedding_model"))
if not embd_model:
return get_error_data_result(
f"`embedding_model` {req.get('embedding_model')} doesn't exist"
)
key_mapping = {
"chunk_num": "chunk_count",
"doc_num": "document_count",
"parser_id": "chunk_method",
"embd_id": "embedding_model",
}
mapped_keys = {
new_key: req[old_key]
for new_key, old_key in key_mapping.items()
if old_key in req
}
req.update(mapped_keys)
flds = list(req.keys())
for f in flds:
if req[f] == "" and f in ["permission", "parser_id", "chunk_method"]:
del req[f]
if not KnowledgebaseService.save(**req):
return get_error_data_result(message="Create dataset error.(Database error)")
renamed_data = {}
e, k = KnowledgebaseService.get_by_id(req["id"])
for key, value in k.to_dict().items():
new_key = key_mapping.get(key, key)
renamed_data[new_key] = value
return get_result(data=renamed_data)
@manager.route("/datasets", methods=["DELETE"]) # noqa: F821
@token_required
def delete(tenant_id):
"""
Delete datasets.
---
tags:
- Datasets
security:
- ApiKeyAuth: []
parameters:
- in: header
name: Authorization
type: string
required: true
description: Bearer token for authentication.
- in: body
name: body
description: Dataset deletion parameters.
required: true
schema:
type: object
properties:
ids:
type: array
items:
type: string
description: List of dataset IDs to delete.
responses:
200:
description: Successful operation.
schema:
type: object
"""
errors = []
success_count = 0
req = request.json
if not req:
ids = None
else:
ids = req.get("ids")
if not ids:
id_list = []
kbs = KnowledgebaseService.query(tenant_id=tenant_id)
for kb in kbs:
id_list.append(kb.id)
else:
id_list = ids
unique_id_list, duplicate_messages = check_duplicate_ids(id_list, "dataset")
id_list = unique_id_list
for id in id_list:
kbs = KnowledgebaseService.query(id=id, tenant_id=tenant_id)
if not kbs:
errors.append(f"You don't own the dataset {id}")
continue
for doc in DocumentService.query(kb_id=id):
if not DocumentService.remove_document(doc, tenant_id):
errors.append(f"Remove document error for dataset {id}")
continue
f2d = File2DocumentService.get_by_document_id(doc.id)
FileService.filter_delete(
[
File.source_type == FileSource.KNOWLEDGEBASE,
File.id == f2d[0].file_id,
]
)
File2DocumentService.delete_by_document_id(doc.id)
FileService.filter_delete(
[File.source_type == FileSource.KNOWLEDGEBASE, File.type == "folder", File.name == kbs[0].name])
if not KnowledgebaseService.delete_by_id(id):
errors.append(f"Delete dataset error for {id}")
continue
success_count += 1
if errors:
if success_count > 0:
return get_result(
data={"success_count": success_count, "errors": errors},
message=f"Partially deleted {success_count} datasets with {len(errors)} errors"
)
else:
return get_error_data_result(message="; ".join(errors))
if duplicate_messages:
if success_count > 0:
return get_result(message=f"Partially deleted {success_count} datasets with {len(duplicate_messages)} errors", data={"success_count": success_count, "errors": duplicate_messages},)
else:
return get_error_data_result(message=";".join(duplicate_messages))
return get_result(code=settings.RetCode.SUCCESS)
@manager.route("/datasets/<dataset_id>", methods=["PUT"]) # noqa: F821
@token_required
def update(tenant_id, dataset_id):
"""
Update a dataset.
---
tags:
- Datasets
security:
- ApiKeyAuth: []
parameters:
- in: path
name: dataset_id
type: string
required: true
description: ID of the dataset to update.
- in: header
name: Authorization
type: string
required: true
description: Bearer token for authentication.
- in: body
name: body
description: Dataset update parameters.
required: true
schema:
type: object
properties:
name:
type: string
description: New name of the dataset.
permission:
type: string
enum: ['me', 'team']
description: Updated permission.
chunk_method:
type: string
enum: ["naive", "manual", "qa", "table", "paper", "book", "laws",
"presentation", "picture", "one", "email", "tag"
]
description: Updated chunking method.
parser_config:
type: object
description: Updated parser configuration.
responses:
200:
description: Successful operation.
schema:
type: object
"""
if not KnowledgebaseService.query(id=dataset_id, tenant_id=tenant_id):
return get_error_data_result(message="You don't own the dataset")
req = request.json
for k in req.keys():
if dataset_readonly_fields(k):
return get_result(code=settings.RetCode.ARGUMENT_ERROR, message=f"'{k}' is readonly.")
e, t = TenantService.get_by_id(tenant_id)
invalid_keys = {"id", "embd_id", "chunk_num", "doc_num", "parser_id", "create_date", "create_time", "created_by", "status","token_num","update_date","update_time"}
if any(key in req for key in invalid_keys):
return get_error_data_result(message="The input parameters are invalid.")
permission = req.get("permission")
chunk_method = req.get("chunk_method")
parser_config = req.get("parser_config")
valid_parser_config(parser_config)
valid_permission = ["me", "team"]
valid_chunk_method = [
"naive",
"manual",
"qa",
"table",
"paper",
"book",
"laws",
"presentation",
"picture",
"one",
"email",
"tag"
]
check_validation = valid(
permission,
valid_permission,
chunk_method,
valid_chunk_method,
)
if check_validation:
return check_validation
if "tenant_id" in req:
if req["tenant_id"] != tenant_id:
return get_error_data_result(message="Can't change `tenant_id`.")
e, kb = KnowledgebaseService.get_by_id(dataset_id)
if "parser_config" in req:
temp_dict = kb.parser_config
temp_dict.update(req["parser_config"])
req["parser_config"] = temp_dict
if "chunk_count" in req:
if req["chunk_count"] != kb.chunk_num:
return get_error_data_result(message="Can't change `chunk_count`.")
req.pop("chunk_count")
if "document_count" in req:
if req["document_count"] != kb.doc_num:
return get_error_data_result(message="Can't change `document_count`.")
req.pop("document_count")
if req.get("chunk_method"):
if kb.chunk_num != 0 and req["chunk_method"] != kb.parser_id:
return get_error_data_result(
message="If `chunk_count` is not 0, `chunk_method` is not changeable."
)
req["parser_id"] = req.pop("chunk_method")
if req["parser_id"] != kb.parser_id:
if not req.get("parser_config"):
req["parser_config"] = get_parser_config(chunk_method, parser_config)
if "embedding_model" in req:
if kb.chunk_num != 0 and req["embedding_model"] != kb.embd_id:
return get_error_data_result(
message="If `chunk_count` is not 0, `embedding_model` is not changeable."
)
if not req.get("embedding_model"):
return get_error_data_result("`embedding_model` can't be empty")
valid_embedding_models = [
"BAAI/bge-large-zh-v1.5",
"BAAI/bge-base-en-v1.5",
"BAAI/bge-large-en-v1.5",
"BAAI/bge-small-en-v1.5",
"BAAI/bge-small-zh-v1.5",
"jinaai/jina-embeddings-v2-base-en",
"jinaai/jina-embeddings-v2-small-en",
"nomic-ai/nomic-embed-text-v1.5",
"sentence-transformers/all-MiniLM-L6-v2",
"text-embedding-v2",
"text-embedding-v3",
"maidalun1020/bce-embedding-base_v1",
]
embd_model = LLMService.query(
llm_name=req["embedding_model"], model_type="embedding"
)
if embd_model:
if req["embedding_model"] not in valid_embedding_models and not TenantLLMService.query(tenant_id=tenant_id,model_type="embedding",llm_name=req.get("embedding_model"),):
return get_error_data_result(f"`embedding_model` {req.get('embedding_model')} doesn't exist")
if not embd_model:
embd_model=TenantLLMService.query(tenant_id=tenant_id,model_type="embedding", llm_name=req.get("embedding_model"))
if not embd_model:
return get_error_data_result(
f"`embedding_model` {req.get('embedding_model')} doesn't exist"
)
req["embd_id"] = req.pop("embedding_model")
if "name" in req:
req["name"] = req["name"].strip()
if len(req["name"]) >= 128:
return get_error_data_result(
message="Dataset name should not be longer than 128 characters."
)
if (
req["name"].lower() != kb.name.lower()
and len(
KnowledgebaseService.query(
name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value
)
)
> 0
):
return get_error_data_result(
message="Duplicated dataset name in updating dataset."
)
flds = list(req.keys())
for f in flds:
if req[f] == "" and f in ["permission", "parser_id", "chunk_method"]:
del req[f]
if not KnowledgebaseService.update_by_id(kb.id, req):
return get_error_data_result(message="Update dataset error.(Database error)")
return get_result(code=settings.RetCode.SUCCESS)
@manager.route("/datasets", methods=["GET"]) # noqa: F821
@token_required
def list_datasets(tenant_id):
"""
List datasets.
---
tags:
- Datasets
security:
- ApiKeyAuth: []
parameters:
- in: query
name: id
type: string
required: false
description: Dataset ID to filter.
- in: query
name: name
type: string
required: false
description: Dataset name to filter.
- in: query
name: page
type: integer
required: false
default: 1
description: Page number.
- in: query
name: page_size
type: integer
required: false
default: 1024
description: Number of items per page.
- in: query
name: orderby
type: string
required: false
default: "create_time"
description: Field to order by.
- in: query
name: desc
type: boolean
required: false
default: true
description: Order in descending.
- in: header
name: Authorization
type: string
required: true
description: Bearer token for authentication.
responses:
200:
description: Successful operation.
schema:
type: array
items:
type: object
"""
id = request.args.get("id")
name = request.args.get("name")
if id:
kbs = KnowledgebaseService.get_kb_by_id(id,tenant_id)
if not kbs:
return get_error_data_result(f"You don't own the dataset {id}")
if name:
kbs = KnowledgebaseService.get_kb_by_name(name,tenant_id)
if not kbs:
return get_error_data_result(f"You don't own the dataset {name}")
page_number = int(request.args.get("page", 1))
items_per_page = int(request.args.get("page_size", 30))
orderby = request.args.get("orderby", "create_time")
if request.args.get("desc", "false").lower() not in ["true", "false"]:
return get_error_data_result("desc should be true or false")
if request.args.get("desc", "true").lower() == "false":
desc = False
else:
desc = True
tenants = TenantService.get_joined_tenants_by_user_id(tenant_id)
kbs = KnowledgebaseService.get_list(
[m["tenant_id"] for m in tenants],
tenant_id,
page_number,
items_per_page,
orderby,
desc,
id,
name,
)
renamed_list = []
for kb in kbs:
key_mapping = {
"chunk_num": "chunk_count",
"doc_num": "document_count",
"parser_id": "chunk_method",
"embd_id": "embedding_model",
}
renamed_data = {}
for key, value in kb.items():
new_key = key_mapping.get(key, key)
renamed_data[new_key] = value
renamed_list.append(renamed_data)
return get_result(data=renamed_list)

View File

@ -0,0 +1,88 @@
#
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from flask import request, jsonify
from api.db import LLMType
from api.db.services.knowledgebase_service import KnowledgebaseService
from api.db.services.llm_service import LLMBundle
from api import settings
from api.utils.api_utils import validate_request, build_error_result, apikey_required
from rag.app.tag import label_question
@manager.route('/dify/retrieval', methods=['POST']) # noqa: F821
@apikey_required
@validate_request("knowledge_id", "query")
def retrieval(tenant_id):
req = request.json
question = req["query"]
kb_id = req["knowledge_id"]
use_kg = req.get("use_kg", False)
retrieval_setting = req.get("retrieval_setting", {})
similarity_threshold = float(retrieval_setting.get("score_threshold", 0.0))
top = int(retrieval_setting.get("top_k", 1024))
try:
e, kb = KnowledgebaseService.get_by_id(kb_id)
if not e:
return build_error_result(message="Knowledgebase not found!", code=settings.RetCode.NOT_FOUND)
if kb.tenant_id != tenant_id:
return build_error_result(message="Knowledgebase not found!", code=settings.RetCode.NOT_FOUND)
embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)
ranks = settings.retrievaler.retrieval(
question,
embd_mdl,
kb.tenant_id,
[kb_id],
page=1,
page_size=top,
similarity_threshold=similarity_threshold,
vector_similarity_weight=0.3,
top=top,
rank_feature=label_question(question, [kb])
)
if use_kg:
ck = settings.kg_retrievaler.retrieval(question,
[tenant_id],
[kb_id],
embd_mdl,
LLMBundle(kb.tenant_id, LLMType.CHAT))
if ck["content_with_weight"]:
ranks["chunks"].insert(0, ck)
records = []
for c in ranks["chunks"]:
c.pop("vector", None)
records.append({
"content": c["content_with_weight"],
"score": c["similarity"],
"title": c["docnm_kwd"],
"metadata": {}
})
return jsonify({"records": records})
except Exception as e:
if str(e).find("not_found") > 0:
return build_error_result(
message='No chunk found! Check the chunk status please!',
code=settings.RetCode.NOT_FOUND
)
return build_error_result(message=str(e), code=settings.RetCode.SERVER_ERROR)

1475
api/apps/sdk/doc.py Normal file

File diff suppressed because it is too large Load Diff

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