ParisNeo commited on
Commit
09b8333
·
1 Parent(s): 6984dd1

applyed linting

Browse files
README.md CHANGED
@@ -1077,7 +1077,7 @@ Each server has its own specific configuration options:
1077
  | --key | none | Access Key to protect the lightrag service |
1078
 
1079
 
1080
- For protecting the server using an authentication key, you can also use an environment variable named `LIGHTRAG_API_KEY`.
1081
  ### Example Usage
1082
 
1083
  #### LoLLMs RAG Server
@@ -1088,6 +1088,10 @@ lollms-lightrag-server --model mistral-nemo --port 8080 --working-dir ./custom_r
1088
 
1089
  # Using specific models (ensure they are installed in your LoLLMs instance)
1090
  lollms-lightrag-server --model mistral-nemo:latest --embedding-model bge-m3 --embedding-dim 1024
 
 
 
 
1091
  ```
1092
 
1093
  #### Ollama RAG Server
 
1077
  | --key | none | Access Key to protect the lightrag service |
1078
 
1079
 
1080
+ For protecting the server using an authentication key, you can also use an environment variable named `LIGHTRAG_API_KEY`.
1081
  ### Example Usage
1082
 
1083
  #### LoLLMs RAG Server
 
1088
 
1089
  # Using specific models (ensure they are installed in your LoLLMs instance)
1090
  lollms-lightrag-server --model mistral-nemo:latest --embedding-model bge-m3 --embedding-dim 1024
1091
+
1092
+ # Using specific models and an authentication key
1093
+ lollms-lightrag-server --model mistral-nemo:latest --embedding-model bge-m3 --embedding-dim 1024 --key ky-mykey
1094
+
1095
  ```
1096
 
1097
  #### Ollama RAG Server
lightrag/api/azure_openai_lightrag_server.py CHANGED
@@ -20,19 +20,12 @@ from dotenv import load_dotenv
20
  import inspect
21
  import json
22
  from fastapi.responses import StreamingResponse
23
- from fastapi import FastAPI, HTTPException
24
- import os
25
- from typing import Optional
26
 
27
- from fastapi import FastAPI, Depends, HTTPException, Security
28
  from fastapi.security import APIKeyHeader
29
- import os
30
- import argparse
31
- from typing import Optional
32
  from fastapi.middleware.cors import CORSMiddleware
33
 
34
  from starlette.status import HTTP_403_FORBIDDEN
35
- from fastapi import HTTPException
36
 
37
  load_dotenv()
38
 
@@ -106,8 +99,12 @@ def parse_args():
106
  help="Logging level (default: INFO)",
107
  )
108
 
109
- parser.add_argument('--key', type=str, help='API key for authentication. This protects lightrag server against unauthorized access', default=None)
110
-
 
 
 
 
111
 
112
  return parser.parse_args()
113
 
@@ -170,29 +167,29 @@ class InsertResponse(BaseModel):
170
  message: str
171
  document_count: int
172
 
 
173
  def get_api_key_dependency(api_key: Optional[str]):
174
  if not api_key:
175
  # If no API key is configured, return a dummy dependency that always succeeds
176
  async def no_auth():
177
  return None
 
178
  return no_auth
179
-
180
  # If API key is configured, use proper authentication
181
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
182
-
183
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
184
  if not api_key_header_value:
185
  raise HTTPException(
186
- status_code=HTTP_403_FORBIDDEN,
187
- detail="API Key required"
188
  )
189
  if api_key_header_value != api_key:
190
  raise HTTPException(
191
- status_code=HTTP_403_FORBIDDEN,
192
- detail="Invalid API Key"
193
  )
194
  return api_key_header_value
195
-
196
  return api_key_auth
197
 
198
 
@@ -209,18 +206,20 @@ def create_app(args):
209
  format="%(levelname)s:%(message)s", level=getattr(logging, args.log_level)
210
  )
211
 
212
-
213
  # Check if API key is provided either through env var or args
214
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
215
-
216
  # Initialize FastAPI
217
  app = FastAPI(
218
  title="LightRAG API",
219
- description="API for querying text using LightRAG with separate storage and input directories"+"(With authentication)" if api_key else "",
 
 
 
220
  version="1.0.0",
221
- openapi_tags=[{"name": "api"}]
222
  )
223
-
224
  # Add CORS middleware
225
  app.add_middleware(
226
  CORSMiddleware,
@@ -363,7 +362,9 @@ def create_app(args):
363
  except Exception as e:
364
  raise HTTPException(status_code=500, detail=str(e))
365
 
366
- @app.post("/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)])
 
 
367
  async def query_text(request: QueryRequest):
368
  try:
369
  response = await rag.aquery(
@@ -404,7 +405,11 @@ def create_app(args):
404
  except Exception as e:
405
  raise HTTPException(status_code=500, detail=str(e))
406
 
407
- @app.post("/documents/text", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
408
  async def insert_text(request: InsertTextRequest):
409
  try:
410
  await rag.ainsert(request.text)
@@ -416,7 +421,11 @@ def create_app(args):
416
  except Exception as e:
417
  raise HTTPException(status_code=500, detail=str(e))
418
 
419
- @app.post("/documents/file", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
420
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
421
  try:
422
  content = await file.read()
@@ -440,7 +449,11 @@ def create_app(args):
440
  except Exception as e:
441
  raise HTTPException(status_code=500, detail=str(e))
442
 
443
- @app.post("/documents/batch", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
444
  async def insert_batch(files: List[UploadFile] = File(...)):
445
  try:
446
  inserted_count = 0
@@ -470,7 +483,11 @@ def create_app(args):
470
  except Exception as e:
471
  raise HTTPException(status_code=500, detail=str(e))
472
 
473
- @app.delete("/documents", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
474
  async def clear_documents():
475
  try:
476
  rag.text_chunks = []
 
20
  import inspect
21
  import json
22
  from fastapi.responses import StreamingResponse
 
 
 
23
 
24
+ from fastapi import Depends, Security
25
  from fastapi.security import APIKeyHeader
 
 
 
26
  from fastapi.middleware.cors import CORSMiddleware
27
 
28
  from starlette.status import HTTP_403_FORBIDDEN
 
29
 
30
  load_dotenv()
31
 
 
99
  help="Logging level (default: INFO)",
100
  )
101
 
102
+ parser.add_argument(
103
+ "--key",
104
+ type=str,
105
+ help="API key for authentication. This protects lightrag server against unauthorized access",
106
+ default=None,
107
+ )
108
 
109
  return parser.parse_args()
110
 
 
167
  message: str
168
  document_count: int
169
 
170
+
171
  def get_api_key_dependency(api_key: Optional[str]):
172
  if not api_key:
173
  # If no API key is configured, return a dummy dependency that always succeeds
174
  async def no_auth():
175
  return None
176
+
177
  return no_auth
178
+
179
  # If API key is configured, use proper authentication
180
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
181
+
182
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
183
  if not api_key_header_value:
184
  raise HTTPException(
185
+ status_code=HTTP_403_FORBIDDEN, detail="API Key required"
 
186
  )
187
  if api_key_header_value != api_key:
188
  raise HTTPException(
189
+ status_code=HTTP_403_FORBIDDEN, detail="Invalid API Key"
 
190
  )
191
  return api_key_header_value
192
+
193
  return api_key_auth
194
 
195
 
 
206
  format="%(levelname)s:%(message)s", level=getattr(logging, args.log_level)
207
  )
208
 
 
209
  # Check if API key is provided either through env var or args
210
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
211
+
212
  # Initialize FastAPI
213
  app = FastAPI(
214
  title="LightRAG API",
215
+ description="API for querying text using LightRAG with separate storage and input directories"
216
+ + "(With authentication)"
217
+ if api_key
218
+ else "",
219
  version="1.0.0",
220
+ openapi_tags=[{"name": "api"}],
221
  )
222
+
223
  # Add CORS middleware
224
  app.add_middleware(
225
  CORSMiddleware,
 
362
  except Exception as e:
363
  raise HTTPException(status_code=500, detail=str(e))
364
 
365
+ @app.post(
366
+ "/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)]
367
+ )
368
  async def query_text(request: QueryRequest):
369
  try:
370
  response = await rag.aquery(
 
405
  except Exception as e:
406
  raise HTTPException(status_code=500, detail=str(e))
407
 
408
+ @app.post(
409
+ "/documents/text",
410
+ response_model=InsertResponse,
411
+ dependencies=[Depends(optional_api_key)],
412
+ )
413
  async def insert_text(request: InsertTextRequest):
414
  try:
415
  await rag.ainsert(request.text)
 
421
  except Exception as e:
422
  raise HTTPException(status_code=500, detail=str(e))
423
 
424
+ @app.post(
425
+ "/documents/file",
426
+ response_model=InsertResponse,
427
+ dependencies=[Depends(optional_api_key)],
428
+ )
429
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
430
  try:
431
  content = await file.read()
 
449
  except Exception as e:
450
  raise HTTPException(status_code=500, detail=str(e))
451
 
452
+ @app.post(
453
+ "/documents/batch",
454
+ response_model=InsertResponse,
455
+ dependencies=[Depends(optional_api_key)],
456
+ )
457
  async def insert_batch(files: List[UploadFile] = File(...)):
458
  try:
459
  inserted_count = 0
 
483
  except Exception as e:
484
  raise HTTPException(status_code=500, detail=str(e))
485
 
486
+ @app.delete(
487
+ "/documents",
488
+ response_model=InsertResponse,
489
+ dependencies=[Depends(optional_api_key)],
490
+ )
491
  async def clear_documents():
492
  try:
493
  rag.text_chunks = []
lightrag/api/lollms_lightrag_server.py CHANGED
@@ -11,19 +11,14 @@ from pathlib import Path
11
  import shutil
12
  import aiofiles
13
  from ascii_colors import trace_exception
14
- from fastapi import FastAPI, HTTPException
15
  import os
16
- from typing import Optional
17
 
18
- from fastapi import FastAPI, Depends, HTTPException, Security
19
  from fastapi.security import APIKeyHeader
20
- import os
21
- import argparse
22
- from typing import Optional
23
  from fastapi.middleware.cors import CORSMiddleware
24
 
25
  from starlette.status import HTTP_403_FORBIDDEN
26
- from fastapi import HTTPException
27
 
28
  def parse_args():
29
  parser = argparse.ArgumentParser(
@@ -98,8 +93,12 @@ def parse_args():
98
  help="Logging level (default: INFO)",
99
  )
100
 
101
- parser.add_argument('--key', type=str, help='API key for authentication. This protects lightrag server against unauthorized access', default=None)
102
-
 
 
 
 
103
 
104
  return parser.parse_args()
105
 
@@ -162,29 +161,29 @@ class InsertResponse(BaseModel):
162
  message: str
163
  document_count: int
164
 
 
165
  def get_api_key_dependency(api_key: Optional[str]):
166
  if not api_key:
167
  # If no API key is configured, return a dummy dependency that always succeeds
168
  async def no_auth():
169
  return None
 
170
  return no_auth
171
-
172
  # If API key is configured, use proper authentication
173
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
174
-
175
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
176
  if not api_key_header_value:
177
  raise HTTPException(
178
- status_code=HTTP_403_FORBIDDEN,
179
- detail="API Key required"
180
  )
181
  if api_key_header_value != api_key:
182
  raise HTTPException(
183
- status_code=HTTP_403_FORBIDDEN,
184
- detail="Invalid API Key"
185
  )
186
  return api_key_header_value
187
-
188
  return api_key_auth
189
 
190
 
@@ -196,15 +195,18 @@ def create_app(args):
196
 
197
  # Check if API key is provided either through env var or args
198
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
199
-
200
  # Initialize FastAPI
201
  app = FastAPI(
202
  title="LightRAG API",
203
- description="API for querying text using LightRAG with separate storage and input directories"+"(With authentication)" if api_key else "",
 
 
 
204
  version="1.0.0",
205
- openapi_tags=[{"name": "api"}]
206
  )
207
-
208
  # Add CORS middleware
209
  app.add_middleware(
210
  CORSMiddleware,
@@ -319,7 +321,9 @@ def create_app(args):
319
  except Exception as e:
320
  raise HTTPException(status_code=500, detail=str(e))
321
 
322
- @app.post("/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)])
 
 
323
  async def query_text(request: QueryRequest):
324
  try:
325
  response = await rag.aquery(
@@ -361,7 +365,11 @@ def create_app(args):
361
  except Exception as e:
362
  raise HTTPException(status_code=500, detail=str(e))
363
 
364
- @app.post("/documents/text", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
365
  async def insert_text(request: InsertTextRequest):
366
  try:
367
  rag.insert(request.text)
@@ -373,7 +381,11 @@ def create_app(args):
373
  except Exception as e:
374
  raise HTTPException(status_code=500, detail=str(e))
375
 
376
- @app.post("/documents/file", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
377
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
378
  try:
379
  content = await file.read()
@@ -397,7 +409,11 @@ def create_app(args):
397
  except Exception as e:
398
  raise HTTPException(status_code=500, detail=str(e))
399
 
400
- @app.post("/documents/batch", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
401
  async def insert_batch(files: List[UploadFile] = File(...)):
402
  try:
403
  inserted_count = 0
@@ -427,7 +443,11 @@ def create_app(args):
427
  except Exception as e:
428
  raise HTTPException(status_code=500, detail=str(e))
429
 
430
- @app.delete("/documents", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
431
  async def clear_documents():
432
  try:
433
  rag.text_chunks = []
 
11
  import shutil
12
  import aiofiles
13
  from ascii_colors import trace_exception
 
14
  import os
 
15
 
16
+ from fastapi import Depends, Security
17
  from fastapi.security import APIKeyHeader
 
 
 
18
  from fastapi.middleware.cors import CORSMiddleware
19
 
20
  from starlette.status import HTTP_403_FORBIDDEN
21
+
22
 
23
  def parse_args():
24
  parser = argparse.ArgumentParser(
 
93
  help="Logging level (default: INFO)",
94
  )
95
 
96
+ parser.add_argument(
97
+ "--key",
98
+ type=str,
99
+ help="API key for authentication. This protects lightrag server against unauthorized access",
100
+ default=None,
101
+ )
102
 
103
  return parser.parse_args()
104
 
 
161
  message: str
162
  document_count: int
163
 
164
+
165
  def get_api_key_dependency(api_key: Optional[str]):
166
  if not api_key:
167
  # If no API key is configured, return a dummy dependency that always succeeds
168
  async def no_auth():
169
  return None
170
+
171
  return no_auth
172
+
173
  # If API key is configured, use proper authentication
174
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
175
+
176
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
177
  if not api_key_header_value:
178
  raise HTTPException(
179
+ status_code=HTTP_403_FORBIDDEN, detail="API Key required"
 
180
  )
181
  if api_key_header_value != api_key:
182
  raise HTTPException(
183
+ status_code=HTTP_403_FORBIDDEN, detail="Invalid API Key"
 
184
  )
185
  return api_key_header_value
186
+
187
  return api_key_auth
188
 
189
 
 
195
 
196
  # Check if API key is provided either through env var or args
197
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
198
+
199
  # Initialize FastAPI
200
  app = FastAPI(
201
  title="LightRAG API",
202
+ description="API for querying text using LightRAG with separate storage and input directories"
203
+ + "(With authentication)"
204
+ if api_key
205
+ else "",
206
  version="1.0.0",
207
+ openapi_tags=[{"name": "api"}],
208
  )
209
+
210
  # Add CORS middleware
211
  app.add_middleware(
212
  CORSMiddleware,
 
321
  except Exception as e:
322
  raise HTTPException(status_code=500, detail=str(e))
323
 
324
+ @app.post(
325
+ "/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)]
326
+ )
327
  async def query_text(request: QueryRequest):
328
  try:
329
  response = await rag.aquery(
 
365
  except Exception as e:
366
  raise HTTPException(status_code=500, detail=str(e))
367
 
368
+ @app.post(
369
+ "/documents/text",
370
+ response_model=InsertResponse,
371
+ dependencies=[Depends(optional_api_key)],
372
+ )
373
  async def insert_text(request: InsertTextRequest):
374
  try:
375
  rag.insert(request.text)
 
381
  except Exception as e:
382
  raise HTTPException(status_code=500, detail=str(e))
383
 
384
+ @app.post(
385
+ "/documents/file",
386
+ response_model=InsertResponse,
387
+ dependencies=[Depends(optional_api_key)],
388
+ )
389
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
390
  try:
391
  content = await file.read()
 
409
  except Exception as e:
410
  raise HTTPException(status_code=500, detail=str(e))
411
 
412
+ @app.post(
413
+ "/documents/batch",
414
+ response_model=InsertResponse,
415
+ dependencies=[Depends(optional_api_key)],
416
+ )
417
  async def insert_batch(files: List[UploadFile] = File(...)):
418
  try:
419
  inserted_count = 0
 
443
  except Exception as e:
444
  raise HTTPException(status_code=500, detail=str(e))
445
 
446
+ @app.delete(
447
+ "/documents",
448
+ response_model=InsertResponse,
449
+ dependencies=[Depends(optional_api_key)],
450
+ )
451
  async def clear_documents():
452
  try:
453
  rag.text_chunks = []
lightrag/api/ollama_lightrag_server.py CHANGED
@@ -11,19 +11,13 @@ from pathlib import Path
11
  import shutil
12
  import aiofiles
13
  from ascii_colors import trace_exception
14
- from fastapi import FastAPI, HTTPException
15
  import os
16
- from typing import Optional
17
 
18
- from fastapi import FastAPI, Depends, HTTPException, Security
19
  from fastapi.security import APIKeyHeader
20
- import os
21
- import argparse
22
- from typing import Optional
23
  from fastapi.middleware.cors import CORSMiddleware
24
 
25
  from starlette.status import HTTP_403_FORBIDDEN
26
- from fastapi import HTTPException
27
 
28
 
29
  def parse_args():
@@ -98,7 +92,12 @@ def parse_args():
98
  choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
99
  help="Logging level (default: INFO)",
100
  )
101
- parser.add_argument('--key', type=str, help='API key for authentication. This protects lightrag server against unauthorized access', default=None)
 
 
 
 
 
102
 
103
  return parser.parse_args()
104
 
@@ -161,29 +160,29 @@ class InsertResponse(BaseModel):
161
  message: str
162
  document_count: int
163
 
 
164
  def get_api_key_dependency(api_key: Optional[str]):
165
  if not api_key:
166
  # If no API key is configured, return a dummy dependency that always succeeds
167
  async def no_auth():
168
  return None
 
169
  return no_auth
170
-
171
  # If API key is configured, use proper authentication
172
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
173
-
174
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
175
  if not api_key_header_value:
176
  raise HTTPException(
177
- status_code=HTTP_403_FORBIDDEN,
178
- detail="API Key required"
179
  )
180
  if api_key_header_value != api_key:
181
  raise HTTPException(
182
- status_code=HTTP_403_FORBIDDEN,
183
- detail="Invalid API Key"
184
  )
185
  return api_key_header_value
186
-
187
  return api_key_auth
188
 
189
 
@@ -195,15 +194,18 @@ def create_app(args):
195
 
196
  # Check if API key is provided either through env var or args
197
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
198
-
199
  # Initialize FastAPI
200
  app = FastAPI(
201
  title="LightRAG API",
202
- description="API for querying text using LightRAG with separate storage and input directories"+"(With authentication)" if api_key else "",
 
 
 
203
  version="1.0.0",
204
- openapi_tags=[{"name": "api"}]
205
  )
206
-
207
  # Add CORS middleware
208
  app.add_middleware(
209
  CORSMiddleware,
@@ -216,7 +218,6 @@ def create_app(args):
216
  # Create the optional API key dependency
217
  optional_api_key = get_api_key_dependency(api_key)
218
 
219
-
220
  # Create working directory if it doesn't exist
221
  Path(args.working_dir).mkdir(parents=True, exist_ok=True)
222
 
@@ -319,7 +320,9 @@ def create_app(args):
319
  except Exception as e:
320
  raise HTTPException(status_code=500, detail=str(e))
321
 
322
- @app.post("/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)])
 
 
323
  async def query_text(request: QueryRequest):
324
  try:
325
  response = await rag.aquery(
@@ -361,7 +364,11 @@ def create_app(args):
361
  except Exception as e:
362
  raise HTTPException(status_code=500, detail=str(e))
363
 
364
- @app.post("/documents/text", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
365
  async def insert_text(request: InsertTextRequest):
366
  try:
367
  await rag.ainsert(request.text)
@@ -373,7 +380,11 @@ def create_app(args):
373
  except Exception as e:
374
  raise HTTPException(status_code=500, detail=str(e))
375
 
376
- @app.post("/documents/file", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
377
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
378
  try:
379
  content = await file.read()
@@ -397,7 +408,11 @@ def create_app(args):
397
  except Exception as e:
398
  raise HTTPException(status_code=500, detail=str(e))
399
 
400
- @app.post("/documents/batch", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
401
  async def insert_batch(files: List[UploadFile] = File(...)):
402
  try:
403
  inserted_count = 0
@@ -427,7 +442,11 @@ def create_app(args):
427
  except Exception as e:
428
  raise HTTPException(status_code=500, detail=str(e))
429
 
430
- @app.delete("/documents", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
431
  async def clear_documents():
432
  try:
433
  rag.text_chunks = []
 
11
  import shutil
12
  import aiofiles
13
  from ascii_colors import trace_exception
 
14
  import os
 
15
 
16
+ from fastapi import Depends, Security
17
  from fastapi.security import APIKeyHeader
 
 
 
18
  from fastapi.middleware.cors import CORSMiddleware
19
 
20
  from starlette.status import HTTP_403_FORBIDDEN
 
21
 
22
 
23
  def parse_args():
 
92
  choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
93
  help="Logging level (default: INFO)",
94
  )
95
+ parser.add_argument(
96
+ "--key",
97
+ type=str,
98
+ help="API key for authentication. This protects lightrag server against unauthorized access",
99
+ default=None,
100
+ )
101
 
102
  return parser.parse_args()
103
 
 
160
  message: str
161
  document_count: int
162
 
163
+
164
  def get_api_key_dependency(api_key: Optional[str]):
165
  if not api_key:
166
  # If no API key is configured, return a dummy dependency that always succeeds
167
  async def no_auth():
168
  return None
169
+
170
  return no_auth
171
+
172
  # If API key is configured, use proper authentication
173
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
174
+
175
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
176
  if not api_key_header_value:
177
  raise HTTPException(
178
+ status_code=HTTP_403_FORBIDDEN, detail="API Key required"
 
179
  )
180
  if api_key_header_value != api_key:
181
  raise HTTPException(
182
+ status_code=HTTP_403_FORBIDDEN, detail="Invalid API Key"
 
183
  )
184
  return api_key_header_value
185
+
186
  return api_key_auth
187
 
188
 
 
194
 
195
  # Check if API key is provided either through env var or args
196
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
197
+
198
  # Initialize FastAPI
199
  app = FastAPI(
200
  title="LightRAG API",
201
+ description="API for querying text using LightRAG with separate storage and input directories"
202
+ + "(With authentication)"
203
+ if api_key
204
+ else "",
205
  version="1.0.0",
206
+ openapi_tags=[{"name": "api"}],
207
  )
208
+
209
  # Add CORS middleware
210
  app.add_middleware(
211
  CORSMiddleware,
 
218
  # Create the optional API key dependency
219
  optional_api_key = get_api_key_dependency(api_key)
220
 
 
221
  # Create working directory if it doesn't exist
222
  Path(args.working_dir).mkdir(parents=True, exist_ok=True)
223
 
 
320
  except Exception as e:
321
  raise HTTPException(status_code=500, detail=str(e))
322
 
323
+ @app.post(
324
+ "/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)]
325
+ )
326
  async def query_text(request: QueryRequest):
327
  try:
328
  response = await rag.aquery(
 
364
  except Exception as e:
365
  raise HTTPException(status_code=500, detail=str(e))
366
 
367
+ @app.post(
368
+ "/documents/text",
369
+ response_model=InsertResponse,
370
+ dependencies=[Depends(optional_api_key)],
371
+ )
372
  async def insert_text(request: InsertTextRequest):
373
  try:
374
  await rag.ainsert(request.text)
 
380
  except Exception as e:
381
  raise HTTPException(status_code=500, detail=str(e))
382
 
383
+ @app.post(
384
+ "/documents/file",
385
+ response_model=InsertResponse,
386
+ dependencies=[Depends(optional_api_key)],
387
+ )
388
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
389
  try:
390
  content = await file.read()
 
408
  except Exception as e:
409
  raise HTTPException(status_code=500, detail=str(e))
410
 
411
+ @app.post(
412
+ "/documents/batch",
413
+ response_model=InsertResponse,
414
+ dependencies=[Depends(optional_api_key)],
415
+ )
416
  async def insert_batch(files: List[UploadFile] = File(...)):
417
  try:
418
  inserted_count = 0
 
442
  except Exception as e:
443
  raise HTTPException(status_code=500, detail=str(e))
444
 
445
+ @app.delete(
446
+ "/documents",
447
+ response_model=InsertResponse,
448
+ dependencies=[Depends(optional_api_key)],
449
+ )
450
  async def clear_documents():
451
  try:
452
  rag.text_chunks = []
lightrag/api/openai_lightrag_server.py CHANGED
@@ -14,19 +14,13 @@ import aiofiles
14
  from ascii_colors import trace_exception
15
  import nest_asyncio
16
 
17
- from fastapi import FastAPI, HTTPException
18
  import os
19
- from typing import Optional
20
 
21
- from fastapi import FastAPI, Depends, HTTPException, Security
22
  from fastapi.security import APIKeyHeader
23
- import os
24
- import argparse
25
- from typing import Optional
26
  from fastapi.middleware.cors import CORSMiddleware
27
 
28
  from starlette.status import HTTP_403_FORBIDDEN
29
- from fastapi import HTTPException
30
 
31
  # Apply nest_asyncio to solve event loop issues
32
  nest_asyncio.apply()
@@ -89,8 +83,12 @@ def parse_args():
89
  help="Logging level (default: INFO)",
90
  )
91
 
92
- parser.add_argument('--key', type=str, help='API key for authentication. This protects lightrag server against unauthorized access', default=None)
93
-
 
 
 
 
94
 
95
  return parser.parse_args()
96
 
@@ -153,29 +151,29 @@ class InsertResponse(BaseModel):
153
  message: str
154
  document_count: int
155
 
 
156
  def get_api_key_dependency(api_key: Optional[str]):
157
  if not api_key:
158
  # If no API key is configured, return a dummy dependency that always succeeds
159
  async def no_auth():
160
  return None
 
161
  return no_auth
162
-
163
  # If API key is configured, use proper authentication
164
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
165
-
166
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
167
  if not api_key_header_value:
168
  raise HTTPException(
169
- status_code=HTTP_403_FORBIDDEN,
170
- detail="API Key required"
171
  )
172
  if api_key_header_value != api_key:
173
  raise HTTPException(
174
- status_code=HTTP_403_FORBIDDEN,
175
- detail="Invalid API Key"
176
  )
177
  return api_key_header_value
178
-
179
  return api_key_auth
180
 
181
 
@@ -192,18 +190,20 @@ def create_app(args):
192
  format="%(levelname)s:%(message)s", level=getattr(logging, args.log_level)
193
  )
194
 
195
-
196
  # Check if API key is provided either through env var or args
197
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
198
-
199
  # Initialize FastAPI
200
  app = FastAPI(
201
  title="LightRAG API",
202
- description="API for querying text using LightRAG with separate storage and input directories"+"(With authentication)" if api_key else "",
 
 
 
203
  version="1.0.0",
204
- openapi_tags=[{"name": "api"}]
205
  )
206
-
207
  # Add CORS middleware
208
  app.add_middleware(
209
  CORSMiddleware,
@@ -335,7 +335,9 @@ def create_app(args):
335
  except Exception as e:
336
  raise HTTPException(status_code=500, detail=str(e))
337
 
338
- @app.post("/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)])
 
 
339
  async def query_text(request: QueryRequest):
340
  try:
341
  response = await rag.aquery(
@@ -377,7 +379,11 @@ def create_app(args):
377
  except Exception as e:
378
  raise HTTPException(status_code=500, detail=str(e))
379
 
380
- @app.post("/documents/text", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
381
  async def insert_text(request: InsertTextRequest):
382
  try:
383
  rag.insert(request.text)
@@ -389,7 +395,11 @@ def create_app(args):
389
  except Exception as e:
390
  raise HTTPException(status_code=500, detail=str(e))
391
 
392
- @app.post("/documents/file", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
393
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
394
  try:
395
  content = await file.read()
@@ -413,7 +423,11 @@ def create_app(args):
413
  except Exception as e:
414
  raise HTTPException(status_code=500, detail=str(e))
415
 
416
- @app.post("/documents/batch", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
417
  async def insert_batch(files: List[UploadFile] = File(...)):
418
  try:
419
  inserted_count = 0
@@ -443,7 +457,11 @@ def create_app(args):
443
  except Exception as e:
444
  raise HTTPException(status_code=500, detail=str(e))
445
 
446
- @app.delete("/documents", response_model=InsertResponse, dependencies=[Depends(optional_api_key)])
 
 
 
 
447
  async def clear_documents():
448
  try:
449
  rag.text_chunks = []
 
14
  from ascii_colors import trace_exception
15
  import nest_asyncio
16
 
 
17
  import os
 
18
 
19
+ from fastapi import Depends, Security
20
  from fastapi.security import APIKeyHeader
 
 
 
21
  from fastapi.middleware.cors import CORSMiddleware
22
 
23
  from starlette.status import HTTP_403_FORBIDDEN
 
24
 
25
  # Apply nest_asyncio to solve event loop issues
26
  nest_asyncio.apply()
 
83
  help="Logging level (default: INFO)",
84
  )
85
 
86
+ parser.add_argument(
87
+ "--key",
88
+ type=str,
89
+ help="API key for authentication. This protects lightrag server against unauthorized access",
90
+ default=None,
91
+ )
92
 
93
  return parser.parse_args()
94
 
 
151
  message: str
152
  document_count: int
153
 
154
+
155
  def get_api_key_dependency(api_key: Optional[str]):
156
  if not api_key:
157
  # If no API key is configured, return a dummy dependency that always succeeds
158
  async def no_auth():
159
  return None
160
+
161
  return no_auth
162
+
163
  # If API key is configured, use proper authentication
164
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
165
+
166
  async def api_key_auth(api_key_header_value: str | None = Security(api_key_header)):
167
  if not api_key_header_value:
168
  raise HTTPException(
169
+ status_code=HTTP_403_FORBIDDEN, detail="API Key required"
 
170
  )
171
  if api_key_header_value != api_key:
172
  raise HTTPException(
173
+ status_code=HTTP_403_FORBIDDEN, detail="Invalid API Key"
 
174
  )
175
  return api_key_header_value
176
+
177
  return api_key_auth
178
 
179
 
 
190
  format="%(levelname)s:%(message)s", level=getattr(logging, args.log_level)
191
  )
192
 
 
193
  # Check if API key is provided either through env var or args
194
  api_key = os.getenv("LIGHTRAG_API_KEY") or args.key
195
+
196
  # Initialize FastAPI
197
  app = FastAPI(
198
  title="LightRAG API",
199
+ description="API for querying text using LightRAG with separate storage and input directories"
200
+ + "(With authentication)"
201
+ if api_key
202
+ else "",
203
  version="1.0.0",
204
+ openapi_tags=[{"name": "api"}],
205
  )
206
+
207
  # Add CORS middleware
208
  app.add_middleware(
209
  CORSMiddleware,
 
335
  except Exception as e:
336
  raise HTTPException(status_code=500, detail=str(e))
337
 
338
+ @app.post(
339
+ "/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)]
340
+ )
341
  async def query_text(request: QueryRequest):
342
  try:
343
  response = await rag.aquery(
 
379
  except Exception as e:
380
  raise HTTPException(status_code=500, detail=str(e))
381
 
382
+ @app.post(
383
+ "/documents/text",
384
+ response_model=InsertResponse,
385
+ dependencies=[Depends(optional_api_key)],
386
+ )
387
  async def insert_text(request: InsertTextRequest):
388
  try:
389
  rag.insert(request.text)
 
395
  except Exception as e:
396
  raise HTTPException(status_code=500, detail=str(e))
397
 
398
+ @app.post(
399
+ "/documents/file",
400
+ response_model=InsertResponse,
401
+ dependencies=[Depends(optional_api_key)],
402
+ )
403
  async def insert_file(file: UploadFile = File(...), description: str = Form(None)):
404
  try:
405
  content = await file.read()
 
423
  except Exception as e:
424
  raise HTTPException(status_code=500, detail=str(e))
425
 
426
+ @app.post(
427
+ "/documents/batch",
428
+ response_model=InsertResponse,
429
+ dependencies=[Depends(optional_api_key)],
430
+ )
431
  async def insert_batch(files: List[UploadFile] = File(...)):
432
  try:
433
  inserted_count = 0
 
457
  except Exception as e:
458
  raise HTTPException(status_code=500, detail=str(e))
459
 
460
+ @app.delete(
461
+ "/documents",
462
+ response_model=InsertResponse,
463
+ dependencies=[Depends(optional_api_key)],
464
+ )
465
  async def clear_documents():
466
  try:
467
  rag.text_chunks = []