Merge branch 'main' into main
Browse files- README.md +1 -0
- examples/lightrag_hf_demo.py +1 -1
- examples/lightrag_ollama_demo.py +1 -1
- examples/lightrag_openai_compatible_demo.py +1 -1
- examples/lightrag_openai_demo.py +1 -1
- examples/lightrag_siliconcloud_demo.py +79 -0
- lightrag/llm.py +53 -1
- requirements.txt +2 -1
README.md
CHANGED
|
@@ -629,6 +629,7 @@ def extract_queries(file_path):
|
|
| 629 |
β βββ lightrag_ollama_demo.py
|
| 630 |
β βββ lightrag_openai_compatible_demo.py
|
| 631 |
β βββ lightrag_openai_demo.py
|
|
|
|
| 632 |
β βββ vram_management_demo.py
|
| 633 |
βββ lightrag
|
| 634 |
β βββ __init__.py
|
|
|
|
| 629 |
β βββ lightrag_ollama_demo.py
|
| 630 |
β βββ lightrag_openai_compatible_demo.py
|
| 631 |
β βββ lightrag_openai_demo.py
|
| 632 |
+
β βββ lightrag_siliconcloud_demo.py
|
| 633 |
β βββ vram_management_demo.py
|
| 634 |
βββ lightrag
|
| 635 |
β βββ __init__.py
|
examples/lightrag_hf_demo.py
CHANGED
|
@@ -30,7 +30,7 @@ rag = LightRAG(
|
|
| 30 |
)
|
| 31 |
|
| 32 |
|
| 33 |
-
with open("./book.txt") as f:
|
| 34 |
rag.insert(f.read())
|
| 35 |
|
| 36 |
# Perform naive search
|
|
|
|
| 30 |
)
|
| 31 |
|
| 32 |
|
| 33 |
+
with open("./book.txt", "r", encoding="utf-8") as f:
|
| 34 |
rag.insert(f.read())
|
| 35 |
|
| 36 |
# Perform naive search
|
examples/lightrag_ollama_demo.py
CHANGED
|
@@ -21,7 +21,7 @@ rag = LightRAG(
|
|
| 21 |
)
|
| 22 |
|
| 23 |
|
| 24 |
-
with open("./book.txt") as f:
|
| 25 |
rag.insert(f.read())
|
| 26 |
|
| 27 |
# Perform naive search
|
|
|
|
| 21 |
)
|
| 22 |
|
| 23 |
|
| 24 |
+
with open("./book.txt", "r", encoding="utf-8") as f:
|
| 25 |
rag.insert(f.read())
|
| 26 |
|
| 27 |
# Perform naive search
|
examples/lightrag_openai_compatible_demo.py
CHANGED
|
@@ -55,7 +55,7 @@ rag = LightRAG(
|
|
| 55 |
)
|
| 56 |
|
| 57 |
|
| 58 |
-
with open("./book.txt") as f:
|
| 59 |
rag.insert(f.read())
|
| 60 |
|
| 61 |
# Perform naive search
|
|
|
|
| 55 |
)
|
| 56 |
|
| 57 |
|
| 58 |
+
with open("./book.txt", "r", encoding="utf-8") as f:
|
| 59 |
rag.insert(f.read())
|
| 60 |
|
| 61 |
# Perform naive search
|
examples/lightrag_openai_demo.py
CHANGED
|
@@ -15,7 +15,7 @@ rag = LightRAG(
|
|
| 15 |
)
|
| 16 |
|
| 17 |
|
| 18 |
-
with open("./book.txt") as f:
|
| 19 |
rag.insert(f.read())
|
| 20 |
|
| 21 |
# Perform naive search
|
|
|
|
| 15 |
)
|
| 16 |
|
| 17 |
|
| 18 |
+
with open("./book.txt", "r", encoding="utf-8") as f:
|
| 19 |
rag.insert(f.read())
|
| 20 |
|
| 21 |
# Perform naive search
|
examples/lightrag_siliconcloud_demo.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import asyncio
|
| 3 |
+
from lightrag import LightRAG, QueryParam
|
| 4 |
+
from lightrag.llm import openai_complete_if_cache, siliconcloud_embedding
|
| 5 |
+
from lightrag.utils import EmbeddingFunc
|
| 6 |
+
import numpy as np
|
| 7 |
+
|
| 8 |
+
WORKING_DIR = "./dickens"
|
| 9 |
+
|
| 10 |
+
if not os.path.exists(WORKING_DIR):
|
| 11 |
+
os.mkdir(WORKING_DIR)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
async def llm_model_func(
|
| 15 |
+
prompt, system_prompt=None, history_messages=[], **kwargs
|
| 16 |
+
) -> str:
|
| 17 |
+
return await openai_complete_if_cache(
|
| 18 |
+
"Qwen/Qwen2.5-7B-Instruct",
|
| 19 |
+
prompt,
|
| 20 |
+
system_prompt=system_prompt,
|
| 21 |
+
history_messages=history_messages,
|
| 22 |
+
api_key=os.getenv("UPSTAGE_API_KEY"),
|
| 23 |
+
base_url="https://api.siliconflow.cn/v1/",
|
| 24 |
+
**kwargs,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
async def embedding_func(texts: list[str]) -> np.ndarray:
|
| 29 |
+
return await siliconcloud_embedding(
|
| 30 |
+
texts,
|
| 31 |
+
model="netease-youdao/bce-embedding-base_v1",
|
| 32 |
+
api_key=os.getenv("UPSTAGE_API_KEY"),
|
| 33 |
+
max_token_size=int(512 * 1.5)
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# function test
|
| 38 |
+
async def test_funcs():
|
| 39 |
+
result = await llm_model_func("How are you?")
|
| 40 |
+
print("llm_model_func: ", result)
|
| 41 |
+
|
| 42 |
+
result = await embedding_func(["How are you?"])
|
| 43 |
+
print("embedding_func: ", result)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
asyncio.run(test_funcs())
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
rag = LightRAG(
|
| 50 |
+
working_dir=WORKING_DIR,
|
| 51 |
+
llm_model_func=llm_model_func,
|
| 52 |
+
embedding_func=EmbeddingFunc(
|
| 53 |
+
embedding_dim=768, max_token_size=512, func=embedding_func
|
| 54 |
+
),
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
with open("./book.txt") as f:
|
| 59 |
+
rag.insert(f.read())
|
| 60 |
+
|
| 61 |
+
# Perform naive search
|
| 62 |
+
print(
|
| 63 |
+
rag.query("What are the top themes in this story?", param=QueryParam(mode="naive"))
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
# Perform local search
|
| 67 |
+
print(
|
| 68 |
+
rag.query("What are the top themes in this story?", param=QueryParam(mode="local"))
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
# Perform global search
|
| 72 |
+
print(
|
| 73 |
+
rag.query("What are the top themes in this story?", param=QueryParam(mode="global"))
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
# Perform hybrid search
|
| 77 |
+
print(
|
| 78 |
+
rag.query("What are the top themes in this story?", param=QueryParam(mode="hybrid"))
|
| 79 |
+
)
|
lightrag/llm.py
CHANGED
|
@@ -2,9 +2,15 @@ import os
|
|
| 2 |
import copy
|
| 3 |
import json
|
| 4 |
import aioboto3
|
|
|
|
| 5 |
import numpy as np
|
| 6 |
import ollama
|
|
|
|
| 7 |
from openai import AsyncOpenAI, APIConnectionError, RateLimitError, Timeout, AsyncAzureOpenAI
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
from tenacity import (
|
| 9 |
retry,
|
| 10 |
stop_after_attempt,
|
|
@@ -365,7 +371,7 @@ async def ollama_model_complete(
|
|
| 365 |
@wrap_embedding_func_with_attrs(embedding_dim=1536, max_token_size=8192)
|
| 366 |
@retry(
|
| 367 |
stop=stop_after_attempt(3),
|
| 368 |
-
wait=wait_exponential(multiplier=1, min=4, max=
|
| 369 |
retry=retry_if_exception_type((RateLimitError, APIConnectionError, Timeout)),
|
| 370 |
)
|
| 371 |
async def openai_embedding(
|
|
@@ -385,6 +391,7 @@ async def openai_embedding(
|
|
| 385 |
)
|
| 386 |
return np.array([dp.embedding for dp in response.data])
|
| 387 |
|
|
|
|
| 388 |
@wrap_embedding_func_with_attrs(embedding_dim=1536, max_token_size=8192)
|
| 389 |
@retry(
|
| 390 |
stop=stop_after_attempt(3),
|
|
@@ -412,6 +419,51 @@ async def azure_openai_embedding(
|
|
| 412 |
return np.array([dp.embedding for dp in response.data])
|
| 413 |
|
| 414 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
# @wrap_embedding_func_with_attrs(embedding_dim=1024, max_token_size=8192)
|
| 416 |
# @retry(
|
| 417 |
# stop=stop_after_attempt(3),
|
|
|
|
| 2 |
import copy
|
| 3 |
import json
|
| 4 |
import aioboto3
|
| 5 |
+
import aiohttp
|
| 6 |
import numpy as np
|
| 7 |
import ollama
|
| 8 |
+
|
| 9 |
from openai import AsyncOpenAI, APIConnectionError, RateLimitError, Timeout, AsyncAzureOpenAI
|
| 10 |
+
|
| 11 |
+
import base64
|
| 12 |
+
import struct
|
| 13 |
+
|
| 14 |
from tenacity import (
|
| 15 |
retry,
|
| 16 |
stop_after_attempt,
|
|
|
|
| 371 |
@wrap_embedding_func_with_attrs(embedding_dim=1536, max_token_size=8192)
|
| 372 |
@retry(
|
| 373 |
stop=stop_after_attempt(3),
|
| 374 |
+
wait=wait_exponential(multiplier=1, min=4, max=60),
|
| 375 |
retry=retry_if_exception_type((RateLimitError, APIConnectionError, Timeout)),
|
| 376 |
)
|
| 377 |
async def openai_embedding(
|
|
|
|
| 391 |
)
|
| 392 |
return np.array([dp.embedding for dp in response.data])
|
| 393 |
|
| 394 |
+
|
| 395 |
@wrap_embedding_func_with_attrs(embedding_dim=1536, max_token_size=8192)
|
| 396 |
@retry(
|
| 397 |
stop=stop_after_attempt(3),
|
|
|
|
| 419 |
return np.array([dp.embedding for dp in response.data])
|
| 420 |
|
| 421 |
|
| 422 |
+
@retry(
|
| 423 |
+
stop=stop_after_attempt(3),
|
| 424 |
+
wait=wait_exponential(multiplier=1, min=4, max=60),
|
| 425 |
+
retry=retry_if_exception_type((RateLimitError, APIConnectionError, Timeout)),
|
| 426 |
+
)
|
| 427 |
+
async def siliconcloud_embedding(
|
| 428 |
+
texts: list[str],
|
| 429 |
+
model: str = "netease-youdao/bce-embedding-base_v1",
|
| 430 |
+
base_url: str = "https://api.siliconflow.cn/v1/embeddings",
|
| 431 |
+
max_token_size: int = 512,
|
| 432 |
+
api_key: str = None,
|
| 433 |
+
) -> np.ndarray:
|
| 434 |
+
if api_key and not api_key.startswith('Bearer '):
|
| 435 |
+
api_key = 'Bearer ' + api_key
|
| 436 |
+
|
| 437 |
+
headers = {
|
| 438 |
+
"Authorization": api_key,
|
| 439 |
+
"Content-Type": "application/json"
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
truncate_texts = [text[0:max_token_size] for text in texts]
|
| 443 |
+
|
| 444 |
+
payload = {
|
| 445 |
+
"model": model,
|
| 446 |
+
"input": truncate_texts,
|
| 447 |
+
"encoding_format": "base64"
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
base64_strings = []
|
| 451 |
+
async with aiohttp.ClientSession() as session:
|
| 452 |
+
async with session.post(base_url, headers=headers, json=payload) as response:
|
| 453 |
+
content = await response.json()
|
| 454 |
+
if 'code' in content:
|
| 455 |
+
raise ValueError(content)
|
| 456 |
+
base64_strings = [item['embedding'] for item in content['data']]
|
| 457 |
+
|
| 458 |
+
embeddings = []
|
| 459 |
+
for string in base64_strings:
|
| 460 |
+
decode_bytes = base64.b64decode(string)
|
| 461 |
+
n = len(decode_bytes) // 4
|
| 462 |
+
float_array = struct.unpack('<' + 'f' * n, decode_bytes)
|
| 463 |
+
embeddings.append(float_array)
|
| 464 |
+
return np.array(embeddings)
|
| 465 |
+
|
| 466 |
+
|
| 467 |
# @wrap_embedding_func_with_attrs(embedding_dim=1024, max_token_size=8192)
|
| 468 |
# @retry(
|
| 469 |
# stop=stop_after_attempt(3),
|
requirements.txt
CHANGED
|
@@ -11,4 +11,5 @@ tiktoken
|
|
| 11 |
torch
|
| 12 |
transformers
|
| 13 |
xxhash
|
| 14 |
-
pyvis
|
|
|
|
|
|
| 11 |
torch
|
| 12 |
transformers
|
| 13 |
xxhash
|
| 14 |
+
pyvis
|
| 15 |
+
aiohttp
|