Compare commits

..

No commits in common. "ae462bc9dcc8a22b8d69ad3db6dcb53ad6064f8e" and "84df2adf562abc7ab3452963e5997b3a043f13a1" have entirely different histories.

13 changed files with 57 additions and 67 deletions

2
.gitignore vendored
View File

@ -19,7 +19,7 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information # MSVC Windows builds of rustc generate these, which store debugging information
*.pdb *.pdb
.trie *.trie
.idea/ .idea/
.vscode/ .vscode/

View File

@ -70,34 +70,6 @@ deploy:
**回答:** Ragflow原生解析器心跳触发的问题不影响正常使用可忽略官方回答可参考https://github.com/infiniflow/ragflow/issues/6700 **回答:** Ragflow原生解析器心跳触发的问题不影响正常使用可忽略官方回答可参考https://github.com/infiniflow/ragflow/issues/6700
## 问题 11为什么添加ollama时无法联通
**回答:** ollama需要预先设置为对所有网络接口开放
修改配置文件:
```bash
vim /etc/systemd/system/ollama.service
```
[Service] 下添加:
```bash
Environment="OLLAMA_HOST=0.0.0.0"
```
重新载入配置文件重启ollama。
```bash
systemctl daemon-reload
systemctl restart ollama
```
## 问题 12在后台知识库连接测试中显示 text-embedding-v3无法连通
**回答:** 出现此情况原因是使用 ragflow 创建的初始用户(创建时间最早的用户),默认自带了通义千问的模型配置,可登陆此用户,在模型管理中移除通义千问的模型配置,并添加新的嵌入模型配置,后台会自动读取最新添加的模型配置信息。
嵌入模型仅支持 bge-m3 模型联网API仅支持硅基流动平台可免费调用该嵌入模型https://cloud.siliconflow.cn/i/bjDoFhPf
--- ---

View File

@ -159,6 +159,24 @@ def delete_document(doc_id):
return error_response(str(e)) return error_response(str(e))
@knowledgebase_bp.route("/documents/<doc_id>/parse", methods=["POST"])
def parse_document(doc_id):
"""开始解析文档"""
# 处理 OPTIONS 预检请求
if request.method == "OPTIONS":
response = success_response({})
# 添加 CORS 相关头
response.headers.add("Access-Control-Allow-Methods", "POST")
response.headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization")
return response
try:
result = KnowledgebaseService.async_parse_document(doc_id)
return success_response(data=result)
except Exception as e:
return error_response(str(e), code=500)
@knowledgebase_bp.route("/documents/<doc_id>/parse/progress", methods=["GET"]) @knowledgebase_bp.route("/documents/<doc_id>/parse/progress", methods=["GET"])
def get_parse_progress(doc_id): def get_parse_progress(doc_id):
"""获取文档解析进度""" """获取文档解析进度"""
@ -224,8 +242,8 @@ def set_system_embedding_config_route():
@knowledgebase_bp.route("/documents/<doc_id>/parse", methods=["POST"]) @knowledgebase_bp.route("/documents/<doc_id>/parse", methods=["POST"])
def parse_document(doc_id): def parse_document_async(doc_id): # 函数名改为 async 以区分
"""开始解析文档""" """开始异步解析单个文档"""
if request.method == "OPTIONS": if request.method == "OPTIONS":
response = success_response({}) response = success_response({})
response.headers.add("Access-Control-Allow-Methods", "POST") response.headers.add("Access-Control-Allow-Methods", "POST")
@ -233,7 +251,7 @@ def parse_document(doc_id):
return response return response
try: try:
result = KnowledgebaseService.parse_document(doc_id) result = KnowledgebaseService.parse_document(doc_id) # 调用同步版本
if result.get("success"): if result.get("success"):
return success_response(data={"message": f"文档 {doc_id} 同步解析完成。", "details": result}) return success_response(data={"message": f"文档 {doc_id} 同步解析完成。", "details": result})
else: else:

View File

@ -1,9 +1,7 @@
from typing import Any, Dict, Type, TypeVar
from peewee import Model from peewee import Model
from typing import Type, TypeVar, Dict, Any
T = TypeVar("T", bound=Model) T = TypeVar('T', bound=Model)
class BaseService: class BaseService:
model: Type[T] model: Type[T]
@ -22,4 +20,6 @@ class BaseService:
@classmethod @classmethod
def query(cls, **kwargs) -> list[T]: def query(cls, **kwargs) -> list[T]:
return list(cls.model.select().where(*[getattr(cls.model, k) == v for k, v in kwargs.items()])) return list(cls.model.select().where(*[
getattr(cls.model, k) == v for k, v in kwargs.items()
]))

View File

@ -1,15 +1,16 @@
from peewee import * from peewee import *
from .base_service import BaseService from .base_service import BaseService
from .models import File2Document from .models import File2Document
class File2DocumentService(BaseService): class File2DocumentService(BaseService):
model = File2Document model = File2Document
@classmethod @classmethod
def create_mapping(cls, file_id: str, document_id: str) -> File2Document: def create_mapping(cls, file_id: str, document_id: str) -> File2Document:
return cls.insert({"file_id": file_id, "document_id": document_id}) return cls.insert({
'file_id': file_id,
'document_id': document_id
})
@classmethod @classmethod
def get_by_document_id(cls, document_id: str) -> list[File2Document]: def get_by_document_id(cls, document_id: str) -> list[File2Document]:

View File

@ -1,4 +1,3 @@
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

View File

@ -484,8 +484,11 @@ def perform_parse(doc_id, doc_info, file_info, embedding_config, kb_info):
# 4. 更新文本块的图像信息 # 4. 更新文本块的图像信息
if image_info_list and chunk_ids_list: if image_info_list and chunk_ids_list:
conn = None
cursor = None
try: try:
conn = get_db_connection()
cursor = conn.cursor()
# 为每个文本块找到最近的图片 # 为每个文本块找到最近的图片
for i, chunk_id in enumerate(chunk_ids_list): for i, chunk_id in enumerate(chunk_ids_list):
@ -513,7 +516,11 @@ def perform_parse(doc_id, doc_info, file_info, embedding_config, kb_info):
except Exception as e: except Exception as e:
logger.error(f"[Parser-ERROR] 更新文本块图片关联失败: {e}") logger.error(f"[Parser-ERROR] 更新文本块图片关联失败: {e}")
raise Exception(f"[Parser-ERROR] 更新文本块图片关联失败: {e}") raise Exception(f"[Parser-ERROR] 更新文本块图片关联失败: {e}")
finally:
if cursor:
cursor.close()
if conn:
conn.close()
# 5. 更新最终状态 # 5. 更新最终状态
process_duration = time.time() - start_time process_duration = time.time() - start_time

View File

@ -711,19 +711,12 @@ class KnowledgebaseService:
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
# 先检查文档是否存在 # 先检查文档是否存在
# check_query = """
# SELECT
# d.kb_id,
# kb.created_by AS tenant_id -- 获取 tenant_id (knowledgebase的创建者)
# FROM document d
# JOIN knowledgebase kb ON d.kb_id = kb.id -- JOIN knowledgebase 表
# WHERE d.id = %s
# """
check_query = """ check_query = """
SELECT SELECT
d.kb_id, d.kb_id,
d.created_by AS tenant_id kb.created_by AS tenant_id -- 获取 tenant_id (knowledgebase的创建者)
FROM document d FROM document d
JOIN knowledgebase kb ON d.kb_id = kb.id -- JOIN knowledgebase
WHERE d.id = %s WHERE d.id = %s
""" """
cursor.execute(check_query, (doc_id,)) cursor.execute(check_query, (doc_id,))
@ -1048,7 +1041,7 @@ class KnowledgebaseService:
SELECT llm_name, api_key, api_base SELECT llm_name, api_key, api_base
FROM tenant_llm FROM tenant_llm
WHERE tenant_id = %s AND model_type = 'embedding' WHERE tenant_id = %s AND model_type = 'embedding'
ORDER BY create_time DESC ORDER BY create_time DESC # 如果一个用户可能有多个embedding配置取最早的
LIMIT 1 LIMIT 1
""" """
cursor.execute(query_embedding_config, (earliest_user_id,)) cursor.execute(query_embedding_config, (earliest_user_id,))

View File

@ -11,7 +11,7 @@ export function createTableDataApi(data: Tables.CreateOrUpdateTableRequestData)
} }
/** 删 */ /** 删 */
export function deleteTableDataApi(id: string) { export function deleteTableDataApi(id: number) {
return request({ return request({
url: `api/v1/users/${id}`, url: `api/v1/users/${id}`,
method: "delete" method: "delete"
@ -42,7 +42,7 @@ export function getTableDataApi(params: Tables.TableRequestData) {
* @param password * @param password
* @returns BaseResponse * @returns BaseResponse
*/ */
export function resetPasswordApi(userId: string, password: string) { export function resetPasswordApi(userId: number, password: string) {
return request({ return request({
url: `api/v1/users/${userId}/reset-password`, url: `api/v1/users/${userId}/reset-password`,
method: "put", method: "put",

View File

@ -1,5 +1,5 @@
export interface CreateOrUpdateTableRequestData { export interface CreateOrUpdateTableRequestData {
id?: string id?: number
username: string username: string
email?: string email?: string
password?: string password?: string
@ -21,7 +21,7 @@ export interface TableRequestData {
} }
export interface TableData { export interface TableData {
id: string id: number
username: string username: string
email: string email: string
createTime: string createTime: string

View File

@ -39,7 +39,7 @@ const formRules: FormRules<CreateOrUpdateTableRequestData> = {
// #region // #region
const resetPasswordDialogVisible = ref<boolean>(false) const resetPasswordDialogVisible = ref<boolean>(false)
const resetPasswordFormRef = ref<FormInstance | null>(null) const resetPasswordFormRef = ref<FormInstance | null>(null)
const currentUserId = ref<string | undefined>(undefined) // ID const currentUserId = ref<number | undefined>(undefined) // ID
const resetPasswordFormData = reactive({ const resetPasswordFormData = reactive({
password: "" password: ""
}) })

Binary file not shown.