yangdx commited on
Commit
b28bdc6
·
2 Parent(s): 1d1b99c c6d8b34

Merge branch 'main' into feat-node-expand

Browse files
Dockerfile CHANGED
@@ -1,13 +1,23 @@
1
  # Build stage
2
- FROM python:3.11-slim as builder
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
- node_data = await self.chunk_entity_relation_graph.get_node(entity_name)
1847
- if not node_data:
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.get_node(
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
- edge_data = await self.chunk_entity_relation_graph.get_edge(
2044
  source_entity, target_entity
2045
  )
2046
- if not edge_data:
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.get_node(entity_name)
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.get_edge(
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
- node_data = await self.chunk_entity_relation_graph.get_node(entity_name)
2387
- if not node_data:
 
 
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
- target_entity_data = {}
2396
  if target_exists:
2397
- target_entity_data = await self.chunk_entity_relation_graph.get_node(
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
- + ([target_entity_data] if target_exists else []),
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
- yield content
 
133
  except Exception as e:
134
  logger.error(f"Error in stream response: {str(e)}")
135
  raise
136
 
137
- return inner()
 
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 (