Merge branch 'main' into feat-node-expand
Browse files- Dockerfile +15 -1
- README-zh.md +0 -0
- lightrag/api/requirements.txt +1 -0
- lightrag/lightrag.py +20 -14
- lightrag/llm/openai.py +5 -2
Dockerfile
CHANGED
@@ -1,13 +1,23 @@
|
|
1 |
# Build stage
|
2 |
-
FROM python:3.11-slim
|
3 |
|
4 |
WORKDIR /app
|
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
# Copy only requirements files first to leverage Docker cache
|
7 |
COPY requirements.txt .
|
8 |
COPY lightrag/api/requirements.txt ./lightrag/api/
|
9 |
|
10 |
# Install dependencies
|
|
|
11 |
RUN pip install --user --no-cache-dir -r requirements.txt
|
12 |
RUN pip install --user --no-cache-dir -r lightrag/api/requirements.txt
|
13 |
|
@@ -28,6 +38,10 @@ ENV PATH=/root/.local/bin:$PATH
|
|
28 |
# Create necessary directories
|
29 |
RUN mkdir -p /app/data/rag_storage /app/data/inputs
|
30 |
|
|
|
|
|
|
|
|
|
31 |
# Expose the default port
|
32 |
EXPOSE 9621
|
33 |
|
|
|
1 |
# Build stage
|
2 |
+
FROM python:3.11-slim AS builder
|
3 |
|
4 |
WORKDIR /app
|
5 |
|
6 |
+
# Install Rust and required build dependencies
|
7 |
+
RUN apt-get update && apt-get install -y \
|
8 |
+
curl \
|
9 |
+
build-essential \
|
10 |
+
pkg-config \
|
11 |
+
&& rm -rf /var/lib/apt/lists/* \
|
12 |
+
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
|
13 |
+
&& . $HOME/.cargo/env
|
14 |
+
|
15 |
# Copy only requirements files first to leverage Docker cache
|
16 |
COPY requirements.txt .
|
17 |
COPY lightrag/api/requirements.txt ./lightrag/api/
|
18 |
|
19 |
# Install dependencies
|
20 |
+
ENV PATH="/root/.cargo/bin:${PATH}"
|
21 |
RUN pip install --user --no-cache-dir -r requirements.txt
|
22 |
RUN pip install --user --no-cache-dir -r lightrag/api/requirements.txt
|
23 |
|
|
|
38 |
# Create necessary directories
|
39 |
RUN mkdir -p /app/data/rag_storage /app/data/inputs
|
40 |
|
41 |
+
# Docker data directories
|
42 |
+
ENV WORKING_DIR=/app/data/rag_storage
|
43 |
+
ENV INPUT_DIR=/app/data/inputs
|
44 |
+
|
45 |
# Expose the default port
|
46 |
EXPOSE 9621
|
47 |
|
README-zh.md
ADDED
File without changes
|
lightrag/api/requirements.txt
CHANGED
@@ -3,6 +3,7 @@ ascii_colors
|
|
3 |
asyncpg
|
4 |
distro
|
5 |
fastapi
|
|
|
6 |
httpcore
|
7 |
httpx
|
8 |
jiter
|
|
|
3 |
asyncpg
|
4 |
distro
|
5 |
fastapi
|
6 |
+
graspologic>=3.4.1
|
7 |
httpcore
|
8 |
httpx
|
9 |
jiter
|
lightrag/lightrag.py
CHANGED
@@ -1843,9 +1843,10 @@ class LightRAG:
|
|
1843 |
"""
|
1844 |
try:
|
1845 |
# 1. Get current entity information
|
1846 |
-
|
1847 |
-
if not
|
1848 |
raise ValueError(f"Entity '{entity_name}' does not exist")
|
|
|
1849 |
|
1850 |
# Check if entity is being renamed
|
1851 |
new_entity_name = updated_data.get("entity_name", entity_name)
|
@@ -1858,7 +1859,7 @@ class LightRAG:
|
|
1858 |
"Entity renaming is not allowed. Set allow_rename=True to enable this feature"
|
1859 |
)
|
1860 |
|
1861 |
-
existing_node = await self.chunk_entity_relation_graph.
|
1862 |
new_entity_name
|
1863 |
)
|
1864 |
if existing_node:
|
@@ -2040,14 +2041,16 @@ class LightRAG:
|
|
2040 |
"""
|
2041 |
try:
|
2042 |
# 1. Get current relation information
|
2043 |
-
|
2044 |
source_entity, target_entity
|
2045 |
)
|
2046 |
-
if not
|
2047 |
raise ValueError(
|
2048 |
f"Relation from '{source_entity}' to '{target_entity}' does not exist"
|
2049 |
)
|
2050 |
-
|
|
|
|
|
2051 |
# Important: First delete the old relation record from the vector database
|
2052 |
old_relation_id = compute_mdhash_id(
|
2053 |
source_entity + target_entity, prefix="rel-"
|
@@ -2156,7 +2159,7 @@ class LightRAG:
|
|
2156 |
"""
|
2157 |
try:
|
2158 |
# Check if entity already exists
|
2159 |
-
existing_node = await self.chunk_entity_relation_graph.
|
2160 |
if existing_node:
|
2161 |
raise ValueError(f"Entity '{entity_name}' already exists")
|
2162 |
|
@@ -2250,7 +2253,7 @@ class LightRAG:
|
|
2250 |
raise ValueError(f"Target entity '{target_entity}' does not exist")
|
2251 |
|
2252 |
# Check if relation already exists
|
2253 |
-
existing_edge = await self.chunk_entity_relation_graph.
|
2254 |
source_entity, target_entity
|
2255 |
)
|
2256 |
if existing_edge:
|
@@ -2383,19 +2386,22 @@ class LightRAG:
|
|
2383 |
# 1. Check if all source entities exist
|
2384 |
source_entities_data = {}
|
2385 |
for entity_name in source_entities:
|
2386 |
-
|
2387 |
-
|
|
|
|
|
2388 |
raise ValueError(f"Source entity '{entity_name}' does not exist")
|
|
|
2389 |
source_entities_data[entity_name] = node_data
|
2390 |
|
2391 |
# 2. Check if target entity exists and get its data if it does
|
2392 |
target_exists = await self.chunk_entity_relation_graph.has_node(
|
2393 |
target_entity
|
2394 |
)
|
2395 |
-
|
2396 |
if target_exists:
|
2397 |
-
|
2398 |
-
target_entity
|
2399 |
)
|
2400 |
logger.info(
|
2401 |
f"Target entity '{target_entity}' already exists, will merge data"
|
@@ -2404,7 +2410,7 @@ class LightRAG:
|
|
2404 |
# 3. Merge entity data
|
2405 |
merged_entity_data = self._merge_entity_attributes(
|
2406 |
list(source_entities_data.values())
|
2407 |
-
+ ([
|
2408 |
merge_strategy,
|
2409 |
)
|
2410 |
|
|
|
1843 |
"""
|
1844 |
try:
|
1845 |
# 1. Get current entity information
|
1846 |
+
node_exists = await self.chunk_entity_relation_graph.has_node(entity_name)
|
1847 |
+
if not node_exists:
|
1848 |
raise ValueError(f"Entity '{entity_name}' does not exist")
|
1849 |
+
node_data = await self.chunk_entity_relation_graph.get_node(entity_name)
|
1850 |
|
1851 |
# Check if entity is being renamed
|
1852 |
new_entity_name = updated_data.get("entity_name", entity_name)
|
|
|
1859 |
"Entity renaming is not allowed. Set allow_rename=True to enable this feature"
|
1860 |
)
|
1861 |
|
1862 |
+
existing_node = await self.chunk_entity_relation_graph.has_node(
|
1863 |
new_entity_name
|
1864 |
)
|
1865 |
if existing_node:
|
|
|
2041 |
"""
|
2042 |
try:
|
2043 |
# 1. Get current relation information
|
2044 |
+
edge_exists = await self.chunk_entity_relation_graph.has_edge(
|
2045 |
source_entity, target_entity
|
2046 |
)
|
2047 |
+
if not edge_exists:
|
2048 |
raise ValueError(
|
2049 |
f"Relation from '{source_entity}' to '{target_entity}' does not exist"
|
2050 |
)
|
2051 |
+
edge_data = await self.chunk_entity_relation_graph.get_edge(
|
2052 |
+
source_entity, target_entity
|
2053 |
+
)
|
2054 |
# Important: First delete the old relation record from the vector database
|
2055 |
old_relation_id = compute_mdhash_id(
|
2056 |
source_entity + target_entity, prefix="rel-"
|
|
|
2159 |
"""
|
2160 |
try:
|
2161 |
# Check if entity already exists
|
2162 |
+
existing_node = await self.chunk_entity_relation_graph.has_node(entity_name)
|
2163 |
if existing_node:
|
2164 |
raise ValueError(f"Entity '{entity_name}' already exists")
|
2165 |
|
|
|
2253 |
raise ValueError(f"Target entity '{target_entity}' does not exist")
|
2254 |
|
2255 |
# Check if relation already exists
|
2256 |
+
existing_edge = await self.chunk_entity_relation_graph.has_edge(
|
2257 |
source_entity, target_entity
|
2258 |
)
|
2259 |
if existing_edge:
|
|
|
2386 |
# 1. Check if all source entities exist
|
2387 |
source_entities_data = {}
|
2388 |
for entity_name in source_entities:
|
2389 |
+
node_exists = await self.chunk_entity_relation_graph.has_node(
|
2390 |
+
entity_name
|
2391 |
+
)
|
2392 |
+
if not node_exists:
|
2393 |
raise ValueError(f"Source entity '{entity_name}' does not exist")
|
2394 |
+
node_data = await self.chunk_entity_relation_graph.get_node(entity_name)
|
2395 |
source_entities_data[entity_name] = node_data
|
2396 |
|
2397 |
# 2. Check if target entity exists and get its data if it does
|
2398 |
target_exists = await self.chunk_entity_relation_graph.has_node(
|
2399 |
target_entity
|
2400 |
)
|
2401 |
+
existing_target_entity_data = {}
|
2402 |
if target_exists:
|
2403 |
+
existing_target_entity_data = (
|
2404 |
+
await self.chunk_entity_relation_graph.get_node(target_entity)
|
2405 |
)
|
2406 |
logger.info(
|
2407 |
f"Target entity '{target_entity}' already exists, will merge data"
|
|
|
2410 |
# 3. Merge entity data
|
2411 |
merged_entity_data = self._merge_entity_attributes(
|
2412 |
list(source_entities_data.values())
|
2413 |
+
+ ([existing_target_entity_data] if target_exists else []),
|
2414 |
merge_strategy,
|
2415 |
)
|
2416 |
|
lightrag/llm/openai.py
CHANGED
@@ -123,18 +123,21 @@ async def openai_complete_if_cache(
|
|
123 |
|
124 |
async def inner():
|
125 |
try:
|
|
|
126 |
async for chunk in response:
|
127 |
content = chunk.choices[0].delta.content
|
128 |
if content is None:
|
129 |
continue
|
130 |
if r"\u" in content:
|
131 |
content = safe_unicode_decode(content.encode("utf-8"))
|
132 |
-
|
|
|
133 |
except Exception as e:
|
134 |
logger.error(f"Error in stream response: {str(e)}")
|
135 |
raise
|
136 |
|
137 |
-
|
|
|
138 |
|
139 |
else:
|
140 |
if (
|
|
|
123 |
|
124 |
async def inner():
|
125 |
try:
|
126 |
+
_content = ""
|
127 |
async for chunk in response:
|
128 |
content = chunk.choices[0].delta.content
|
129 |
if content is None:
|
130 |
continue
|
131 |
if r"\u" in content:
|
132 |
content = safe_unicode_decode(content.encode("utf-8"))
|
133 |
+
_content += content
|
134 |
+
return _content
|
135 |
except Exception as e:
|
136 |
logger.error(f"Error in stream response: {str(e)}")
|
137 |
raise
|
138 |
|
139 |
+
response_content = await inner()
|
140 |
+
return response_content
|
141 |
|
142 |
else:
|
143 |
if (
|