ragflow-cli 0.25.0.dev5__tar.gz → 0.25.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragflow-cli
3
- Version: 0.25.0.dev5
3
+ Version: 0.25.1
4
4
  Summary: Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring.
5
5
  Author-email: Lynn <lynn_inf@hotmail.com>
6
6
  License: Apache License, Version 2.0
@@ -62,7 +62,7 @@ It consists of a server-side Service and a command-line client (CLI), both imple
62
62
  1. Ensure the Admin Service is running.
63
63
  2. Install ragflow-cli.
64
64
  ```bash
65
- pip install ragflow-cli==0.24.0
65
+ pip install ragflow-cli==0.25.1
66
66
  ```
67
67
  3. Launch the CLI client:
68
68
  ```bash
@@ -48,7 +48,7 @@ It consists of a server-side Service and a command-line client (CLI), both imple
48
48
  1. Ensure the Admin Service is running.
49
49
  2. Install ragflow-cli.
50
50
  ```bash
51
- pip install ragflow-cli==0.24.0
51
+ pip install ragflow-cli==0.25.1
52
52
  ```
53
53
  3. Launch the CLI client:
54
54
  ```bash
@@ -77,10 +77,17 @@ sql_command: login_user
77
77
  | drop_user_dataset
78
78
  | list_user_datasets
79
79
  | list_user_dataset_files
80
+ | list_user_dataset_documents
81
+ | list_user_datasets_metadata
82
+ | list_user_documents_metadata_summary
80
83
  | list_user_agents
81
84
  | list_user_chats
82
85
  | create_user_chat
83
86
  | drop_user_chat
87
+ | create_dataset_table
88
+ | drop_dataset_table
89
+ | create_metadata_table
90
+ | drop_metadata_table
84
91
  | list_user_model_providers
85
92
  | list_user_default_models
86
93
  | parse_dataset_docs
@@ -88,20 +95,35 @@ sql_command: login_user
88
95
  | parse_dataset_async
89
96
  | import_docs_into_dataset
90
97
  | search_on_datasets
98
+ | get_chunk
99
+ | list_chunks
100
+ | insert_dataset_from_file
101
+ | insert_metadata_from_file
102
+ | update_chunk
103
+ | set_metadata
104
+ | remove_tags
105
+ | remove_chunks
91
106
  | create_chat_session
92
107
  | drop_chat_session
93
108
  | list_chat_sessions
94
109
  | chat_on_session
95
110
  | list_server_configs
111
+ | show_fingerprint
112
+ | set_license
113
+ | set_license_config
114
+ | show_license
115
+ | check_license
96
116
  | benchmark
97
117
 
98
118
  // meta command definition
99
119
  meta_command: "\\" meta_command_name [meta_args]
100
120
 
121
+ COMMA: ","
122
+
101
123
  meta_command_name: /[a-zA-Z?]+/
102
124
  meta_args: (meta_arg)+
103
125
 
104
- meta_arg: /[^\\s"']+/ | quoted_string
126
+ meta_arg: /[^\s"',]+/ | quoted_string
105
127
 
106
128
  // command definition
107
129
 
@@ -122,6 +144,7 @@ ALTER: "ALTER"i
122
144
  ACTIVE: "ACTIVE"i
123
145
  ADMIN: "ADMIN"i
124
146
  PASSWORD: "PASSWORD"i
147
+ DATASET_TABLE: "DATASET TABLE"i
125
148
  DATASET: "DATASET"i
126
149
  DATASETS: "DATASETS"i
127
150
  OF: "OF"i
@@ -156,11 +179,18 @@ DEFAULT: "DEFAULT"i
156
179
  CHATS: "CHATS"i
157
180
  CHAT: "CHAT"i
158
181
  FILES: "FILES"i
182
+ DOCUMENT: "DOCUMENT"i
183
+ DOCUMENTS: "DOCUMENTS"i
184
+ METADATA: "METADATA"i
185
+ SUMMARY: "SUMMARY"i
159
186
  AS: "AS"i
160
187
  PARSE: "PARSE"i
161
188
  IMPORT: "IMPORT"i
162
189
  INTO: "INTO"i
190
+ IN: "IN"i
163
191
  WITH: "WITH"i
192
+ VECTOR: "VECTOR"i
193
+ SIZE: "SIZE"i
164
194
  PARSER: "PARSER"i
165
195
  PIPELINE: "PIPELINE"i
166
196
  SEARCH: "SEARCH"i
@@ -178,8 +208,25 @@ PING: "PING"i
178
208
  SESSION: "SESSION"i
179
209
  SESSIONS: "SESSIONS"i
180
210
  SERVER: "SERVER"i
181
-
182
- login_user: LOGIN USER quoted_string ";"
211
+ FINGERPRINT: "FINGERPRINT"i
212
+ LICENSE: "LICENSE"i
213
+ CHECK: "CHECK"i
214
+ CONFIG: "CONFIG"i
215
+ INDEX: "INDEX"i
216
+ TABLE: "TABLE"i
217
+ CHUNK: "CHUNK"i
218
+ CHUNKS: "CHUNKS"i
219
+ GET: "GET"i
220
+ INSERT: "INSERT"i
221
+ PAGE: "PAGE"i
222
+ KEYWORDS: "KEYWORDS"i
223
+ AVAILABLE: "AVAILABLE"i
224
+ FILE: "FILE"i
225
+ UPDATE: "UPDATE"i
226
+ REMOVE: "REMOVE"i
227
+ TAGS: "TAGS"i
228
+
229
+ login_user: LOGIN USER quoted_string (PASSWORD quoted_string)? ";"
183
230
  list_services: LIST SERVICES ";"
184
231
  show_service: SHOW SERVICE NUMBER ";"
185
232
  startup_service: STARTUP SERVICE NUMBER ";"
@@ -223,6 +270,12 @@ list_variables: LIST VARS ";"
223
270
  list_configs: LIST CONFIGS ";"
224
271
  list_environments: LIST ENVS ";"
225
272
 
273
+ show_fingerprint: SHOW FINGERPRINT ";"
274
+ set_license: SET LICENSE quoted_string ";"
275
+ set_license_config: SET LICENSE CONFIG NUMBER NUMBER ";"
276
+ show_license: SHOW LICENSE ";"
277
+ check_license: CHECK LICENSE ";"
278
+
226
279
  list_server_configs: LIST SERVER CONFIGS ";"
227
280
 
228
281
  benchmark: BENCHMARK NUMBER NUMBER user_statement
@@ -256,6 +309,9 @@ user_statement: ping_server
256
309
  | list_user_default_models
257
310
  | import_docs_into_dataset
258
311
  | search_on_datasets
312
+ | update_chunk
313
+ | set_metadata
314
+ | remove_tags
259
315
  | create_chat_session
260
316
  | drop_chat_session
261
317
  | list_chat_sessions
@@ -284,6 +340,9 @@ create_user_dataset_with_parser: CREATE DATASET quoted_string WITH EMBEDDING quo
284
340
  create_user_dataset_with_pipeline: CREATE DATASET quoted_string WITH EMBEDDING quoted_string PIPELINE quoted_string ";"
285
341
  drop_user_dataset: DROP DATASET quoted_string ";"
286
342
  list_user_dataset_files: LIST FILES OF DATASET quoted_string ";"
343
+ list_user_dataset_documents: LIST DOCUMENTS OF DATASET quoted_string ";"
344
+ list_user_datasets_metadata: LIST METADATA OF DATASETS quoted_string (COMMA quoted_string)* ";"
345
+ list_user_documents_metadata_summary: LIST METADATA SUMMARY OF DATASET quoted_string (DOCUMENTS quoted_string (COMMA quoted_string)*)? ";"
287
346
  list_user_agents: LIST AGENTS ";"
288
347
  list_user_chats: LIST CHATS ";"
289
348
  create_user_chat: CREATE CHAT quoted_string ";"
@@ -296,16 +355,31 @@ list_user_model_providers: LIST MODEL PROVIDERS ";"
296
355
  list_user_default_models: LIST DEFAULT MODELS ";"
297
356
  import_docs_into_dataset: IMPORT quoted_string INTO DATASET quoted_string ";"
298
357
  search_on_datasets: SEARCH quoted_string ON DATASETS quoted_string ";"
358
+ get_chunk: GET CHUNK quoted_string ";"
359
+ list_chunks: LIST CHUNKS OF DOCUMENT quoted_string ("PAGE" NUMBER)? ("SIZE" NUMBER)? ("KEYWORDS" quoted_string)? ("AVAILABLE" NUMBER)? ";"
360
+ set_metadata: SET METADATA OF DOCUMENT quoted_string TO quoted_string ";"
361
+ remove_tags: REMOVE TAGS quoted_string (COMMA quoted_string)* FROM DATASET quoted_string ";"
362
+ remove_chunks: REMOVE CHUNKS quoted_string (COMMA quoted_string)* FROM DOCUMENT quoted_string ";"
363
+ | REMOVE ALL CHUNKS FROM DOCUMENT quoted_string ";"
299
364
 
300
365
  parse_dataset_docs: PARSE quoted_string OF DATASET quoted_string ";"
301
366
  parse_dataset_sync: PARSE DATASET quoted_string SYNC ";"
302
367
  parse_dataset_async: PARSE DATASET quoted_string ASYNC ";"
303
368
 
304
- identifier_list: identifier ("," identifier)*
369
+ // Internal CLI only for GO
370
+ create_dataset_table: CREATE DATASET TABLE quoted_string VECTOR SIZE NUMBER ";"
371
+ drop_dataset_table: DROP DATASET TABLE quoted_string ";"
372
+ create_metadata_table: CREATE METADATA TABLE ";"
373
+ drop_metadata_table: DROP METADATA TABLE ";"
374
+ insert_dataset_from_file: INSERT DATASET FROM FILE quoted_string ";"
375
+ insert_metadata_from_file: INSERT METADATA FROM FILE quoted_string ";"
376
+ update_chunk: UPDATE CHUNK quoted_string OF DATASET quoted_string SET quoted_string ";"
377
+
378
+ identifier_list: identifier (COMMA identifier)*
305
379
 
306
380
  identifier: WORD
307
381
  quoted_string: QUOTED_STRING
308
- status: WORD
382
+ status: ON | WORD
309
383
 
310
384
  QUOTED_STRING: /'[^']+'/ | /"[^"]+"/
311
385
  WORD: /[a-zA-Z0-9_\-\.]+/
@@ -325,7 +399,13 @@ class RAGFlowCLITransformer(Transformer):
325
399
 
326
400
  def login_user(self, items):
327
401
  email = items[2].children[0].strip("'\"")
328
- return {"type": "login_user", "email": email}
402
+ if len(items) == 5:
403
+ # With password: LOGIN USER email PASSWORD password
404
+ password = items[4].children[0].strip("'\"")
405
+ return {"type": "login_user", "email": email, "password": password}
406
+ else:
407
+ # Without password: LOGIN USER email
408
+ return {"type": "login_user", "email": email}
329
409
 
330
410
  def ping_server(self, items):
331
411
  return {"type": "ping_server"}
@@ -477,6 +557,24 @@ class RAGFlowCLITransformer(Transformer):
477
557
  def list_environments(self, items):
478
558
  return {"type": "list_environments"}
479
559
 
560
+ def show_fingerprint(self, items):
561
+ return {"type": "show_fingerprint"}
562
+
563
+ def set_license(self, items):
564
+ license = items[2].children[0].strip("'\"")
565
+ return {"type": "set_license", "license": license}
566
+
567
+ def set_license_config(self, items):
568
+ value1: int = int(items[3])
569
+ value2: int = int(items[4])
570
+ return {"type": "set_license_config", "value1": value1, "value2": value2}
571
+
572
+ def show_license(self, items):
573
+ return {"type": "show_license"}
574
+
575
+ def check_license(self, items):
576
+ return {"type": "check_license"}
577
+
480
578
  def list_server_configs(self, items):
481
579
  return {"type": "list_server_configs"}
482
580
 
@@ -559,6 +657,28 @@ class RAGFlowCLITransformer(Transformer):
559
657
  dataset_name = items[4].children[0].strip("'\"")
560
658
  return {"type": "list_user_dataset_files", "dataset_name": dataset_name}
561
659
 
660
+ def list_user_dataset_documents(self, items):
661
+ dataset_name = items[4].children[0].strip("'\"")
662
+ return {"type": "list_user_dataset_documents", "dataset_name": dataset_name}
663
+
664
+ def list_user_datasets_metadata(self, items):
665
+ dataset_names = []
666
+ dataset_names.append(items[4].children[0].strip("'\""))
667
+ for i in range(5, len(items)):
668
+ if items[i] and hasattr(items[i], 'children') and items[i].children:
669
+ dataset_names.append(items[i].children[0].strip("'\""))
670
+ return {"type": "list_user_datasets_metadata", "dataset_names": dataset_names}
671
+
672
+ def list_user_documents_metadata_summary(self, items):
673
+ dataset_name = items[5].children[0].strip("'\"")
674
+ doc_ids = []
675
+ if len(items) > 6 and items[6] == "DOCUMENTS":
676
+ for i in range(7, len(items)):
677
+ if items[i] and hasattr(items[i], 'children') and items[i].children:
678
+ doc_id = items[i].children[0].strip("'\"")
679
+ doc_ids.append(doc_id)
680
+ return {"type": "list_user_documents_metadata_summary", "dataset_name": dataset_name, "document_ids": doc_ids}
681
+
562
682
  def list_user_agents(self, items):
563
683
  return {"type": "list_user_agents"}
564
684
 
@@ -573,6 +693,30 @@ class RAGFlowCLITransformer(Transformer):
573
693
  chat_name = items[2].children[0].strip("'\"")
574
694
  return {"type": "drop_user_chat", "chat_name": chat_name}
575
695
 
696
+ def create_dataset_table(self, items):
697
+ dataset_name = None
698
+ vector_size = None
699
+ for i, item in enumerate(items):
700
+ if hasattr(item, 'data') and item.data == 'quoted_string':
701
+ dataset_name = item.children[0].strip("'\"")
702
+ if hasattr(item, 'type') and item.type == 'NUMBER':
703
+ if i > 0 and items[i-1].type == 'SIZE' and items[i-2].type == 'VECTOR':
704
+ vector_size = int(item)
705
+ return {"type": "create_dataset_table", "dataset_name": dataset_name, "vector_size": vector_size}
706
+
707
+ def drop_dataset_table(self, items):
708
+ dataset_name = None
709
+ for item in items:
710
+ if hasattr(item, 'data') and item.data == 'quoted_string':
711
+ dataset_name = item.children[0].strip("'\"")
712
+ return {"type": "drop_dataset_table", "dataset_name": dataset_name}
713
+
714
+ def create_metadata_table(self, items):
715
+ return {"type": "create_metadata_table"}
716
+
717
+ def drop_metadata_table(self, items):
718
+ return {"type": "drop_metadata_table"}
719
+
576
720
  def list_user_model_providers(self, items):
577
721
  return {"type": "list_user_model_providers"}
578
722
 
@@ -633,6 +777,103 @@ class RAGFlowCLITransformer(Transformer):
633
777
  datasets = datasets.split(" ")
634
778
  return {"type": "search_on_datasets", "datasets": datasets, "question": question}
635
779
 
780
+ def get_chunk(self, items):
781
+ chunk_id = items[2].children[0].strip("'\"")
782
+ return {"type": "get_chunk", "chunk_id": chunk_id}
783
+
784
+ def insert_dataset_from_file(self, items):
785
+ file_path = items[4].children[0].strip("'\"")
786
+ return {"type": "insert_dataset_from_file", "file_path": file_path}
787
+
788
+ def insert_metadata_from_file(self, items):
789
+ file_path = items[4].children[0].strip("'\"")
790
+ return {"type": "insert_metadata_from_file", "file_path": file_path}
791
+
792
+ def update_chunk(self, items):
793
+ def get_quoted_value(item):
794
+ if hasattr(item, 'children') and item.children:
795
+ return item.children[0].strip("'\"")
796
+ return str(item).strip("'\"")
797
+
798
+ chunk_id = get_quoted_value(items[2])
799
+ dataset_name = get_quoted_value(items[5])
800
+ json_body = get_quoted_value(items[7])
801
+ return {"type": "update_chunk", "chunk_id": chunk_id, "dataset_name": dataset_name, "json_body": json_body}
802
+
803
+ def set_metadata(self, items):
804
+ doc_id = items[4].children[0].strip("'\"")
805
+ meta_json = items[6].children[0].strip("'\"")
806
+ return {"type": "set_metadata", "doc_id": doc_id, "meta": meta_json}
807
+
808
+ def remove_tags(self, items):
809
+ # items: REMOVE, TAGS, quoted_string(tag1), quoted_string(tag2), ..., FROM, DATASET, quoted_string(dataset_name), ";"
810
+ tags = []
811
+ # Start from index 2 (after TAGS keyword) and parse quoted strings until FROM
812
+ for i in range(2, len(items)):
813
+ item = items[i]
814
+ # Check for FROM token to stop
815
+ if hasattr(item, 'type') and item.type == 'FROM':
816
+ break
817
+ if hasattr(item, 'children') and item.children:
818
+ tag = item.children[0].strip("'\"")
819
+ tags.append(tag)
820
+ # Find dataset_name: quoted_string after DATASET
821
+ dataset_name = None
822
+ for i, item in enumerate(items):
823
+ # Check if item is a DATASET token
824
+ if hasattr(item, 'type') and item.type == 'DATASET':
825
+ # Next item should be quoted_string
826
+ dataset_name = items[i + 1].children[0].strip("'\"")
827
+ break
828
+ return {"type": "remove_tags", "dataset_name": dataset_name, "tags": tags}
829
+
830
+ def remove_chunks(self, items):
831
+ # Handle two cases:
832
+ # 1. REMOVE CHUNKS quoted_string (COMMA quoted_string)* FROM DOCUMENT quoted_string ";"
833
+ # 2. REMOVE ALL CHUNKS FROM DOCUMENT quoted_string ";"
834
+
835
+ # Check if it's "REMOVE ALL CHUNKS"
836
+ for item in items:
837
+ if hasattr(item, 'type') and item.type == 'ALL':
838
+ # Find doc_id
839
+ for j, inner_item in enumerate(items):
840
+ if hasattr(inner_item, 'type') and inner_item.type == 'DOCUMENT':
841
+ doc_id = items[j + 1].children[0].strip("'\"")
842
+ return {"type": "remove_chunks", "doc_id": doc_id, "delete_all": True}
843
+
844
+ # Otherwise, we have chunk_ids
845
+ chunk_ids = []
846
+ doc_id = None
847
+ for i, item in enumerate(items):
848
+ if hasattr(item, 'type') and item.type == 'DOCUMENT':
849
+ doc_id = items[i + 1].children[0].strip("'\"")
850
+ elif hasattr(item, 'children') and item.children:
851
+ val = item.children[0].strip("'\"")
852
+ # Skip if it's "FROM" or "DOCUMENT"
853
+ if val.upper() in ['FROM', 'DOCUMENT']:
854
+ continue
855
+ chunk_ids.append(val)
856
+
857
+ return {"type": "remove_chunks", "doc_id": doc_id, "chunk_ids": chunk_ids}
858
+
859
+ def list_chunks(self, items):
860
+ doc_id = items[4].children[0].strip("'\"")
861
+ result = {"type": "list_chunks", "doc_id": doc_id}
862
+
863
+ # Parse optional parameters: PAGE, SIZE, KEYWORDS, AVAILABLE
864
+ # items structure varies based on which params are present
865
+ for i, item in enumerate(items):
866
+ if str(item) == "PAGE":
867
+ result["page"] = int(items[i + 1])
868
+ elif str(item) == "SIZE":
869
+ result["size"] = int(items[i + 1])
870
+ elif str(item) == "KEYWORDS":
871
+ result["keywords"] = items[i + 1].children[0].strip("'\"")
872
+ elif str(item) == "AVAILABLE":
873
+ result["available_int"] = int(items[i + 1])
874
+
875
+ return result
876
+
636
877
  def benchmark(self, items):
637
878
  concurrency: int = int(items[1])
638
879
  iterations: int = int(items[2])
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ragflow-cli"
3
- version = "0.25.0.dev5"
3
+ version = "0.25.1"
4
4
  description = "Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring. "
5
5
  authors = [{ name = "Lynn", email = "lynn_inf@hotmail.com" }]
6
6
  license = { text = "Apache License, Version 2.0" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragflow-cli
3
- Version: 0.25.0.dev5
3
+ Version: 0.25.1
4
4
  Summary: Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring.
5
5
  Author-email: Lynn <lynn_inf@hotmail.com>
6
6
  License: Apache License, Version 2.0
@@ -62,7 +62,7 @@ It consists of a server-side Service and a command-line client (CLI), both imple
62
62
  1. Ensure the Admin Service is running.
63
63
  2. Install ragflow-cli.
64
64
  ```bash
65
- pip install ragflow-cli==0.24.0
65
+ pip install ragflow-cli==0.25.1
66
66
  ```
67
67
  3. Launch the CLI client:
68
68
  ```bash
@@ -18,6 +18,9 @@ import sys
18
18
  import argparse
19
19
  import base64
20
20
  import getpass
21
+ import os
22
+ import atexit
23
+ import readline
21
24
  from cmd import Cmd
22
25
  from typing import Any, Dict, List
23
26
 
@@ -61,6 +64,12 @@ class RAGFlowCLI(Cmd):
61
64
  self.port: int = 0
62
65
  self.mode: str = "admin"
63
66
  self.ragflow_client = None
67
+ # History file for readline persistence
68
+ self.history_file = os.path.expanduser("~/.ragflow_cli_history")
69
+ # Load existing history
70
+ self._load_history()
71
+ # Register cleanup to save history on exit
72
+ atexit.register(self._save_history)
64
73
 
65
74
  intro = r"""Type "\h" for help."""
66
75
  prompt = "ragflow> "
@@ -99,6 +108,7 @@ class RAGFlowCLI(Cmd):
99
108
  return {"type": "empty"}
100
109
 
101
110
  self.command_history.append(command_str)
111
+ readline.add_history(command_str)
102
112
 
103
113
  try:
104
114
  result = self.parser.parse(command_str)
@@ -210,6 +220,21 @@ class RAGFlowCLI(Cmd):
210
220
 
211
221
  print(separator)
212
222
 
223
+ def _load_history(self):
224
+ """Load command history from file."""
225
+ try:
226
+ if os.path.exists(self.history_file):
227
+ readline.read_history_file(self.history_file)
228
+ except Exception:
229
+ pass # Ignore errors loading history
230
+
231
+ def _save_history(self):
232
+ """Save command history to file."""
233
+ try:
234
+ readline.write_history_file(self.history_file)
235
+ except Exception:
236
+ pass # Ignore errors saving history
237
+
213
238
  def run_interactive(self, args):
214
239
  if self.verify_auth(args, single_command=False, auth=args["auth"]):
215
240
  print(r"""