diff --git a/Dockerfile b/Dockerfile index c52f1ab3..edc6addb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,23 @@ # Build stage -FROM python:3.11-slim as builder +FROM python:3.11-slim AS builder WORKDIR /app +# Install Rust and required build dependencies +RUN apt-get update && apt-get install -y \ + curl \ + build-essential \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* \ + && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && . $HOME/.cargo/env + # Copy only requirements files first to leverage Docker cache COPY requirements.txt . COPY lightrag/api/requirements.txt ./lightrag/api/ # Install dependencies +ENV PATH="/root/.cargo/bin:${PATH}" RUN pip install --user --no-cache-dir -r requirements.txt RUN pip install --user --no-cache-dir -r lightrag/api/requirements.txt @@ -28,6 +38,10 @@ ENV PATH=/root/.local/bin:$PATH # Create necessary directories RUN mkdir -p /app/data/rag_storage /app/data/inputs +# Docker data directories +ENV WORKING_DIR=/app/data/rag_storage +ENV INPUT_DIR=/app/data/inputs + # Expose the default port EXPOSE 9621 diff --git a/README-zh.md b/README-zh.md new file mode 100644 index 00000000..e69de29b diff --git a/lightrag/api/requirements.txt b/lightrag/api/requirements.txt index 0e8e246b..afd76f5b 100644 --- a/lightrag/api/requirements.txt +++ b/lightrag/api/requirements.txt @@ -3,6 +3,7 @@ ascii_colors asyncpg distro fastapi +graspologic>=3.4.1 httpcore httpx jiter diff --git a/lightrag/lightrag.py b/lightrag/lightrag.py index a466e572..a8b11549 100644 --- a/lightrag/lightrag.py +++ b/lightrag/lightrag.py @@ -1843,9 +1843,10 @@ class LightRAG: """ try: # 1. Get current entity information - node_data = await self.chunk_entity_relation_graph.get_node(entity_name) - if not node_data: + node_exists = await self.chunk_entity_relation_graph.has_node(entity_name) + if not node_exists: raise ValueError(f"Entity '{entity_name}' does not exist") + node_data = await self.chunk_entity_relation_graph.get_node(entity_name) # Check if entity is being renamed new_entity_name = updated_data.get("entity_name", entity_name) @@ -1858,7 +1859,7 @@ class LightRAG: "Entity renaming is not allowed. Set allow_rename=True to enable this feature" ) - existing_node = await self.chunk_entity_relation_graph.get_node( + existing_node = await self.chunk_entity_relation_graph.has_node( new_entity_name ) if existing_node: @@ -2040,14 +2041,16 @@ class LightRAG: """ try: # 1. Get current relation information - edge_data = await self.chunk_entity_relation_graph.get_edge( + edge_exists = await self.chunk_entity_relation_graph.has_edge( source_entity, target_entity ) - if not edge_data: + if not edge_exists: raise ValueError( f"Relation from '{source_entity}' to '{target_entity}' does not exist" ) - + edge_data = await self.chunk_entity_relation_graph.get_edge( + source_entity, target_entity + ) # Important: First delete the old relation record from the vector database old_relation_id = compute_mdhash_id( source_entity + target_entity, prefix="rel-" @@ -2156,7 +2159,7 @@ class LightRAG: """ try: # Check if entity already exists - existing_node = await self.chunk_entity_relation_graph.get_node(entity_name) + existing_node = await self.chunk_entity_relation_graph.has_node(entity_name) if existing_node: raise ValueError(f"Entity '{entity_name}' already exists") @@ -2250,7 +2253,7 @@ class LightRAG: raise ValueError(f"Target entity '{target_entity}' does not exist") # Check if relation already exists - existing_edge = await self.chunk_entity_relation_graph.get_edge( + existing_edge = await self.chunk_entity_relation_graph.has_edge( source_entity, target_entity ) if existing_edge: @@ -2383,19 +2386,22 @@ class LightRAG: # 1. Check if all source entities exist source_entities_data = {} for entity_name in source_entities: - node_data = await self.chunk_entity_relation_graph.get_node(entity_name) - if not node_data: + node_exists = await self.chunk_entity_relation_graph.has_node( + entity_name + ) + if not node_exists: raise ValueError(f"Source entity '{entity_name}' does not exist") + node_data = await self.chunk_entity_relation_graph.get_node(entity_name) source_entities_data[entity_name] = node_data # 2. Check if target entity exists and get its data if it does target_exists = await self.chunk_entity_relation_graph.has_node( target_entity ) - target_entity_data = {} + existing_target_entity_data = {} if target_exists: - target_entity_data = await self.chunk_entity_relation_graph.get_node( - target_entity + existing_target_entity_data = ( + await self.chunk_entity_relation_graph.get_node(target_entity) ) logger.info( f"Target entity '{target_entity}' already exists, will merge data" @@ -2404,7 +2410,7 @@ class LightRAG: # 3. Merge entity data merged_entity_data = self._merge_entity_attributes( list(source_entities_data.values()) - + ([target_entity_data] if target_exists else []), + + ([existing_target_entity_data] if target_exists else []), merge_strategy, ) diff --git a/lightrag/llm/openai.py b/lightrag/llm/openai.py index 70aa0ceb..555fea90 100644 --- a/lightrag/llm/openai.py +++ b/lightrag/llm/openai.py @@ -123,18 +123,21 @@ async def openai_complete_if_cache( async def inner(): try: + _content = "" async for chunk in response: content = chunk.choices[0].delta.content if content is None: continue if r"\u" in content: content = safe_unicode_decode(content.encode("utf-8")) - yield content + _content += content + return _content except Exception as e: logger.error(f"Error in stream response: {str(e)}") raise - return inner() + response_content = await inner() + return response_content else: if ( diff --git a/lightrag_webui/env.development.smaple b/lightrag_webui/env.development.smaple new file mode 100644 index 00000000..080cf95f --- /dev/null +++ b/lightrag_webui/env.development.smaple @@ -0,0 +1,2 @@ +# Development environment configuration +VITE_BACKEND_URL=/api diff --git a/lightrag_webui/env.local.sample b/lightrag_webui/env.local.sample new file mode 100644 index 00000000..0f2c293c --- /dev/null +++ b/lightrag_webui/env.local.sample @@ -0,0 +1,3 @@ +VITE_BACKEND_URL=http://localhost:9621 +VITE_API_PROXY=true +VITE_API_ENDPOINTS=/api,/documents,/graphs,/graph,/health,/query,/docs,/openapi.json