Merge remote-tracking branch 'origin/main' into api_improvment
# Conflicts: # lightrag/api/lightrag_server.py
This commit is contained in:
@@ -61,7 +61,10 @@ from ..kg.tidb_impl import (
|
||||
)
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv(override=True)
|
||||
try:
|
||||
load_dotenv(override=True)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to load .env file: {e}")
|
||||
|
||||
# Initialize config parser
|
||||
config = configparser.ConfigParser()
|
||||
@@ -131,8 +134,8 @@ def get_env_value(env_key: str, default: Any, value_type: type = str) -> Any:
|
||||
if value is None:
|
||||
return default
|
||||
|
||||
if isinstance(value_type, bool):
|
||||
return value.lower() in ("true", "1", "yes")
|
||||
if value_type is bool:
|
||||
return value.lower() in ("true", "1", "yes", "t", "on")
|
||||
try:
|
||||
return value_type(value)
|
||||
except ValueError:
|
||||
@@ -234,6 +237,8 @@ def display_splash_screen(args: argparse.Namespace) -> None:
|
||||
ASCIIColors.yellow(f"{ollama_server_infos.LIGHTRAG_MODEL}")
|
||||
ASCIIColors.white(" ├─ Log Level: ", end="")
|
||||
ASCIIColors.yellow(f"{args.log_level}")
|
||||
ASCIIColors.white(" ├─ Verbose Debug: ", end="")
|
||||
ASCIIColors.yellow(f"{args.verbose}")
|
||||
ASCIIColors.white(" └─ Timeout: ", end="")
|
||||
ASCIIColors.yellow(f"{args.timeout if args.timeout else 'None (infinite)'}")
|
||||
|
||||
@@ -252,10 +257,8 @@ def display_splash_screen(args: argparse.Namespace) -> None:
|
||||
ASCIIColors.yellow(f"{protocol}://localhost:{args.port}/docs")
|
||||
ASCIIColors.white(" ├─ Alternative Documentation (local): ", end="")
|
||||
ASCIIColors.yellow(f"{protocol}://localhost:{args.port}/redoc")
|
||||
ASCIIColors.white(" ├─ WebUI (local): ", end="")
|
||||
ASCIIColors.white(" └─ WebUI (local): ", end="")
|
||||
ASCIIColors.yellow(f"{protocol}://localhost:{args.port}/webui")
|
||||
ASCIIColors.white(" └─ Graph Viewer (local): ", end="")
|
||||
ASCIIColors.yellow(f"{protocol}://localhost:{args.port}/graph-viewer")
|
||||
|
||||
ASCIIColors.yellow("\n📝 Note:")
|
||||
ASCIIColors.white(""" Since the server is running on 0.0.0.0:
|
||||
@@ -565,6 +568,13 @@ def parse_args() -> argparse.Namespace:
|
||||
help="Prefix of the namespace",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--verbose",
|
||||
type=bool,
|
||||
default=get_env_value("VERBOSE", False, bool),
|
||||
help="Verbose debug output(default: from env or false)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# conver relative path to absolute path
|
||||
@@ -776,6 +786,23 @@ class InsertResponse(BaseModel):
|
||||
message: str = Field(description="Message describing the operation result")
|
||||
|
||||
|
||||
class DocStatusResponse(BaseModel):
|
||||
id: str
|
||||
content_summary: str
|
||||
content_length: int
|
||||
status: DocStatus
|
||||
created_at: str
|
||||
updated_at: str
|
||||
chunks_count: Optional[int] = None
|
||||
error: Optional[str] = None
|
||||
metadata: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
class DocsStatusesResponse(BaseModel):
|
||||
statuses: Dict[DocStatus, List[DocStatusResponse]] = {}
|
||||
|
||||
|
||||
|
||||
def get_api_key_dependency(api_key: Optional[str]):
|
||||
if not api_key:
|
||||
# If no API key is configured, return a dummy dependency that always succeeds
|
||||
@@ -809,6 +836,11 @@ temp_prefix = "__tmp_" # prefix for temporary files
|
||||
|
||||
|
||||
def create_app(args):
|
||||
# Initialize verbose debug setting
|
||||
from lightrag.utils import set_verbose_debug
|
||||
|
||||
set_verbose_debug(args.verbose)
|
||||
|
||||
global global_top_k
|
||||
global_top_k = args.top_k # save top_k from args
|
||||
|
||||
@@ -1806,20 +1838,57 @@ def create_app(args):
|
||||
app.include_router(ollama_api.router, prefix="/api")
|
||||
|
||||
@app.get("/documents", dependencies=[Depends(optional_api_key)])
|
||||
async def documents():
|
||||
"""Get current system status"""
|
||||
return doc_manager.indexed_files
|
||||
async def documents() -> DocsStatusesResponse:
|
||||
"""
|
||||
Get documents statuses
|
||||
Returns:
|
||||
DocsStatusesResponse: A response object containing a dictionary where keys are DocStatus
|
||||
and values are lists of DocStatusResponse objects representing documents in each status category.
|
||||
"""
|
||||
try:
|
||||
statuses = (
|
||||
DocStatus.PENDING,
|
||||
DocStatus.PROCESSING,
|
||||
DocStatus.PROCESSED,
|
||||
DocStatus.FAILED,
|
||||
)
|
||||
|
||||
tasks = [rag.get_docs_by_status(status) for status in statuses]
|
||||
results: List[Dict[str, DocProcessingStatus]] = await asyncio.gather(*tasks)
|
||||
|
||||
response = DocsStatusesResponse()
|
||||
|
||||
for idx, result in enumerate(results):
|
||||
status = statuses[idx]
|
||||
for doc_id, doc_status in result.items():
|
||||
if status not in response.statuses:
|
||||
response.statuses[status] = []
|
||||
response.statuses[status].append(
|
||||
DocStatusResponse(
|
||||
id=doc_id,
|
||||
content_summary=doc_status.content_summary,
|
||||
content_length=doc_status.content_length,
|
||||
status=doc_status.status,
|
||||
created_at=doc_status.created_at,
|
||||
updated_at=doc_status.updated_at,
|
||||
chunks_count=doc_status.chunks_count,
|
||||
error=doc_status.error,
|
||||
metadata=doc_status.metadata,
|
||||
)
|
||||
)
|
||||
return response
|
||||
except Exception as e:
|
||||
logging.error(f"Error GET /documents: {str(e)}")
|
||||
logging.error(traceback.format_exc())
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get("/health", dependencies=[Depends(optional_api_key)])
|
||||
async def get_status():
|
||||
"""Get current system status"""
|
||||
files = doc_manager.scan_directory()
|
||||
return {
|
||||
"status": "healthy",
|
||||
"working_directory": str(args.working_dir),
|
||||
"input_directory": str(args.input_dir),
|
||||
"indexed_files": [str(f) for f in files],
|
||||
"indexed_files_count": len(files),
|
||||
"configuration": {
|
||||
# LLM configuration binding/host address (if applicable)/model (if applicable)
|
||||
"llm_binding": args.llm_binding,
|
||||
@@ -1838,17 +1907,9 @@ def create_app(args):
|
||||
}
|
||||
|
||||
# Webui mount webui/index.html
|
||||
webui_dir = Path(__file__).parent / "webui"
|
||||
app.mount(
|
||||
"/graph-viewer",
|
||||
StaticFiles(directory=webui_dir, html=True),
|
||||
name="webui",
|
||||
)
|
||||
|
||||
# Serve the static files
|
||||
static_dir = Path(__file__).parent / "static"
|
||||
static_dir = Path(__file__).parent / "webui"
|
||||
static_dir.mkdir(exist_ok=True)
|
||||
app.mount("/webui", StaticFiles(directory=static_dir, html=True), name="static")
|
||||
app.mount("/webui", StaticFiles(directory=static_dir, html=True), name="webui")
|
||||
|
||||
return app
|
||||
|
||||
|
Reference in New Issue
Block a user