KevinHuSh commited on
Commit
58d441f
·
1 Parent(s): 7943d52

refine error response, add set api-key MD (#178)

Browse files
api/apps/conversation_app.py CHANGED
@@ -253,6 +253,8 @@ def chat(dialog, messages, **kwargs):
253
  for c in kbinfos["chunks"]:
254
  if c.get("vector"):
255
  del c["vector"]
 
 
256
  return {"answer": answer, "reference": kbinfos}
257
 
258
 
 
253
  for c in kbinfos["chunks"]:
254
  if c.get("vector"):
255
  del c["vector"]
256
+ if answer.lower().find("invalid key") >= 0 or answer.lower().find("invalid api")>=0:
257
+ answer += " Please set LLM API-Key in 'User Setting -> Model Providers -> API-Key'"
258
  return {"answer": answer, "reference": kbinfos}
259
 
260
 
api/apps/kb_app.py CHANGED
@@ -13,10 +13,12 @@
13
  # See the License for the specific language governing permissions and
14
  # limitations under the License.
15
  #
 
16
  from flask import request
17
  from flask_login import login_required, current_user
18
 
19
  from api.db.services import duplicate_name
 
20
  from api.db.services.user_service import TenantService, UserTenantService
21
  from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
22
  from api.utils import get_uuid, get_format_time
@@ -25,6 +27,8 @@ from api.db.services.knowledgebase_service import KnowledgebaseService
25
  from api.db.db_models import Knowledgebase
26
  from api.settings import stat_logger, RetCode
27
  from api.utils.api_utils import get_json_result
 
 
28
 
29
 
30
  @manager.route('/create', methods=['post'])
@@ -125,11 +129,22 @@ def list():
125
  def rm():
126
  req = request.json
127
  try:
128
- if not KnowledgebaseService.query(
129
- created_by=current_user.id, id=req["kb_id"]):
 
130
  return get_json_result(
131
  data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
132
 
 
 
 
 
 
 
 
 
 
 
133
  if not KnowledgebaseService.update_by_id(
134
  req["kb_id"], {"status": StatusEnum.INVALID.value}):
135
  return get_data_error_result(
 
13
  # See the License for the specific language governing permissions and
14
  # limitations under the License.
15
  #
16
+ from elasticsearch_dsl import Q
17
  from flask import request
18
  from flask_login import login_required, current_user
19
 
20
  from api.db.services import duplicate_name
21
+ from api.db.services.document_service import DocumentService
22
  from api.db.services.user_service import TenantService, UserTenantService
23
  from api.utils.api_utils import server_error_response, get_data_error_result, validate_request
24
  from api.utils import get_uuid, get_format_time
 
27
  from api.db.db_models import Knowledgebase
28
  from api.settings import stat_logger, RetCode
29
  from api.utils.api_utils import get_json_result
30
+ from rag.nlp import search
31
+ from rag.utils import ELASTICSEARCH
32
 
33
 
34
  @manager.route('/create', methods=['post'])
 
129
  def rm():
130
  req = request.json
131
  try:
132
+ kbs = KnowledgebaseService.query(
133
+ created_by=current_user.id, id=req["kb_id"])
134
+ if not kbs:
135
  return get_json_result(
136
  data=False, retmsg=f'Only owner of knowledgebase authorized for this operation.', retcode=RetCode.OPERATING_ERROR)
137
 
138
+ for doc in DocumentService.query(kb_id=req["kb_id"]):
139
+ ELASTICSEARCH.deleteByQuery(
140
+ Q("match", doc_id=doc.id), idxnm=search.index_name(kbs[0].tenant_id))
141
+
142
+ DocumentService.increment_chunk_num(
143
+ doc.id, doc.kb_id, doc.token_num * -1, doc.chunk_num * -1, 0)
144
+ if not DocumentService.delete(doc):
145
+ return get_data_error_result(
146
+ retmsg="Database error (Document removal)!")
147
+
148
  if not KnowledgebaseService.update_by_id(
149
  req["kb_id"], {"status": StatusEnum.INVALID.value}):
150
  return get_data_error_result(
api/db/services/knowledgebase_service.py CHANGED
@@ -62,7 +62,7 @@ class KnowledgebaseService(CommonService):
62
  if not kbs:
63
  return
64
  d = kbs[0].to_dict()
65
- d["embd_id"] = kbs[0].tenant.embd_id
66
  return d
67
 
68
  @classmethod
 
62
  if not kbs:
63
  return
64
  d = kbs[0].to_dict()
65
+ #d["embd_id"] = kbs[0].tenant.embd_id
66
  return d
67
 
68
  @classmethod
api/utils/api_utils.py CHANGED
@@ -149,6 +149,9 @@ def server_error_response(e):
149
  if len(e.args) > 1:
150
  return get_json_result(
151
  retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e.args[0]), data=e.args[1])
 
 
 
152
  return get_json_result(retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e))
153
 
154
 
 
149
  if len(e.args) > 1:
150
  return get_json_result(
151
  retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e.args[0]), data=e.args[1])
152
+ if repr(e).find("index_not_found_exception") >=0:
153
+ return get_json_result(retcode=RetCode.EXCEPTION_ERROR, retmsg="No chunk found, please upload file and parse it.")
154
+
155
  return get_json_result(retcode=RetCode.EXCEPTION_ERROR, retmsg=repr(e))
156
 
157
 
docker/docker-compose-CN.yml ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '2.2'
2
+ services:
3
+ es01:
4
+ container_name: ragflow-es-01
5
+ image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
6
+ volumes:
7
+ - esdata01:/usr/share/elasticsearch/data
8
+ ports:
9
+ - ${ES_PORT}:9200
10
+ environment:
11
+ - node.name=es01
12
+ - cluster.name=${CLUSTER_NAME}
13
+ - cluster.initial_master_nodes=es01
14
+ - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
15
+ - bootstrap.memory_lock=false
16
+ - xpack.security.enabled=false
17
+ - TZ=${TIMEZONE}
18
+ mem_limit: ${MEM_LIMIT}
19
+ ulimits:
20
+ memlock:
21
+ soft: -1
22
+ hard: -1
23
+ healthcheck:
24
+ test: ["CMD-SHELL", "curl http://localhost:9200"]
25
+ interval: 10s
26
+ timeout: 10s
27
+ retries: 120
28
+ networks:
29
+ - ragflow
30
+ restart: always
31
+
32
+ kibana:
33
+ depends_on:
34
+ es01:
35
+ condition: service_healthy
36
+ image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
37
+ container_name: ragflow-kibana
38
+ volumes:
39
+ - kibanadata:/usr/share/kibana/data
40
+ ports:
41
+ - ${KIBANA_PORT}:5601
42
+ environment:
43
+ - SERVERNAME=kibana
44
+ - ELASTICSEARCH_HOSTS=http://es01:9200
45
+ - TZ=${TIMEZONE}
46
+ mem_limit: ${MEM_LIMIT}
47
+ networks:
48
+ - ragflow
49
+
50
+ mysql:
51
+ image: mysql:5.7.18
52
+ container_name: ragflow-mysql
53
+ environment:
54
+ - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
55
+ - TZ=${TIMEZONE}
56
+ command:
57
+ --max_connections=1000
58
+ --character-set-server=utf8mb4
59
+ --collation-server=utf8mb4_general_ci
60
+ --default-authentication-plugin=mysql_native_password
61
+ --tls_version="TLSv1.2,TLSv1.3"
62
+ --init-file /data/application/init.sql
63
+ ports:
64
+ - ${MYSQL_PORT}:3306
65
+ volumes:
66
+ - mysql_data:/var/lib/mysql
67
+ - ./init.sql:/data/application/init.sql
68
+ networks:
69
+ - ragflow
70
+ healthcheck:
71
+ test: ["CMD", "mysqladmin" ,"ping", "-uroot", "-p${MYSQL_PASSWORD}"]
72
+ interval: 10s
73
+ timeout: 10s
74
+ retries: 3
75
+ restart: always
76
+
77
+
78
+ minio:
79
+ image: quay.io/minio/minio:RELEASE.2023-12-20T01-00-02Z
80
+ container_name: ragflow-minio
81
+ command: server --console-address ":9001" /data
82
+ ports:
83
+ - 9000:9000
84
+ - 9001:9001
85
+ environment:
86
+ - MINIO_ROOT_USER=${MINIO_USER}
87
+ - MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
88
+ - TZ=${TIMEZONE}
89
+ volumes:
90
+ - minio_data:/data
91
+ networks:
92
+ - ragflow
93
+ restart: always
94
+
95
+
96
+ ragflow:
97
+ depends_on:
98
+ mysql:
99
+ condition: service_healthy
100
+ es01:
101
+ condition: service_healthy
102
+ image: swr.cn-north-4.myhuaweicloud.com/infiniflow/ragflow:v1.0
103
+ container_name: ragflow-server
104
+ ports:
105
+ - ${SVR_HTTP_PORT}:9380
106
+ - 80:80
107
+ - 443:443
108
+ volumes:
109
+ - ./service_conf.yaml:/ragflow/conf/service_conf.yaml
110
+ - ./ragflow-logs:/ragflow/logs
111
+ - ./nginx/ragflow.conf:/etc/nginx/conf.d/ragflow.conf
112
+ - ./nginx/proxy.conf:/etc/nginx/proxy.conf
113
+ - ./nginx/nginx.conf:/etc/nginx/nginx.conf
114
+ environment:
115
+ - TZ=${TIMEZONE}
116
+ networks:
117
+ - ragflow
118
+ restart: always
119
+
120
+
121
+ volumes:
122
+ esdata01:
123
+ driver: local
124
+ kibanadata:
125
+ driver: local
126
+ mysql_data:
127
+ driver: local
128
+ minio_data:
129
+ driver: local
130
+
131
+ networks:
132
+ ragflow:
133
+ driver: bridge
docs/llm_api_key_setup.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ ## Set Before Starting The System
3
+
4
+ In **user_default_llm** of [service_conf.yaml](./docker/service_conf.yaml), you need to specify LLM factory and your own _API_KEY_.
5
+ RagFlow supports the flowing LLM factory, and with more coming in the pipeline:
6
+
7
+ > [OpenAI](https://platform.openai.com/login?launch), [Tongyi-Qianwen](https://dashscope.console.aliyun.com/model),
8
+ > [ZHIPU-AI](https://open.bigmodel.cn/), [Moonshot](https://platform.moonshot.cn/docs/docs)
9
+
10
+ After sign in these LLM suppliers, create your own API-Key, they all have a certain amount of free quota.
11
+
12
+ ## After Starting The System
13
+
14
+ You can also set API-Key in **User Setting** as following:
15
+
16
+ <div align="center" style="margin-top:20px;margin-bottom:20px;">
17
+ <img src="https://github.com/infiniflow/ragflow/assets/12318111/e4e4066c-e964-45ff-bd56-c3fc7fb18bd3" width="1000"/>
18
+ </div>
19
+
rag/llm/chat_model.py CHANGED
@@ -156,7 +156,7 @@ class LocalLLM(Base):
156
 
157
  return do_rpc
158
 
159
- def __init__(self, **kwargs):
160
  self.client = LocalLLM.RPCProxy("127.0.0.1", 7860)
161
 
162
  def chat(self, system, history, gen_conf):
 
156
 
157
  return do_rpc
158
 
159
+ def __init__(self, *args, **kwargs):
160
  self.client = LocalLLM.RPCProxy("127.0.0.1", 7860)
161
 
162
  def chat(self, system, history, gen_conf):
rag/llm/rpc_server.py CHANGED
@@ -7,6 +7,23 @@ from threading import Thread
7
  from transformers import AutoModelForCausalLM, AutoTokenizer
8
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  class RPCHandler:
11
  def __init__(self):
12
  self._functions = {}
@@ -49,6 +66,7 @@ def chat(messages, gen_conf):
49
  global tokenizer
50
  model = Model()
51
  try:
 
52
  conf = {
53
  "max_new_tokens": int(
54
  gen_conf.get(
 
7
  from transformers import AutoModelForCausalLM, AutoTokenizer
8
 
9
 
10
+ def torch_gc():
11
+ try:
12
+ import torch
13
+ if torch.cuda.is_available():
14
+ # with torch.cuda.device(DEVICE):
15
+ torch.cuda.empty_cache()
16
+ torch.cuda.ipc_collect()
17
+ elif torch.backends.mps.is_available():
18
+ try:
19
+ from torch.mps import empty_cache
20
+ empty_cache()
21
+ except Exception as e:
22
+ pass
23
+ except Exception:
24
+ pass
25
+
26
+
27
  class RPCHandler:
28
  def __init__(self):
29
  self._functions = {}
 
66
  global tokenizer
67
  model = Model()
68
  try:
69
+ torch_gc()
70
  conf = {
71
  "max_new_tokens": int(
72
  gen_conf.get(