lightrag / tests /test_graph_storage.py
gzdaniel's picture
Merge branch 'main' into add-Memgraph-graph-db
917d3f4
#!/usr/bin/env python
"""
้€š็”จๅ›พๅญ˜ๅ‚จๆต‹่ฏ•็จ‹ๅบ
่ฏฅ็จ‹ๅบๆ นๆฎ.envไธญ็š„LIGHTRAG_GRAPH_STORAGE้…็ฝฎ้€‰ๆ‹ฉไฝฟ็”จ็š„ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹๏ผŒ
ๅนถๅฏนๅ…ถ่ฟ›่กŒๅŸบๆœฌๆ“ไฝœๅ’Œ้ซ˜็บงๆ“ไฝœ็š„ๆต‹่ฏ•ใ€‚
ๆ”ฏๆŒ็š„ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹ๅŒ…ๆ‹ฌ๏ผš
- NetworkXStorage
- Neo4JStorage
- MongoDBStorage
- PGGraphStorage
- MemgraphStorage
"""
import asyncio
import os
import sys
import importlib
import numpy as np
from dotenv import load_dotenv
from ascii_colors import ASCIIColors
# ๆทปๅŠ ้กน็›ฎๆ น็›ฎๅฝ•ๅˆฐPython่ทฏๅพ„
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lightrag.types import KnowledgeGraph
from lightrag.kg import (
STORAGE_IMPLEMENTATIONS,
STORAGE_ENV_REQUIREMENTS,
STORAGES,
verify_storage_implementation,
)
from lightrag.kg.shared_storage import initialize_share_data
from lightrag.constants import GRAPH_FIELD_SEP
# ๆจกๆ‹Ÿ็š„ๅตŒๅ…ฅๅ‡ฝๆ•ฐ๏ผŒ่ฟ”ๅ›ž้šๆœบๅ‘้‡
async def mock_embedding_func(texts):
return np.random.rand(len(texts), 10) # ่ฟ”ๅ›ž10็ปด้šๆœบๅ‘้‡
def check_env_file():
"""
ๆฃ€ๆŸฅ.envๆ–‡ไปถๆ˜ฏๅฆๅญ˜ๅœจ๏ผŒๅฆ‚ๆžœไธๅญ˜ๅœจๅˆ™ๅ‘ๅ‡บ่ญฆๅ‘Š
่ฟ”ๅ›žTrue่กจ็คบๅบ”่ฏฅ็ปง็ปญๆ‰ง่กŒ๏ผŒFalse่กจ็คบๅบ”่ฏฅ้€€ๅ‡บ
"""
if not os.path.exists(".env"):
warning_msg = "่ญฆๅ‘Š: ๅฝ“ๅ‰็›ฎๅฝ•ไธญๆฒกๆœ‰ๆ‰พๅˆฐ.envๆ–‡ไปถ๏ผŒ่ฟ™ๅฏ่ƒฝไผšๅฝฑๅ“ๅญ˜ๅ‚จ้…็ฝฎ็š„ๅŠ ่ฝฝใ€‚"
ASCIIColors.yellow(warning_msg)
# ๆฃ€ๆŸฅๆ˜ฏๅฆๅœจไบคไบ’ๅผ็ปˆ็ซฏไธญ่ฟ่กŒ
if sys.stdin.isatty():
response = input("ๆ˜ฏๅฆ็ปง็ปญๆ‰ง่กŒ? (yes/no): ")
if response.lower() != "yes":
ASCIIColors.red("ๆต‹่ฏ•็จ‹ๅบๅทฒๅ–ๆถˆ")
return False
return True
async def initialize_graph_storage():
"""
ๆ นๆฎ็Žฏๅขƒๅ˜้‡ๅˆๅง‹ๅŒ–็›ธๅบ”็š„ๅ›พๅญ˜ๅ‚จๅฎžไพ‹
่ฟ”ๅ›žๅˆๅง‹ๅŒ–็š„ๅญ˜ๅ‚จๅฎžไพ‹
"""
# ไปŽ็Žฏๅขƒๅ˜้‡ไธญ่Žทๅ–ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹
graph_storage_type = os.getenv("LIGHTRAG_GRAPH_STORAGE", "NetworkXStorage")
# ้ชŒ่ฏๅญ˜ๅ‚จ็ฑปๅž‹ๆ˜ฏๅฆๆœ‰ๆ•ˆ
try:
verify_storage_implementation("GRAPH_STORAGE", graph_storage_type)
except ValueError as e:
ASCIIColors.red(f"้”™่ฏฏ: {str(e)}")
ASCIIColors.yellow(
f"ๆ”ฏๆŒ็š„ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹: {', '.join(STORAGE_IMPLEMENTATIONS['GRAPH_STORAGE']['implementations'])}"
)
return None
# ๆฃ€ๆŸฅๆ‰€้œ€็š„็Žฏๅขƒๅ˜้‡
required_env_vars = STORAGE_ENV_REQUIREMENTS.get(graph_storage_type, [])
missing_env_vars = [var for var in required_env_vars if not os.getenv(var)]
if missing_env_vars:
ASCIIColors.red(
f"้”™่ฏฏ: {graph_storage_type} ้œ€่ฆไปฅไธ‹็Žฏๅขƒๅ˜้‡๏ผŒไฝ†ๆœช่ฎพ็ฝฎ: {', '.join(missing_env_vars)}"
)
return None
# ๅŠจๆ€ๅฏผๅ…ฅ็›ธๅบ”็š„ๆจกๅ—
module_path = STORAGES.get(graph_storage_type)
if not module_path:
ASCIIColors.red(f"้”™่ฏฏ: ๆœชๆ‰พๅˆฐ {graph_storage_type} ็š„ๆจกๅ—่ทฏๅพ„")
return None
try:
module = importlib.import_module(module_path, package="lightrag")
storage_class = getattr(module, graph_storage_type)
except (ImportError, AttributeError) as e:
ASCIIColors.red(f"้”™่ฏฏ: ๅฏผๅ…ฅ {graph_storage_type} ๅคฑ่ดฅ: {str(e)}")
return None
# ๅˆๅง‹ๅŒ–ๅญ˜ๅ‚จๅฎžไพ‹
global_config = {
"embedding_batch_num": 10, # ๆ‰นๅค„็†ๅคงๅฐ
"vector_db_storage_cls_kwargs": {
"cosine_better_than_threshold": 0.5 # ไฝ™ๅผฆ็›ธไผผๅบฆ้˜ˆๅ€ผ
},
"working_dir": os.environ.get("WORKING_DIR", "./rag_storage"), # ๅทฅไฝœ็›ฎๅฝ•
}
# ๅฆ‚ๆžœไฝฟ็”จ NetworkXStorage๏ผŒ้œ€่ฆๅ…ˆๅˆๅง‹ๅŒ– shared_storage
if graph_storage_type == "NetworkXStorage":
initialize_share_data() # ไฝฟ็”จๅ•่ฟ›็จ‹ๆจกๅผ
try:
storage = storage_class(
namespace="test_graph",
global_config=global_config,
embedding_func=mock_embedding_func,
)
# ๅˆๅง‹ๅŒ–่ฟžๆŽฅ
await storage.initialize()
return storage
except Exception as e:
ASCIIColors.red(f"้”™่ฏฏ: ๅˆๅง‹ๅŒ– {graph_storage_type} ๅคฑ่ดฅ: {str(e)}")
return None
async def test_graph_basic(storage):
"""
ๆต‹่ฏ•ๅ›พๆ•ฐๆฎๅบ“็š„ๅŸบๆœฌๆ“ไฝœ:
1. ไฝฟ็”จ upsert_node ๆ’ๅ…ฅไธคไธช่Š‚็‚น
2. ไฝฟ็”จ upsert_edge ๆ’ๅ…ฅไธ€ๆก่ฟžๆŽฅไธคไธช่Š‚็‚น็š„่พน
3. ไฝฟ็”จ get_node ่ฏปๅ–ไธ€ไธช่Š‚็‚น
4. ไฝฟ็”จ get_edge ่ฏปๅ–ไธ€ๆก่พน
"""
try:
# 1. ๆ’ๅ…ฅ็ฌฌไธ€ไธช่Š‚็‚น
node1_id = "ไบบๅทฅๆ™บ่ƒฝ"
node1_data = {
"entity_id": node1_id,
"description": "ไบบๅทฅๆ™บ่ƒฝๆ˜ฏ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไผๅ›พไบ†่งฃๆ™บ่ƒฝ็š„ๅฎž่ดจ๏ผŒๅนถ็”Ÿไบงๅ‡บไธ€็งๆ–ฐ็š„่ƒฝไปฅไบบ็ฑปๆ™บ่ƒฝ็›ธไผผ็š„ๆ–นๅผๅšๅ‡บๅๅบ”็š„ๆ™บ่ƒฝๆœบๅ™จใ€‚",
"keywords": "AI,ๆœบๅ™จๅญฆไน ,ๆทฑๅบฆๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น1: {node1_id}")
await storage.upsert_node(node1_id, node1_data)
# 2. ๆ’ๅ…ฅ็ฌฌไบŒไธช่Š‚็‚น
node2_id = "ๆœบๅ™จๅญฆไน "
node2_data = {
"entity_id": node2_id,
"description": "ๆœบๅ™จๅญฆไน ๆ˜ฏไบบๅทฅๆ™บ่ƒฝ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไฝฟ็”จ็ปŸ่ฎกๅญฆๆ–นๆณ•่ฎฉ่ฎก็ฎ—ๆœบ็ณป็ปŸๅœจไธ่ขซๆ˜Ž็กฎ็ผ–็จ‹็š„ๆƒ…ๅ†ตไธ‹ไนŸ่ƒฝๅคŸๅญฆไน ใ€‚",
"keywords": "็›‘็ฃๅญฆไน ,ๆ— ็›‘็ฃๅญฆไน ,ๅผบๅŒ–ๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น2: {node2_id}")
await storage.upsert_node(node2_id, node2_data)
# 3. ๆ’ๅ…ฅ่ฟžๆŽฅ่พน
edge_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ไบบๅทฅๆ™บ่ƒฝ้ข†ๅŸŸๅŒ…ๅซๆœบๅ™จๅญฆไน ่ฟ™ไธชๅญ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน: {node1_id} -> {node2_id}")
await storage.upsert_edge(node1_id, node2_id, edge_data)
# 4. ่ฏปๅ–่Š‚็‚นๅฑžๆ€ง
print(f"่ฏปๅ–่Š‚็‚นๅฑžๆ€ง: {node1_id}")
node1_props = await storage.get_node(node1_id)
if node1_props:
print(f"ๆˆๅŠŸ่ฏปๅ–่Š‚็‚นๅฑžๆ€ง: {node1_id}")
print(f"่Š‚็‚นๆ่ฟฐ: {node1_props.get('description', 'ๆ— ๆ่ฟฐ')}")
print(f"่Š‚็‚น็ฑปๅž‹: {node1_props.get('entity_type', 'ๆ— ็ฑปๅž‹')}")
print(f"่Š‚็‚นๅ…ณ้”ฎ่ฏ: {node1_props.get('keywords', 'ๆ— ๅ…ณ้”ฎ่ฏ')}")
# ้ชŒ่ฏ่ฟ”ๅ›ž็š„ๅฑžๆ€งๆ˜ฏๅฆๆญฃ็กฎ
assert (
node1_props.get("entity_id") == node1_id
), f"่Š‚็‚นIDไธๅŒน้…: ๆœŸๆœ› {node1_id}, ๅฎž้™… {node1_props.get('entity_id')}"
assert (
node1_props.get("description") == node1_data["description"]
), "่Š‚็‚นๆ่ฟฐไธๅŒน้…"
assert (
node1_props.get("entity_type") == node1_data["entity_type"]
), "่Š‚็‚น็ฑปๅž‹ไธๅŒน้…"
else:
print(f"่ฏปๅ–่Š‚็‚นๅฑžๆ€งๅคฑ่ดฅ: {node1_id}")
assert False, f"ๆœช่ƒฝ่ฏปๅ–่Š‚็‚นๅฑžๆ€ง: {node1_id}"
# 5. ่ฏปๅ–่พนๅฑžๆ€ง
print(f"่ฏปๅ–่พนๅฑžๆ€ง: {node1_id} -> {node2_id}")
edge_props = await storage.get_edge(node1_id, node2_id)
if edge_props:
print(f"ๆˆๅŠŸ่ฏปๅ–่พนๅฑžๆ€ง: {node1_id} -> {node2_id}")
print(f"่พนๅ…ณ็ณป: {edge_props.get('relationship', 'ๆ— ๅ…ณ็ณป')}")
print(f"่พนๆ่ฟฐ: {edge_props.get('description', 'ๆ— ๆ่ฟฐ')}")
print(f"่พนๆƒ้‡: {edge_props.get('weight', 'ๆ— ๆƒ้‡')}")
# ้ชŒ่ฏ่ฟ”ๅ›ž็š„ๅฑžๆ€งๆ˜ฏๅฆๆญฃ็กฎ
assert (
edge_props.get("relationship") == edge_data["relationship"]
), "่พนๅ…ณ็ณปไธๅŒน้…"
assert (
edge_props.get("description") == edge_data["description"]
), "่พนๆ่ฟฐไธๅŒน้…"
assert edge_props.get("weight") == edge_data["weight"], "่พนๆƒ้‡ไธๅŒน้…"
else:
print(f"่ฏปๅ–่พนๅฑžๆ€งๅคฑ่ดฅ: {node1_id} -> {node2_id}")
assert False, f"ๆœช่ƒฝ่ฏปๅ–่พนๅฑžๆ€ง: {node1_id} -> {node2_id}"
# 5.1 ้ชŒ่ฏๆ— ๅ‘ๅ›พ็‰นๆ€ง - ่ฏปๅ–ๅๅ‘่พนๅฑžๆ€ง
print(f"่ฏปๅ–ๅๅ‘่พนๅฑžๆ€ง: {node2_id} -> {node1_id}")
reverse_edge_props = await storage.get_edge(node2_id, node1_id)
if reverse_edge_props:
print(f"ๆˆๅŠŸ่ฏปๅ–ๅๅ‘่พนๅฑžๆ€ง: {node2_id} -> {node1_id}")
print(f"ๅๅ‘่พนๅ…ณ็ณป: {reverse_edge_props.get('relationship', 'ๆ— ๅ…ณ็ณป')}")
print(f"ๅๅ‘่พนๆ่ฟฐ: {reverse_edge_props.get('description', 'ๆ— ๆ่ฟฐ')}")
print(f"ๅๅ‘่พนๆƒ้‡: {reverse_edge_props.get('weight', 'ๆ— ๆƒ้‡')}")
# ้ชŒ่ฏๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งๆ˜ฏๅฆ็›ธๅŒ
assert (
edge_props == reverse_edge_props
), "ๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธไธ€่‡ด๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธ€่‡ด")
else:
print(f"่ฏปๅ–ๅๅ‘่พนๅฑžๆ€งๅคฑ่ดฅ: {node2_id} -> {node1_id}")
assert (
False
), f"ๆœช่ƒฝ่ฏปๅ–ๅๅ‘่พนๅฑžๆ€ง: {node2_id} -> {node1_id}๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๅŸบๆœฌๆต‹่ฏ•ๅฎŒๆˆ๏ผŒๆ•ฐๆฎๅทฒไฟ็•™ๅœจๆ•ฐๆฎๅบ“ไธญ")
return True
except Exception as e:
ASCIIColors.red(f"ๆต‹่ฏ•่ฟ‡็จ‹ไธญๅ‘็”Ÿ้”™่ฏฏ: {str(e)}")
return False
async def test_graph_advanced(storage):
"""
ๆต‹่ฏ•ๅ›พๆ•ฐๆฎๅบ“็š„้ซ˜็บงๆ“ไฝœ:
1. ไฝฟ็”จ node_degree ่Žทๅ–่Š‚็‚น็š„ๅบฆๆ•ฐ
2. ไฝฟ็”จ edge_degree ่Žทๅ–่พน็š„ๅบฆๆ•ฐ
3. ไฝฟ็”จ get_node_edges ่Žทๅ–่Š‚็‚น็š„ๆ‰€ๆœ‰่พน
4. ไฝฟ็”จ get_all_labels ่Žทๅ–ๆ‰€ๆœ‰ๆ ‡็ญพ
5. ไฝฟ็”จ get_knowledge_graph ่Žทๅ–็Ÿฅ่ฏ†ๅ›พ่ฐฑ
6. ไฝฟ็”จ delete_node ๅˆ ้™ค่Š‚็‚น
7. ไฝฟ็”จ remove_nodes ๆ‰น้‡ๅˆ ้™ค่Š‚็‚น
8. ไฝฟ็”จ remove_edges ๅˆ ้™ค่พน
9. ไฝฟ็”จ drop ๆธ…็†ๆ•ฐๆฎ
"""
try:
# 1. ๆ’ๅ…ฅๆต‹่ฏ•ๆ•ฐๆฎ
# ๆ’ๅ…ฅ่Š‚็‚น1: ไบบๅทฅๆ™บ่ƒฝ
node1_id = "ไบบๅทฅๆ™บ่ƒฝ"
node1_data = {
"entity_id": node1_id,
"description": "ไบบๅทฅๆ™บ่ƒฝๆ˜ฏ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไผๅ›พไบ†่งฃๆ™บ่ƒฝ็š„ๅฎž่ดจ๏ผŒๅนถ็”Ÿไบงๅ‡บไธ€็งๆ–ฐ็š„่ƒฝไปฅไบบ็ฑปๆ™บ่ƒฝ็›ธไผผ็š„ๆ–นๅผๅšๅ‡บๅๅบ”็š„ๆ™บ่ƒฝๆœบๅ™จใ€‚",
"keywords": "AI,ๆœบๅ™จๅญฆไน ,ๆทฑๅบฆๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น1: {node1_id}")
await storage.upsert_node(node1_id, node1_data)
# ๆ’ๅ…ฅ่Š‚็‚น2: ๆœบๅ™จๅญฆไน 
node2_id = "ๆœบๅ™จๅญฆไน "
node2_data = {
"entity_id": node2_id,
"description": "ๆœบๅ™จๅญฆไน ๆ˜ฏไบบๅทฅๆ™บ่ƒฝ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไฝฟ็”จ็ปŸ่ฎกๅญฆๆ–นๆณ•่ฎฉ่ฎก็ฎ—ๆœบ็ณป็ปŸๅœจไธ่ขซๆ˜Ž็กฎ็ผ–็จ‹็š„ๆƒ…ๅ†ตไธ‹ไนŸ่ƒฝๅคŸๅญฆไน ใ€‚",
"keywords": "็›‘็ฃๅญฆไน ,ๆ— ็›‘็ฃๅญฆไน ,ๅผบๅŒ–ๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น2: {node2_id}")
await storage.upsert_node(node2_id, node2_data)
# ๆ’ๅ…ฅ่Š‚็‚น3: ๆทฑๅบฆๅญฆไน 
node3_id = "ๆทฑๅบฆๅญฆไน "
node3_data = {
"entity_id": node3_id,
"description": "ๆทฑๅบฆๅญฆไน ๆ˜ฏๆœบๅ™จๅญฆไน ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไฝฟ็”จๅคšๅฑ‚็ฅž็ป็ฝ‘็ปœๆฅๆจกๆ‹Ÿไบบ่„‘็š„ๅญฆไน ่ฟ‡็จ‹ใ€‚",
"keywords": "็ฅž็ป็ฝ‘็ปœ,CNN,RNN",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น3: {node3_id}")
await storage.upsert_node(node3_id, node3_data)
# ๆ’ๅ…ฅ่พน1: ไบบๅทฅๆ™บ่ƒฝ -> ๆœบๅ™จๅญฆไน 
edge1_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ไบบๅทฅๆ™บ่ƒฝ้ข†ๅŸŸๅŒ…ๅซๆœบๅ™จๅญฆไน ่ฟ™ไธชๅญ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน1: {node1_id} -> {node2_id}")
await storage.upsert_edge(node1_id, node2_id, edge1_data)
# ๆ’ๅ…ฅ่พน2: ๆœบๅ™จๅญฆไน  -> ๆทฑๅบฆๅญฆไน 
edge2_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ๆœบๅ™จๅญฆไน ้ข†ๅŸŸๅŒ…ๅซๆทฑๅบฆๅญฆไน ่ฟ™ไธชๅญ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน2: {node2_id} -> {node3_id}")
await storage.upsert_edge(node2_id, node3_id, edge2_data)
# 2. ๆต‹่ฏ• node_degree - ่Žทๅ–่Š‚็‚น็š„ๅบฆๆ•ฐ
print(f"== ๆต‹่ฏ• node_degree: {node1_id}")
node1_degree = await storage.node_degree(node1_id)
print(f"่Š‚็‚น {node1_id} ็š„ๅบฆๆ•ฐ: {node1_degree}")
assert node1_degree == 1, f"่Š‚็‚น {node1_id} ็š„ๅบฆๆ•ฐๅบ”ไธบ1๏ผŒๅฎž้™…ไธบ {node1_degree}"
# 2.1 ๆต‹่ฏ•ๆ‰€ๆœ‰่Š‚็‚น็š„ๅบฆๆ•ฐ
print("== ๆต‹่ฏ•ๆ‰€ๆœ‰่Š‚็‚น็š„ๅบฆๆ•ฐ")
node2_degree = await storage.node_degree(node2_id)
node3_degree = await storage.node_degree(node3_id)
print(f"่Š‚็‚น {node2_id} ็š„ๅบฆๆ•ฐ: {node2_degree}")
print(f"่Š‚็‚น {node3_id} ็š„ๅบฆๆ•ฐ: {node3_degree}")
assert node2_degree == 2, f"่Š‚็‚น {node2_id} ็š„ๅบฆๆ•ฐๅบ”ไธบ2๏ผŒๅฎž้™…ไธบ {node2_degree}"
assert node3_degree == 1, f"่Š‚็‚น {node3_id} ็š„ๅบฆๆ•ฐๅบ”ไธบ1๏ผŒๅฎž้™…ไธบ {node3_degree}"
# 3. ๆต‹่ฏ• edge_degree - ่Žทๅ–่พน็š„ๅบฆๆ•ฐ
print(f"== ๆต‹่ฏ• edge_degree: {node1_id} -> {node2_id}")
edge_degree = await storage.edge_degree(node1_id, node2_id)
print(f"่พน {node1_id} -> {node2_id} ็š„ๅบฆๆ•ฐ: {edge_degree}")
assert (
edge_degree == 3
), f"่พน {node1_id} -> {node2_id} ็š„ๅบฆๆ•ฐๅบ”ไธบ3๏ผŒๅฎž้™…ไธบ {edge_degree}"
# 3.1 ๆต‹่ฏ•ๅๅ‘่พน็š„ๅบฆๆ•ฐ - ้ชŒ่ฏๆ— ๅ‘ๅ›พ็‰นๆ€ง
print(f"== ๆต‹่ฏ•ๅๅ‘่พน็š„ๅบฆๆ•ฐ: {node2_id} -> {node1_id}")
reverse_edge_degree = await storage.edge_degree(node2_id, node1_id)
print(f"ๅๅ‘่พน {node2_id} -> {node1_id} ็š„ๅบฆๆ•ฐ: {reverse_edge_degree}")
assert (
edge_degree == reverse_edge_degree
), "ๆญฃๅ‘่พนๅ’Œๅๅ‘่พน็š„ๅบฆๆ•ฐไธไธ€่‡ด๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆญฃๅ‘่พนๅ’Œๅๅ‘่พน็š„ๅบฆๆ•ฐไธ€่‡ด")
# 4. ๆต‹่ฏ• get_node_edges - ่Žทๅ–่Š‚็‚น็š„ๆ‰€ๆœ‰่พน
print(f"== ๆต‹่ฏ• get_node_edges: {node2_id}")
node2_edges = await storage.get_node_edges(node2_id)
print(f"่Š‚็‚น {node2_id} ็š„ๆ‰€ๆœ‰่พน: {node2_edges}")
assert (
len(node2_edges) == 2
), f"่Š‚็‚น {node2_id} ๅบ”ๆœ‰2ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(node2_edges)}"
# 4.1 ้ชŒ่ฏ่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("== ้ชŒ่ฏ่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ๆฃ€ๆŸฅๆ˜ฏๅฆๅŒ…ๅซไธŽnode1ๅ’Œnode3็š„่ฟžๆŽฅๅ…ณ็ณป๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
has_connection_with_node1 = False
has_connection_with_node3 = False
for edge in node2_edges:
# ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ไธŽnode1็š„่ฟžๆŽฅ๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
if (edge[0] == node1_id and edge[1] == node2_id) or (
edge[0] == node2_id and edge[1] == node1_id
):
has_connection_with_node1 = True
# ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ไธŽnode3็š„่ฟžๆŽฅ๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
if (edge[0] == node2_id and edge[1] == node3_id) or (
edge[0] == node3_id and edge[1] == node2_id
):
has_connection_with_node3 = True
assert (
has_connection_with_node1
), f"่Š‚็‚น {node2_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node1_id} ็š„่ฟžๆŽฅ"
assert (
has_connection_with_node3
), f"่Š‚็‚น {node2_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node3_id} ็š„่ฟžๆŽฅ"
print(f"ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผš่Š‚็‚น {node2_id} ็š„่พนๅˆ—่กจๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน")
# 5. ๆต‹่ฏ• get_all_labels - ่Žทๅ–ๆ‰€ๆœ‰ๆ ‡็ญพ
print("== ๆต‹่ฏ• get_all_labels")
all_labels = await storage.get_all_labels()
print(f"ๆ‰€ๆœ‰ๆ ‡็ญพ: {all_labels}")
assert len(all_labels) == 3, f"ๅบ”ๆœ‰3ไธชๆ ‡็ญพ๏ผŒๅฎž้™…ๆœ‰ {len(all_labels)}"
assert node1_id in all_labels, f"{node1_id} ๅบ”ๅœจๆ ‡็ญพๅˆ—่กจไธญ"
assert node2_id in all_labels, f"{node2_id} ๅบ”ๅœจๆ ‡็ญพๅˆ—่กจไธญ"
assert node3_id in all_labels, f"{node3_id} ๅบ”ๅœจๆ ‡็ญพๅˆ—่กจไธญ"
# 6. ๆต‹่ฏ• get_knowledge_graph - ่Žทๅ–็Ÿฅ่ฏ†ๅ›พ่ฐฑ
print("== ๆต‹่ฏ• get_knowledge_graph")
kg = await storage.get_knowledge_graph("*", max_depth=2, max_nodes=10)
print(f"็Ÿฅ่ฏ†ๅ›พ่ฐฑ่Š‚็‚นๆ•ฐ: {len(kg.nodes)}")
print(f"็Ÿฅ่ฏ†ๅ›พ่ฐฑ่พนๆ•ฐ: {len(kg.edges)}")
assert isinstance(kg, KnowledgeGraph), "่ฟ”ๅ›ž็ป“ๆžœๅบ”ไธบ KnowledgeGraph ็ฑปๅž‹"
assert len(kg.nodes) == 3, f"็Ÿฅ่ฏ†ๅ›พ่ฐฑๅบ”ๆœ‰3ไธช่Š‚็‚น๏ผŒๅฎž้™…ๆœ‰ {len(kg.nodes)}"
assert len(kg.edges) == 2, f"็Ÿฅ่ฏ†ๅ›พ่ฐฑๅบ”ๆœ‰2ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(kg.edges)}"
# 7. ๆต‹่ฏ• delete_node - ๅˆ ้™ค่Š‚็‚น
print(f"== ๆต‹่ฏ• delete_node: {node3_id}")
await storage.delete_node(node3_id)
node3_props = await storage.get_node(node3_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏข่Š‚็‚นๅฑžๆ€ง {node3_id}: {node3_props}")
assert node3_props is None, f"่Š‚็‚น {node3_id} ๅบ”ๅทฒ่ขซๅˆ ้™ค"
# ้‡ๆ–ฐๆ’ๅ…ฅ่Š‚็‚น3็”จไบŽๅŽ็ปญๆต‹่ฏ•
await storage.upsert_node(node3_id, node3_data)
await storage.upsert_edge(node2_id, node3_id, edge2_data)
# 8. ๆต‹่ฏ• remove_edges - ๅˆ ้™ค่พน
print(f"== ๆต‹่ฏ• remove_edges: {node2_id} -> {node3_id}")
await storage.remove_edges([(node2_id, node3_id)])
edge_props = await storage.get_edge(node2_id, node3_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏข่พนๅฑžๆ€ง {node2_id} -> {node3_id}: {edge_props}")
assert edge_props is None, f"่พน {node2_id} -> {node3_id} ๅบ”ๅทฒ่ขซๅˆ ้™ค"
# 8.1 ้ชŒ่ฏๅˆ ้™ค่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print(f"== ้ชŒ่ฏๅˆ ้™ค่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง: {node3_id} -> {node2_id}")
reverse_edge_props = await storage.get_edge(node3_id, node2_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏขๅๅ‘่พนๅฑžๆ€ง {node3_id} -> {node2_id}: {reverse_edge_props}")
assert (
reverse_edge_props is None
), f"ๅๅ‘่พน {node3_id} -> {node2_id} ไนŸๅบ”่ขซๅˆ ้™ค๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๅˆ ้™คไธ€ไธชๆ–นๅ‘็š„่พนๅŽ๏ผŒๅๅ‘่พนไนŸ่ขซๅˆ ้™ค")
# 9. ๆต‹่ฏ• remove_nodes - ๆ‰น้‡ๅˆ ้™ค่Š‚็‚น
print(f"== ๆต‹่ฏ• remove_nodes: [{node2_id}, {node3_id}]")
await storage.remove_nodes([node2_id, node3_id])
node2_props = await storage.get_node(node2_id)
node3_props = await storage.get_node(node3_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏข่Š‚็‚นๅฑžๆ€ง {node2_id}: {node2_props}")
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏข่Š‚็‚นๅฑžๆ€ง {node3_id}: {node3_props}")
assert node2_props is None, f"่Š‚็‚น {node2_id} ๅบ”ๅทฒ่ขซๅˆ ้™ค"
assert node3_props is None, f"่Š‚็‚น {node3_id} ๅบ”ๅทฒ่ขซๅˆ ้™ค"
print("\n้ซ˜็บงๆต‹่ฏ•ๅฎŒๆˆ")
return True
except Exception as e:
ASCIIColors.red(f"ๆต‹่ฏ•่ฟ‡็จ‹ไธญๅ‘็”Ÿ้”™่ฏฏ: {str(e)}")
return False
async def test_graph_batch_operations(storage):
"""
ๆต‹่ฏ•ๅ›พๆ•ฐๆฎๅบ“็š„ๆ‰น้‡ๆ“ไฝœ:
1. ไฝฟ็”จ get_nodes_batch ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๅฑžๆ€ง
2. ไฝฟ็”จ node_degrees_batch ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๅบฆๆ•ฐ
3. ไฝฟ็”จ edge_degrees_batch ๆ‰น้‡่Žทๅ–ๅคšไธช่พน็š„ๅบฆๆ•ฐ
4. ไฝฟ็”จ get_edges_batch ๆ‰น้‡่Žทๅ–ๅคšไธช่พน็š„ๅฑžๆ€ง
5. ไฝฟ็”จ get_nodes_edges_batch ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๆ‰€ๆœ‰่พน
"""
try:
chunk1_id = "1"
chunk2_id = "2"
chunk3_id = "3"
# 1. ๆ’ๅ…ฅๆต‹่ฏ•ๆ•ฐๆฎ
# ๆ’ๅ…ฅ่Š‚็‚น1: ไบบๅทฅๆ™บ่ƒฝ
node1_id = "ไบบๅทฅๆ™บ่ƒฝ"
node1_data = {
"entity_id": node1_id,
"description": "ไบบๅทฅๆ™บ่ƒฝๆ˜ฏ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไผๅ›พไบ†่งฃๆ™บ่ƒฝ็š„ๅฎž่ดจ๏ผŒๅนถ็”Ÿไบงๅ‡บไธ€็งๆ–ฐ็š„่ƒฝไปฅไบบ็ฑปๆ™บ่ƒฝ็›ธไผผ็š„ๆ–นๅผๅšๅ‡บๅๅบ”็š„ๆ™บ่ƒฝๆœบๅ™จใ€‚",
"keywords": "AI,ๆœบๅ™จๅญฆไน ,ๆทฑๅบฆๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk1_id, chunk2_id]),
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น1: {node1_id}")
await storage.upsert_node(node1_id, node1_data)
# ๆ’ๅ…ฅ่Š‚็‚น2: ๆœบๅ™จๅญฆไน 
node2_id = "ๆœบๅ™จๅญฆไน "
node2_data = {
"entity_id": node2_id,
"description": "ๆœบๅ™จๅญฆไน ๆ˜ฏไบบๅทฅๆ™บ่ƒฝ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไฝฟ็”จ็ปŸ่ฎกๅญฆๆ–นๆณ•่ฎฉ่ฎก็ฎ—ๆœบ็ณป็ปŸๅœจไธ่ขซๆ˜Ž็กฎ็ผ–็จ‹็š„ๆƒ…ๅ†ตไธ‹ไนŸ่ƒฝๅคŸๅญฆไน ใ€‚",
"keywords": "็›‘็ฃๅญฆไน ,ๆ— ็›‘็ฃๅญฆไน ,ๅผบๅŒ–ๅญฆไน ",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk2_id, chunk3_id]),
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น2: {node2_id}")
await storage.upsert_node(node2_id, node2_data)
# ๆ’ๅ…ฅ่Š‚็‚น3: ๆทฑๅบฆๅญฆไน 
node3_id = "ๆทฑๅบฆๅญฆไน "
node3_data = {
"entity_id": node3_id,
"description": "ๆทฑๅบฆๅญฆไน ๆ˜ฏๆœบๅ™จๅญฆไน ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒๅฎƒไฝฟ็”จๅคšๅฑ‚็ฅž็ป็ฝ‘็ปœๆฅๆจกๆ‹Ÿไบบ่„‘็š„ๅญฆไน ่ฟ‡็จ‹ใ€‚",
"keywords": "็ฅž็ป็ฝ‘็ปœ,CNN,RNN",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk3_id]),
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น3: {node3_id}")
await storage.upsert_node(node3_id, node3_data)
# ๆ’ๅ…ฅ่Š‚็‚น4: ่‡ช็„ถ่ฏญ่จ€ๅค„็†
node4_id = "่‡ช็„ถ่ฏญ่จ€ๅค„็†"
node4_data = {
"entity_id": node4_id,
"description": "่‡ช็„ถ่ฏญ่จ€ๅค„็†ๆ˜ฏไบบๅทฅๆ™บ่ƒฝ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒไธ“ๆณจไบŽไฝฟ่ฎก็ฎ—ๆœบ็†่งฃๅ’Œๅค„็†ไบบ็ฑป่ฏญ่จ€ใ€‚",
"keywords": "NLP,ๆ–‡ๆœฌๅˆ†ๆž,่ฏญ่จ€ๆจกๅž‹",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น4: {node4_id}")
await storage.upsert_node(node4_id, node4_data)
# ๆ’ๅ…ฅ่Š‚็‚น5: ่ฎก็ฎ—ๆœบ่ง†่ง‰
node5_id = "่ฎก็ฎ—ๆœบ่ง†่ง‰"
node5_data = {
"entity_id": node5_id,
"description": "่ฎก็ฎ—ๆœบ่ง†่ง‰ๆ˜ฏไบบๅทฅๆ™บ่ƒฝ็š„ไธ€ไธชๅˆ†ๆ”ฏ๏ผŒไธ“ๆณจไบŽไฝฟ่ฎก็ฎ—ๆœบ่ƒฝๅคŸไปŽๅ›พๅƒๆˆ–่ง†้ข‘ไธญ่Žทๅ–ไฟกๆฏใ€‚",
"keywords": "CV,ๅ›พๅƒ่ฏ†ๅˆซ,็›ฎๆ ‡ๆฃ€ๆต‹",
"entity_type": "ๆŠ€ๆœฏ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น5: {node5_id}")
await storage.upsert_node(node5_id, node5_data)
# ๆ’ๅ…ฅ่พน1: ไบบๅทฅๆ™บ่ƒฝ -> ๆœบๅ™จๅญฆไน 
edge1_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ไบบๅทฅๆ™บ่ƒฝ้ข†ๅŸŸๅŒ…ๅซๆœบๅ™จๅญฆไน ่ฟ™ไธชๅญ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk1_id, chunk2_id]),
}
print(f"ๆ’ๅ…ฅ่พน1: {node1_id} -> {node2_id}")
await storage.upsert_edge(node1_id, node2_id, edge1_data)
# ๆ’ๅ…ฅ่พน2: ๆœบๅ™จๅญฆไน  -> ๆทฑๅบฆๅญฆไน 
edge2_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ๆœบๅ™จๅญฆไน ้ข†ๅŸŸๅŒ…ๅซๆทฑๅบฆๅญฆไน ่ฟ™ไธชๅญ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk2_id, chunk3_id]),
}
print(f"ๆ’ๅ…ฅ่พน2: {node2_id} -> {node3_id}")
await storage.upsert_edge(node2_id, node3_id, edge2_data)
# ๆ’ๅ…ฅ่พน3: ไบบๅทฅๆ™บ่ƒฝ -> ่‡ช็„ถ่ฏญ่จ€ๅค„็†
edge3_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ไบบๅทฅๆ™บ่ƒฝ้ข†ๅŸŸๅŒ…ๅซ่‡ช็„ถ่ฏญ่จ€ๅค„็†่ฟ™ไธชๅญ้ข†ๅŸŸ",
"source_id": GRAPH_FIELD_SEP.join([chunk3_id]),
}
print(f"ๆ’ๅ…ฅ่พน3: {node1_id} -> {node4_id}")
await storage.upsert_edge(node1_id, node4_id, edge3_data)
# ๆ’ๅ…ฅ่พน4: ไบบๅทฅๆ™บ่ƒฝ -> ่ฎก็ฎ—ๆœบ่ง†่ง‰
edge4_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "ไบบๅทฅๆ™บ่ƒฝ้ข†ๅŸŸๅŒ…ๅซ่ฎก็ฎ—ๆœบ่ง†่ง‰่ฟ™ไธชๅญ้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน4: {node1_id} -> {node5_id}")
await storage.upsert_edge(node1_id, node5_id, edge4_data)
# ๆ’ๅ…ฅ่พน5: ๆทฑๅบฆๅญฆไน  -> ่‡ช็„ถ่ฏญ่จ€ๅค„็†
edge5_data = {
"relationship": "ๅบ”็”จไบŽ",
"weight": 0.8,
"description": "ๆทฑๅบฆๅญฆไน ๆŠ€ๆœฏๅบ”็”จไบŽ่‡ช็„ถ่ฏญ่จ€ๅค„็†้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน5: {node3_id} -> {node4_id}")
await storage.upsert_edge(node3_id, node4_id, edge5_data)
# ๆ’ๅ…ฅ่พน6: ๆทฑๅบฆๅญฆไน  -> ่ฎก็ฎ—ๆœบ่ง†่ง‰
edge6_data = {
"relationship": "ๅบ”็”จไบŽ",
"weight": 0.8,
"description": "ๆทฑๅบฆๅญฆไน ๆŠ€ๆœฏๅบ”็”จไบŽ่ฎก็ฎ—ๆœบ่ง†่ง‰้ข†ๅŸŸ",
}
print(f"ๆ’ๅ…ฅ่พน6: {node3_id} -> {node5_id}")
await storage.upsert_edge(node3_id, node5_id, edge6_data)
# 2. ๆต‹่ฏ• get_nodes_batch - ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๅฑžๆ€ง
print("== ๆต‹่ฏ• get_nodes_batch")
node_ids = [node1_id, node2_id, node3_id]
nodes_dict = await storage.get_nodes_batch(node_ids)
print(f"ๆ‰น้‡่Žทๅ–่Š‚็‚นๅฑžๆ€ง็ป“ๆžœ: {nodes_dict.keys()}")
assert len(nodes_dict) == 3, f"ๅบ”่ฟ”ๅ›ž3ไธช่Š‚็‚น๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(nodes_dict)} ไธช"
assert node1_id in nodes_dict, f"{node1_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert node2_id in nodes_dict, f"{node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert node3_id in nodes_dict, f"{node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
nodes_dict[node1_id]["description"] == node1_data["description"]
), f"{node1_id} ๆ่ฟฐไธๅŒน้…"
assert (
nodes_dict[node2_id]["description"] == node2_data["description"]
), f"{node2_id} ๆ่ฟฐไธๅŒน้…"
assert (
nodes_dict[node3_id]["description"] == node3_data["description"]
), f"{node3_id} ๆ่ฟฐไธๅŒน้…"
# 3. ๆต‹่ฏ• node_degrees_batch - ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๅบฆๆ•ฐ
print("== ๆต‹่ฏ• node_degrees_batch")
node_degrees = await storage.node_degrees_batch(node_ids)
print(f"ๆ‰น้‡่Žทๅ–่Š‚็‚นๅบฆๆ•ฐ็ป“ๆžœ: {node_degrees}")
assert (
len(node_degrees) == 3
), f"ๅบ”่ฟ”ๅ›ž3ไธช่Š‚็‚น็š„ๅบฆๆ•ฐ๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(node_degrees)} ไธช"
assert node1_id in node_degrees, f"{node1_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert node2_id in node_degrees, f"{node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert node3_id in node_degrees, f"{node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
node_degrees[node1_id] == 3
), f"{node1_id} ๅบฆๆ•ฐๅบ”ไธบ3๏ผŒๅฎž้™…ไธบ {node_degrees[node1_id]}"
assert (
node_degrees[node2_id] == 2
), f"{node2_id} ๅบฆๆ•ฐๅบ”ไธบ2๏ผŒๅฎž้™…ไธบ {node_degrees[node2_id]}"
assert (
node_degrees[node3_id] == 3
), f"{node3_id} ๅบฆๆ•ฐๅบ”ไธบ3๏ผŒๅฎž้™…ไธบ {node_degrees[node3_id]}"
# 4. ๆต‹่ฏ• edge_degrees_batch - ๆ‰น้‡่Žทๅ–ๅคšไธช่พน็š„ๅบฆๆ•ฐ
print("== ๆต‹่ฏ• edge_degrees_batch")
edges = [(node1_id, node2_id), (node2_id, node3_id), (node3_id, node4_id)]
edge_degrees = await storage.edge_degrees_batch(edges)
print(f"ๆ‰น้‡่Žทๅ–่พนๅบฆๆ•ฐ็ป“ๆžœ: {edge_degrees}")
assert (
len(edge_degrees) == 3
), f"ๅบ”่ฟ”ๅ›ž3ๆก่พน็š„ๅบฆๆ•ฐ๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(edge_degrees)} ๆก"
assert (
node1_id,
node2_id,
) in edge_degrees, f"่พน {node1_id} -> {node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
node2_id,
node3_id,
) in edge_degrees, f"่พน {node2_id} -> {node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
node3_id,
node4_id,
) in edge_degrees, f"่พน {node3_id} -> {node4_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
# ้ชŒ่ฏ่พน็š„ๅบฆๆ•ฐๆ˜ฏๅฆๆญฃ็กฎ๏ผˆๆบ่Š‚็‚นๅบฆๆ•ฐ + ็›ฎๆ ‡่Š‚็‚นๅบฆๆ•ฐ๏ผ‰
assert (
edge_degrees[(node1_id, node2_id)] == 5
), f"่พน {node1_id} -> {node2_id} ๅบฆๆ•ฐๅบ”ไธบ5๏ผŒๅฎž้™…ไธบ {edge_degrees[(node1_id, node2_id)]}"
assert (
edge_degrees[(node2_id, node3_id)] == 5
), f"่พน {node2_id} -> {node3_id} ๅบฆๆ•ฐๅบ”ไธบ5๏ผŒๅฎž้™…ไธบ {edge_degrees[(node2_id, node3_id)]}"
assert (
edge_degrees[(node3_id, node4_id)] == 5
), f"่พน {node3_id} -> {node4_id} ๅบฆๆ•ฐๅบ”ไธบ5๏ผŒๅฎž้™…ไธบ {edge_degrees[(node3_id, node4_id)]}"
# 5. ๆต‹่ฏ• get_edges_batch - ๆ‰น้‡่Žทๅ–ๅคšไธช่พน็š„ๅฑžๆ€ง
print("== ๆต‹่ฏ• get_edges_batch")
# ๅฐ†ๅ…ƒ็ป„ๅˆ—่กจ่ฝฌๆขไธบNeo4j้ฃŽๆ ผ็š„ๅญ—ๅ…ธๅˆ—่กจ
edge_dicts = [{"src": src, "tgt": tgt} for src, tgt in edges]
edges_dict = await storage.get_edges_batch(edge_dicts)
print(f"ๆ‰น้‡่Žทๅ–่พนๅฑžๆ€ง็ป“ๆžœ: {edges_dict.keys()}")
assert len(edges_dict) == 3, f"ๅบ”่ฟ”ๅ›ž3ๆก่พน็š„ๅฑžๆ€ง๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(edges_dict)} ๆก"
assert (
node1_id,
node2_id,
) in edges_dict, f"่พน {node1_id} -> {node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
node2_id,
node3_id,
) in edges_dict, f"่พน {node2_id} -> {node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
node3_id,
node4_id,
) in edges_dict, f"่พน {node3_id} -> {node4_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
edges_dict[(node1_id, node2_id)]["relationship"]
== edge1_data["relationship"]
), f"่พน {node1_id} -> {node2_id} ๅ…ณ็ณปไธๅŒน้…"
assert (
edges_dict[(node2_id, node3_id)]["relationship"]
== edge2_data["relationship"]
), f"่พน {node2_id} -> {node3_id} ๅ…ณ็ณปไธๅŒน้…"
assert (
edges_dict[(node3_id, node4_id)]["relationship"]
== edge5_data["relationship"]
), f"่พน {node3_id} -> {node4_id} ๅ…ณ็ณปไธๅŒน้…"
# 5.1 ๆต‹่ฏ•ๅๅ‘่พน็š„ๆ‰น้‡่Žทๅ– - ้ชŒ่ฏๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("== ๆต‹่ฏ•ๅๅ‘่พน็š„ๆ‰น้‡่Žทๅ–")
# ๅˆ›ๅปบๅๅ‘่พน็š„ๅญ—ๅ…ธๅˆ—่กจ
reverse_edge_dicts = [{"src": tgt, "tgt": src} for src, tgt in edges]
reverse_edges_dict = await storage.get_edges_batch(reverse_edge_dicts)
print(f"ๆ‰น้‡่Žทๅ–ๅๅ‘่พนๅฑžๆ€ง็ป“ๆžœ: {reverse_edges_dict.keys()}")
assert (
len(reverse_edges_dict) == 3
), f"ๅบ”่ฟ”ๅ›ž3ๆกๅๅ‘่พน็š„ๅฑžๆ€ง๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(reverse_edges_dict)} ๆก"
# ้ชŒ่ฏๆญฃๅ‘ๅ’Œๅๅ‘่พน็š„ๅฑžๆ€งๆ˜ฏๅฆไธ€่‡ด
for (src, tgt), props in edges_dict.items():
assert (
tgt,
src,
) in reverse_edges_dict, f"ๅๅ‘่พน {tgt} -> {src} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
props == reverse_edges_dict[(tgt, src)]
), f"่พน {src} -> {tgt} ๅ’Œๅๅ‘่พน {tgt} -> {src} ็š„ๅฑžๆ€งไธไธ€่‡ด"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆ‰น้‡่Žทๅ–็š„ๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธ€่‡ด")
# 6. ๆต‹่ฏ• get_nodes_edges_batch - ๆ‰น้‡่Žทๅ–ๅคšไธช่Š‚็‚น็š„ๆ‰€ๆœ‰่พน
print("== ๆต‹่ฏ• get_nodes_edges_batch")
nodes_edges = await storage.get_nodes_edges_batch([node1_id, node3_id])
print(f"ๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็ป“ๆžœ: {nodes_edges.keys()}")
assert (
len(nodes_edges) == 2
), f"ๅบ”่ฟ”ๅ›ž2ไธช่Š‚็‚น็š„่พน๏ผŒๅฎž้™…่ฟ”ๅ›ž {len(nodes_edges)} ไธช"
assert node1_id in nodes_edges, f"{node1_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert node3_id in nodes_edges, f"{node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
len(nodes_edges[node1_id]) == 3
), f"{node1_id} ๅบ”ๆœ‰3ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(nodes_edges[node1_id])} ๆก"
assert (
len(nodes_edges[node3_id]) == 3
), f"{node3_id} ๅบ”ๆœ‰3ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(nodes_edges[node3_id])} ๆก"
# 6.1 ้ชŒ่ฏๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("== ้ชŒ่ฏๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ๆฃ€ๆŸฅ่Š‚็‚น1็š„่พนๆ˜ฏๅฆๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
node1_outgoing_edges = [
(src, tgt) for src, tgt in nodes_edges[node1_id] if src == node1_id
]
node1_incoming_edges = [
(src, tgt) for src, tgt in nodes_edges[node1_id] if tgt == node1_id
]
print(f"่Š‚็‚น {node1_id} ็š„ๅ‡บ่พน: {node1_outgoing_edges}")
print(f"่Š‚็‚น {node1_id} ็š„ๅ…ฅ่พน: {node1_incoming_edges}")
# ๆฃ€ๆŸฅๆ˜ฏๅฆๅŒ…ๅซๅˆฐๆœบๅ™จๅญฆไน ใ€่‡ช็„ถ่ฏญ่จ€ๅค„็†ๅ’Œ่ฎก็ฎ—ๆœบ่ง†่ง‰็š„่พน
has_edge_to_node2 = any(tgt == node2_id for _, tgt in node1_outgoing_edges)
has_edge_to_node4 = any(tgt == node4_id for _, tgt in node1_outgoing_edges)
has_edge_to_node5 = any(tgt == node5_id for _, tgt in node1_outgoing_edges)
assert has_edge_to_node2, f"่Š‚็‚น {node1_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซๅˆฐ {node2_id} ็š„่พน"
assert has_edge_to_node4, f"่Š‚็‚น {node1_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซๅˆฐ {node4_id} ็š„่พน"
assert has_edge_to_node5, f"่Š‚็‚น {node1_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซๅˆฐ {node5_id} ็š„่พน"
# ๆฃ€ๆŸฅ่Š‚็‚น3็š„่พนๆ˜ฏๅฆๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
node3_outgoing_edges = [
(src, tgt) for src, tgt in nodes_edges[node3_id] if src == node3_id
]
node3_incoming_edges = [
(src, tgt) for src, tgt in nodes_edges[node3_id] if tgt == node3_id
]
print(f"่Š‚็‚น {node3_id} ็š„ๅ‡บ่พน: {node3_outgoing_edges}")
print(f"่Š‚็‚น {node3_id} ็š„ๅ…ฅ่พน: {node3_incoming_edges}")
# ๆฃ€ๆŸฅๆ˜ฏๅฆๅŒ…ๅซไธŽๆœบๅ™จๅญฆไน ใ€่‡ช็„ถ่ฏญ่จ€ๅค„็†ๅ’Œ่ฎก็ฎ—ๆœบ่ง†่ง‰็š„่ฟžๆŽฅ๏ผˆๅฟฝ็•ฅๆ–นๅ‘๏ผ‰
has_connection_with_node2 = any(
(src == node2_id and tgt == node3_id)
or (src == node3_id and tgt == node2_id)
for src, tgt in nodes_edges[node3_id]
)
has_connection_with_node4 = any(
(src == node3_id and tgt == node4_id)
or (src == node4_id and tgt == node3_id)
for src, tgt in nodes_edges[node3_id]
)
has_connection_with_node5 = any(
(src == node3_id and tgt == node5_id)
or (src == node5_id and tgt == node3_id)
for src, tgt in nodes_edges[node3_id]
)
assert (
has_connection_with_node2
), f"่Š‚็‚น {node3_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node2_id} ็š„่ฟžๆŽฅ"
assert (
has_connection_with_node4
), f"่Š‚็‚น {node3_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node4_id} ็š„่ฟžๆŽฅ"
assert (
has_connection_with_node5
), f"่Š‚็‚น {node3_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node5_id} ็š„่ฟžๆŽฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆ‰น้‡่Žทๅ–็š„่Š‚็‚น่พนๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰")
# 7. ๆต‹่ฏ• get_nodes_by_chunk_ids - ๆ‰น้‡ๆ นๆฎ chunk_ids ่Žทๅ–ๅคšไธช่Š‚็‚น
print("== ๆต‹่ฏ• get_nodes_by_chunk_ids")
print("== ๆต‹่ฏ•ๅ•ไธช chunk_id๏ผŒๅŒน้…ๅคšไธช่Š‚็‚น")
nodes = await storage.get_nodes_by_chunk_ids([chunk2_id])
assert len(nodes) == 2, f"{chunk1_id} ๅบ”ๆœ‰2ไธช่Š‚็‚น๏ผŒๅฎž้™…ๆœ‰ {len(nodes)} ไธช"
has_node1 = any(node["entity_id"] == node1_id for node in nodes)
has_node2 = any(node["entity_id"] == node2_id for node in nodes)
assert has_node1, f"่Š‚็‚น {node1_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert has_node2, f"่Š‚็‚น {node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
print("== ๆต‹่ฏ•ๅคšไธช chunk_id๏ผŒ้ƒจๅˆ†ๅŒน้…ๅคšไธช่Š‚็‚น")
nodes = await storage.get_nodes_by_chunk_ids([chunk2_id, chunk3_id])
assert (
len(nodes) == 3
), f"{chunk2_id}, {chunk3_id} ๅบ”ๆœ‰3ไธช่Š‚็‚น๏ผŒๅฎž้™…ๆœ‰ {len(nodes)} ไธช"
has_node1 = any(node["entity_id"] == node1_id for node in nodes)
has_node2 = any(node["entity_id"] == node2_id for node in nodes)
has_node3 = any(node["entity_id"] == node3_id for node in nodes)
assert has_node1, f"่Š‚็‚น {node1_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert has_node2, f"่Š‚็‚น {node2_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert has_node3, f"่Š‚็‚น {node3_id} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
# 8. ๆต‹่ฏ• get_edges_by_chunk_ids - ๆ‰น้‡ๆ นๆฎ chunk_ids ่Žทๅ–ๅคšๆก่พน
print("== ๆต‹่ฏ• get_edges_by_chunk_ids")
print("== ๆต‹่ฏ•ๅ•ไธช chunk_id๏ผŒๅŒน้…ๅคšๆก่พน")
edges = await storage.get_edges_by_chunk_ids([chunk2_id])
assert len(edges) == 2, f"{chunk2_id} ๅบ”ๆœ‰2ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(edges)} ๆก"
has_edge_node1_node2 = any(
edge["source"] == node1_id and edge["target"] == node2_id for edge in edges
)
has_edge_node2_node3 = any(
edge["source"] == node2_id and edge["target"] == node3_id for edge in edges
)
assert has_edge_node1_node2, f"{chunk2_id} ๅบ”ๅŒ…ๅซ {node1_id} ๅˆฐ {node2_id} ็š„่พน"
assert has_edge_node2_node3, f"{chunk2_id} ๅบ”ๅŒ…ๅซ {node2_id} ๅˆฐ {node3_id} ็š„่พน"
print("== ๆต‹่ฏ•ๅคšไธช chunk_id๏ผŒ้ƒจๅˆ†ๅŒน้…ๅคšๆก่พน")
edges = await storage.get_edges_by_chunk_ids([chunk2_id, chunk3_id])
assert (
len(edges) == 3
), f"{chunk2_id}, {chunk3_id} ๅบ”ๆœ‰3ๆก่พน๏ผŒๅฎž้™…ๆœ‰ {len(edges)} ๆก"
has_edge_node1_node2 = any(
edge["source"] == node1_id and edge["target"] == node2_id for edge in edges
)
has_edge_node2_node3 = any(
edge["source"] == node2_id and edge["target"] == node3_id for edge in edges
)
has_edge_node1_node4 = any(
edge["source"] == node1_id and edge["target"] == node4_id for edge in edges
)
assert (
has_edge_node1_node2
), f"{chunk2_id}, {chunk3_id} ๅบ”ๅŒ…ๅซ {node1_id} ๅˆฐ {node2_id} ็š„่พน"
assert (
has_edge_node2_node3
), f"{chunk2_id}, {chunk3_id} ๅบ”ๅŒ…ๅซ {node2_id} ๅˆฐ {node3_id} ็š„่พน"
assert (
has_edge_node1_node4
), f"{chunk2_id}, {chunk3_id} ๅบ”ๅŒ…ๅซ {node1_id} ๅˆฐ {node4_id} ็š„่พน"
print("\nๆ‰น้‡ๆ“ไฝœๆต‹่ฏ•ๅฎŒๆˆ")
return True
except Exception as e:
ASCIIColors.red(f"ๆต‹่ฏ•่ฟ‡็จ‹ไธญๅ‘็”Ÿ้”™่ฏฏ: {str(e)}")
return False
async def test_graph_special_characters(storage):
"""
ๆต‹่ฏ•ๅ›พๆ•ฐๆฎๅบ“ๅฏน็‰นๆฎŠๅญ—็ฌฆ็š„ๅค„็†:
1. ๆต‹่ฏ•่Š‚็‚นๅ็งฐๅ’Œๆ่ฟฐไธญๅŒ…ๅซๅ•ๅผ•ๅทใ€ๅŒๅผ•ๅทๅ’Œๅๆ–œๆ 
2. ๆต‹่ฏ•่พน็š„ๆ่ฟฐไธญๅŒ…ๅซๅ•ๅผ•ๅทใ€ๅŒๅผ•ๅทๅ’Œๅๆ–œๆ 
3. ้ชŒ่ฏ็‰นๆฎŠๅญ—็ฌฆๆ˜ฏๅฆ่ขซๆญฃ็กฎไฟๅญ˜ๅ’Œๆฃ€็ดข
"""
try:
# 1. ๆต‹่ฏ•่Š‚็‚นๅ็งฐไธญ็š„็‰นๆฎŠๅญ—็ฌฆ
node1_id = "ๅŒ…ๅซ'ๅ•ๅผ•ๅท'็š„่Š‚็‚น"
node1_data = {
"entity_id": node1_id,
"description": "่ฟ™ไธชๆ่ฟฐๅŒ…ๅซ'ๅ•ๅผ•ๅท'ใ€\"ๅŒๅผ•ๅท\"ๅ’Œ\\ๅๆ–œๆ ",
"keywords": "็‰นๆฎŠๅญ—็ฌฆ,ๅผ•ๅท,่ฝฌไน‰",
"entity_type": "ๆต‹่ฏ•่Š‚็‚น",
}
print(f"ๆ’ๅ…ฅๅŒ…ๅซ็‰นๆฎŠๅญ—็ฌฆ็š„่Š‚็‚น1: {node1_id}")
await storage.upsert_node(node1_id, node1_data)
# 2. ๆต‹่ฏ•่Š‚็‚นๅ็งฐไธญ็š„ๅŒๅผ•ๅท
node2_id = 'ๅŒ…ๅซ"ๅŒๅผ•ๅท"็š„่Š‚็‚น'
node2_data = {
"entity_id": node2_id,
"description": "่ฟ™ไธชๆ่ฟฐๅŒๆ—ถๅŒ…ๅซ'ๅ•ๅผ•ๅท'ๅ’Œ\"ๅŒๅผ•ๅท\"ไปฅๅŠ\\ๅๆ–œๆ \\่ทฏๅพ„",
"keywords": "็‰นๆฎŠๅญ—็ฌฆ,ๅผ•ๅท,JSON",
"entity_type": "ๆต‹่ฏ•่Š‚็‚น",
}
print(f"ๆ’ๅ…ฅๅŒ…ๅซ็‰นๆฎŠๅญ—็ฌฆ็š„่Š‚็‚น2: {node2_id}")
await storage.upsert_node(node2_id, node2_data)
# 3. ๆต‹่ฏ•่Š‚็‚นๅ็งฐไธญ็š„ๅๆ–œๆ 
node3_id = "ๅŒ…ๅซ\\ๅๆ–œๆ \\็š„่Š‚็‚น"
node3_data = {
"entity_id": node3_id,
"description": "่ฟ™ไธชๆ่ฟฐๅŒ…ๅซWindows่ทฏๅพ„C:\\Program Files\\ๅ’Œ่ฝฌไน‰ๅญ—็ฌฆ\\n\\t",
"keywords": "ๅๆ–œๆ ,่ทฏๅพ„,่ฝฌไน‰",
"entity_type": "ๆต‹่ฏ•่Š‚็‚น",
}
print(f"ๆ’ๅ…ฅๅŒ…ๅซ็‰นๆฎŠๅญ—็ฌฆ็š„่Š‚็‚น3: {node3_id}")
await storage.upsert_node(node3_id, node3_data)
# 4. ๆต‹่ฏ•่พนๆ่ฟฐไธญ็š„็‰นๆฎŠๅญ—็ฌฆ
edge1_data = {
"relationship": "็‰นๆฎŠ'ๅ…ณ็ณป'",
"weight": 1.0,
"description": "่ฟ™ไธช่พนๆ่ฟฐๅŒ…ๅซ'ๅ•ๅผ•ๅท'ใ€\"ๅŒๅผ•ๅท\"ๅ’Œ\\ๅๆ–œๆ ",
}
print(f"ๆ’ๅ…ฅๅŒ…ๅซ็‰นๆฎŠๅญ—็ฌฆ็š„่พน: {node1_id} -> {node2_id}")
await storage.upsert_edge(node1_id, node2_id, edge1_data)
# 5. ๆต‹่ฏ•่พนๆ่ฟฐไธญ็š„ๆ›ดๅคๆ‚็‰นๆฎŠๅญ—็ฌฆ็ป„ๅˆ
edge2_data = {
"relationship": 'ๅคๆ‚"ๅ…ณ็ณป"\\็ฑปๅž‹',
"weight": 0.8,
"description": "ๅŒ…ๅซSQLๆณจๅ…ฅๅฐ่ฏ•: SELECT * FROM users WHERE name='admin'--",
}
print(f"ๆ’ๅ…ฅๅŒ…ๅซๅคๆ‚็‰นๆฎŠๅญ—็ฌฆ็š„่พน: {node2_id} -> {node3_id}")
await storage.upsert_edge(node2_id, node3_id, edge2_data)
# 6. ้ชŒ่ฏ่Š‚็‚น็‰นๆฎŠๅญ—็ฌฆๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
print("\n== ้ชŒ่ฏ่Š‚็‚น็‰นๆฎŠๅญ—็ฌฆ")
for node_id, original_data in [
(node1_id, node1_data),
(node2_id, node2_data),
(node3_id, node3_data),
]:
node_props = await storage.get_node(node_id)
if node_props:
print(f"ๆˆๅŠŸ่ฏปๅ–่Š‚็‚น: {node_id}")
print(f"่Š‚็‚นๆ่ฟฐ: {node_props.get('description', 'ๆ— ๆ่ฟฐ')}")
# ้ชŒ่ฏ่Š‚็‚นIDๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
node_props.get("entity_id") == node_id
), f"่Š‚็‚นIDไธๅŒน้…: ๆœŸๆœ› {node_id}, ๅฎž้™… {node_props.get('entity_id')}"
# ้ชŒ่ฏๆ่ฟฐๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
node_props.get("description") == original_data["description"]
), f"่Š‚็‚นๆ่ฟฐไธๅŒน้…: ๆœŸๆœ› {original_data['description']}, ๅฎž้™… {node_props.get('description')}"
print(f"่Š‚็‚น {node_id} ็‰นๆฎŠๅญ—็ฌฆ้ชŒ่ฏๆˆๅŠŸ")
else:
print(f"่ฏปๅ–่Š‚็‚นๅฑžๆ€งๅคฑ่ดฅ: {node_id}")
assert False, f"ๆœช่ƒฝ่ฏปๅ–่Š‚็‚นๅฑžๆ€ง: {node_id}"
# 7. ้ชŒ่ฏ่พน็‰นๆฎŠๅญ—็ฌฆๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
print("\n== ้ชŒ่ฏ่พน็‰นๆฎŠๅญ—็ฌฆ")
edge1_props = await storage.get_edge(node1_id, node2_id)
if edge1_props:
print(f"ๆˆๅŠŸ่ฏปๅ–่พน: {node1_id} -> {node2_id}")
print(f"่พนๅ…ณ็ณป: {edge1_props.get('relationship', 'ๆ— ๅ…ณ็ณป')}")
print(f"่พนๆ่ฟฐ: {edge1_props.get('description', 'ๆ— ๆ่ฟฐ')}")
# ้ชŒ่ฏ่พนๅ…ณ็ณปๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
edge1_props.get("relationship") == edge1_data["relationship"]
), f"่พนๅ…ณ็ณปไธๅŒน้…: ๆœŸๆœ› {edge1_data['relationship']}, ๅฎž้™… {edge1_props.get('relationship')}"
# ้ชŒ่ฏ่พนๆ่ฟฐๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
edge1_props.get("description") == edge1_data["description"]
), f"่พนๆ่ฟฐไธๅŒน้…: ๆœŸๆœ› {edge1_data['description']}, ๅฎž้™… {edge1_props.get('description')}"
print(f"่พน {node1_id} -> {node2_id} ็‰นๆฎŠๅญ—็ฌฆ้ชŒ่ฏๆˆๅŠŸ")
else:
print(f"่ฏปๅ–่พนๅฑžๆ€งๅคฑ่ดฅ: {node1_id} -> {node2_id}")
assert False, f"ๆœช่ƒฝ่ฏปๅ–่พนๅฑžๆ€ง: {node1_id} -> {node2_id}"
edge2_props = await storage.get_edge(node2_id, node3_id)
if edge2_props:
print(f"ๆˆๅŠŸ่ฏปๅ–่พน: {node2_id} -> {node3_id}")
print(f"่พนๅ…ณ็ณป: {edge2_props.get('relationship', 'ๆ— ๅ…ณ็ณป')}")
print(f"่พนๆ่ฟฐ: {edge2_props.get('description', 'ๆ— ๆ่ฟฐ')}")
# ้ชŒ่ฏ่พนๅ…ณ็ณปๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
edge2_props.get("relationship") == edge2_data["relationship"]
), f"่พนๅ…ณ็ณปไธๅŒน้…: ๆœŸๆœ› {edge2_data['relationship']}, ๅฎž้™… {edge2_props.get('relationship')}"
# ้ชŒ่ฏ่พนๆ่ฟฐๆ˜ฏๅฆๆญฃ็กฎไฟๅญ˜
assert (
edge2_props.get("description") == edge2_data["description"]
), f"่พนๆ่ฟฐไธๅŒน้…: ๆœŸๆœ› {edge2_data['description']}, ๅฎž้™… {edge2_props.get('description')}"
print(f"่พน {node2_id} -> {node3_id} ็‰นๆฎŠๅญ—็ฌฆ้ชŒ่ฏๆˆๅŠŸ")
else:
print(f"่ฏปๅ–่พนๅฑžๆ€งๅคฑ่ดฅ: {node2_id} -> {node3_id}")
assert False, f"ๆœช่ƒฝ่ฏปๅ–่พนๅฑžๆ€ง: {node2_id} -> {node3_id}"
print("\n็‰นๆฎŠๅญ—็ฌฆๆต‹่ฏ•ๅฎŒๆˆ๏ผŒๆ•ฐๆฎๅทฒไฟ็•™ๅœจๆ•ฐๆฎๅบ“ไธญ")
return True
except Exception as e:
ASCIIColors.red(f"ๆต‹่ฏ•่ฟ‡็จ‹ไธญๅ‘็”Ÿ้”™่ฏฏ: {str(e)}")
return False
async def test_graph_undirected_property(storage):
"""
ไธ“้—จๆต‹่ฏ•ๅ›พๅญ˜ๅ‚จ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง:
1. ้ชŒ่ฏๆ’ๅ…ฅไธ€ไธชๆ–นๅ‘็š„่พนๅŽ๏ผŒๅๅ‘ๆŸฅ่ฏขๆ˜ฏๅฆ่ƒฝ่Žทๅพ—็›ธๅŒ็š„็ป“ๆžœ
2. ้ชŒ่ฏ่พน็š„ๅฑžๆ€งๅœจๆญฃๅ‘ๅ’Œๅๅ‘ๆŸฅ่ฏขไธญๆ˜ฏๅฆไธ€่‡ด
3. ้ชŒ่ฏๅˆ ้™คไธ€ไธชๆ–นๅ‘็š„่พนๅŽ๏ผŒๅฆไธ€ไธชๆ–นๅ‘็š„่พนๆ˜ฏๅฆไนŸ่ขซๅˆ ้™ค
4. ้ชŒ่ฏๆ‰น้‡ๆ“ไฝœไธญ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
"""
try:
# 1. ๆ’ๅ…ฅๆต‹่ฏ•ๆ•ฐๆฎ
# ๆ’ๅ…ฅ่Š‚็‚น1: ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ
node1_id = "่ฎก็ฎ—ๆœบ็ง‘ๅญฆ"
node1_data = {
"entity_id": node1_id,
"description": "่ฎก็ฎ—ๆœบ็ง‘ๅญฆๆ˜ฏ็ ”็ฉถ่ฎก็ฎ—ๆœบๅŠๅ…ถๅบ”็”จ็š„็ง‘ๅญฆใ€‚",
"keywords": "่ฎก็ฎ—ๆœบ,็ง‘ๅญฆ,ๆŠ€ๆœฏ",
"entity_type": "ๅญฆ็ง‘",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น1: {node1_id}")
await storage.upsert_node(node1_id, node1_data)
# ๆ’ๅ…ฅ่Š‚็‚น2: ๆ•ฐๆฎ็ป“ๆž„
node2_id = "ๆ•ฐๆฎ็ป“ๆž„"
node2_data = {
"entity_id": node2_id,
"description": "ๆ•ฐๆฎ็ป“ๆž„ๆ˜ฏ่ฎก็ฎ—ๆœบ็ง‘ๅญฆไธญ็š„ไธ€ไธชๅŸบ็ก€ๆฆ‚ๅฟต๏ผŒ็”จไบŽ็ป„็ป‡ๅ’Œๅญ˜ๅ‚จๆ•ฐๆฎใ€‚",
"keywords": "ๆ•ฐๆฎ,็ป“ๆž„,็ป„็ป‡",
"entity_type": "ๆฆ‚ๅฟต",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น2: {node2_id}")
await storage.upsert_node(node2_id, node2_data)
# ๆ’ๅ…ฅ่Š‚็‚น3: ็ฎ—ๆณ•
node3_id = "็ฎ—ๆณ•"
node3_data = {
"entity_id": node3_id,
"description": "็ฎ—ๆณ•ๆ˜ฏ่งฃๅ†ณ้—ฎ้ข˜็š„ๆญฅ้ชคๅ’Œๆ–นๆณ•ใ€‚",
"keywords": "็ฎ—ๆณ•,ๆญฅ้ชค,ๆ–นๆณ•",
"entity_type": "ๆฆ‚ๅฟต",
}
print(f"ๆ’ๅ…ฅ่Š‚็‚น3: {node3_id}")
await storage.upsert_node(node3_id, node3_data)
# 2. ๆต‹่ฏ•ๆ’ๅ…ฅ่พนๅŽ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("\n== ๆต‹่ฏ•ๆ’ๅ…ฅ่พนๅŽ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ๆ’ๅ…ฅ่พน1: ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ -> ๆ•ฐๆฎ็ป“ๆž„
edge1_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "่ฎก็ฎ—ๆœบ็ง‘ๅญฆๅŒ…ๅซๆ•ฐๆฎ็ป“ๆž„่ฟ™ไธชๆฆ‚ๅฟต",
}
print(f"ๆ’ๅ…ฅ่พน1: {node1_id} -> {node2_id}")
await storage.upsert_edge(node1_id, node2_id, edge1_data)
# ้ชŒ่ฏๆญฃๅ‘ๆŸฅ่ฏข
forward_edge = await storage.get_edge(node1_id, node2_id)
print(f"ๆญฃๅ‘่พนๅฑžๆ€ง: {forward_edge}")
assert forward_edge is not None, f"ๆœช่ƒฝ่ฏปๅ–ๆญฃๅ‘่พนๅฑžๆ€ง: {node1_id} -> {node2_id}"
# ้ชŒ่ฏๅๅ‘ๆŸฅ่ฏข
reverse_edge = await storage.get_edge(node2_id, node1_id)
print(f"ๅๅ‘่พนๅฑžๆ€ง: {reverse_edge}")
assert reverse_edge is not None, f"ๆœช่ƒฝ่ฏปๅ–ๅๅ‘่พนๅฑžๆ€ง: {node2_id} -> {node1_id}"
# ้ชŒ่ฏๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งๆ˜ฏๅฆไธ€่‡ด
assert (
forward_edge == reverse_edge
), "ๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธไธ€่‡ด๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธ€่‡ด")
# 3. ๆต‹่ฏ•่พน็š„ๅบฆๆ•ฐ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("\n== ๆต‹่ฏ•่พน็š„ๅบฆๆ•ฐ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ๆ’ๅ…ฅ่พน2: ่ฎก็ฎ—ๆœบ็ง‘ๅญฆ -> ็ฎ—ๆณ•
edge2_data = {
"relationship": "ๅŒ…ๅซ",
"weight": 1.0,
"description": "่ฎก็ฎ—ๆœบ็ง‘ๅญฆๅŒ…ๅซ็ฎ—ๆณ•่ฟ™ไธชๆฆ‚ๅฟต",
}
print(f"ๆ’ๅ…ฅ่พน2: {node1_id} -> {node3_id}")
await storage.upsert_edge(node1_id, node3_id, edge2_data)
# ้ชŒ่ฏๆญฃๅ‘ๅ’Œๅๅ‘่พน็š„ๅบฆๆ•ฐ
forward_degree = await storage.edge_degree(node1_id, node2_id)
reverse_degree = await storage.edge_degree(node2_id, node1_id)
print(f"ๆญฃๅ‘่พน {node1_id} -> {node2_id} ็š„ๅบฆๆ•ฐ: {forward_degree}")
print(f"ๅๅ‘่พน {node2_id} -> {node1_id} ็š„ๅบฆๆ•ฐ: {reverse_degree}")
assert (
forward_degree == reverse_degree
), "ๆญฃๅ‘ๅ’Œๅๅ‘่พน็š„ๅบฆๆ•ฐไธไธ€่‡ด๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆญฃๅ‘ๅ’Œๅๅ‘่พน็š„ๅบฆๆ•ฐไธ€่‡ด")
# 4. ๆต‹่ฏ•ๅˆ ้™ค่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("\n== ๆต‹่ฏ•ๅˆ ้™ค่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ๅˆ ้™คๆญฃๅ‘่พน
print(f"ๅˆ ้™ค่พน: {node1_id} -> {node2_id}")
await storage.remove_edges([(node1_id, node2_id)])
# ้ชŒ่ฏๆญฃๅ‘่พนๆ˜ฏๅฆ่ขซๅˆ ้™ค
forward_edge = await storage.get_edge(node1_id, node2_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏขๆญฃๅ‘่พนๅฑžๆ€ง {node1_id} -> {node2_id}: {forward_edge}")
assert forward_edge is None, f"่พน {node1_id} -> {node2_id} ๅบ”ๅทฒ่ขซๅˆ ้™ค"
# ้ชŒ่ฏๅๅ‘่พนๆ˜ฏๅฆไนŸ่ขซๅˆ ้™ค
reverse_edge = await storage.get_edge(node2_id, node1_id)
print(f"ๅˆ ้™คๅŽๆŸฅ่ฏขๅๅ‘่พนๅฑžๆ€ง {node2_id} -> {node1_id}: {reverse_edge}")
assert (
reverse_edge is None
), f"ๅๅ‘่พน {node2_id} -> {node1_id} ไนŸๅบ”่ขซๅˆ ้™ค๏ผŒๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๅคฑ่ดฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๅˆ ้™คไธ€ไธชๆ–นๅ‘็š„่พนๅŽ๏ผŒๅๅ‘่พนไนŸ่ขซๅˆ ้™ค")
# 5. ๆต‹่ฏ•ๆ‰น้‡ๆ“ไฝœไธญ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("\n== ๆต‹่ฏ•ๆ‰น้‡ๆ“ไฝœไธญ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
# ้‡ๆ–ฐๆ’ๅ…ฅ่พน
await storage.upsert_edge(node1_id, node2_id, edge1_data)
# ๆ‰น้‡่Žทๅ–่พนๅฑžๆ€ง
edge_dicts = [
{"src": node1_id, "tgt": node2_id},
{"src": node1_id, "tgt": node3_id},
]
reverse_edge_dicts = [
{"src": node2_id, "tgt": node1_id},
{"src": node3_id, "tgt": node1_id},
]
edges_dict = await storage.get_edges_batch(edge_dicts)
reverse_edges_dict = await storage.get_edges_batch(reverse_edge_dicts)
print(f"ๆ‰น้‡่Žทๅ–ๆญฃๅ‘่พนๅฑžๆ€ง็ป“ๆžœ: {edges_dict.keys()}")
print(f"ๆ‰น้‡่Žทๅ–ๅๅ‘่พนๅฑžๆ€ง็ป“ๆžœ: {reverse_edges_dict.keys()}")
# ้ชŒ่ฏๆญฃๅ‘ๅ’Œๅๅ‘่พน็š„ๅฑžๆ€งๆ˜ฏๅฆไธ€่‡ด
for (src, tgt), props in edges_dict.items():
assert (
tgt,
src,
) in reverse_edges_dict, f"ๅๅ‘่พน {tgt} -> {src} ๅบ”ๅœจ่ฟ”ๅ›ž็ป“ๆžœไธญ"
assert (
props == reverse_edges_dict[(tgt, src)]
), f"่พน {src} -> {tgt} ๅ’Œๅๅ‘่พน {tgt} -> {src} ็š„ๅฑžๆ€งไธไธ€่‡ด"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆ‰น้‡่Žทๅ–็š„ๆญฃๅ‘ๅ’Œๅๅ‘่พนๅฑžๆ€งไธ€่‡ด")
# 6. ๆต‹่ฏ•ๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง
print("\n== ๆต‹่ฏ•ๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง")
nodes_edges = await storage.get_nodes_edges_batch([node1_id, node2_id])
print(f"ๆ‰น้‡่Žทๅ–่Š‚็‚น่พน็ป“ๆžœ: {nodes_edges.keys()}")
# ๆฃ€ๆŸฅ่Š‚็‚น1็š„่พนๆ˜ฏๅฆๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰
node1_edges = nodes_edges[node1_id]
node2_edges = nodes_edges[node2_id]
# ๆฃ€ๆŸฅ่Š‚็‚น1ๆ˜ฏๅฆๆœ‰ๅˆฐ่Š‚็‚น2ๅ’Œ่Š‚็‚น3็š„่พน
has_edge_to_node2 = any(
(src == node1_id and tgt == node2_id) for src, tgt in node1_edges
)
has_edge_to_node3 = any(
(src == node1_id and tgt == node3_id) for src, tgt in node1_edges
)
assert has_edge_to_node2, f"่Š‚็‚น {node1_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซๅˆฐ {node2_id} ็š„่พน"
assert has_edge_to_node3, f"่Š‚็‚น {node1_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซๅˆฐ {node3_id} ็š„่พน"
# ๆฃ€ๆŸฅ่Š‚็‚น2ๆ˜ฏๅฆๆœ‰ๅˆฐ่Š‚็‚น1็š„่พน
has_edge_to_node1 = any(
(src == node2_id and tgt == node1_id)
or (src == node1_id and tgt == node2_id)
for src, tgt in node2_edges
)
assert (
has_edge_to_node1
), f"่Š‚็‚น {node2_id} ็š„่พนๅˆ—่กจไธญๅบ”ๅŒ…ๅซไธŽ {node1_id} ็š„่ฟžๆŽฅ"
print("ๆ— ๅ‘ๅ›พ็‰นๆ€ง้ชŒ่ฏๆˆๅŠŸ๏ผšๆ‰น้‡่Žทๅ–็š„่Š‚็‚น่พนๅŒ…ๅซๆ‰€ๆœ‰็›ธๅ…ณ็š„่พน๏ผˆๆ— ่ฎบๆ–นๅ‘๏ผ‰")
print("\nๆ— ๅ‘ๅ›พ็‰นๆ€งๆต‹่ฏ•ๅฎŒๆˆ")
return True
except Exception as e:
ASCIIColors.red(f"ๆต‹่ฏ•่ฟ‡็จ‹ไธญๅ‘็”Ÿ้”™่ฏฏ: {str(e)}")
return False
async def main():
"""ไธปๅ‡ฝๆ•ฐ"""
# ๆ˜พ็คบ็จ‹ๅบๆ ‡้ข˜
ASCIIColors.cyan("""
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ ้€š็”จๅ›พๅญ˜ๅ‚จๆต‹่ฏ•็จ‹ๅบ โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
""")
# ๆฃ€ๆŸฅ.envๆ–‡ไปถ
if not check_env_file():
return
# ๅŠ ่ฝฝ็Žฏๅขƒๅ˜้‡
load_dotenv(dotenv_path=".env", override=False)
# ่Žทๅ–ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹
graph_storage_type = os.getenv("LIGHTRAG_GRAPH_STORAGE", "NetworkXStorage")
ASCIIColors.magenta(f"\nๅฝ“ๅ‰้…็ฝฎ็š„ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹: {graph_storage_type}")
ASCIIColors.white(
f"ๆ”ฏๆŒ็š„ๅ›พๅญ˜ๅ‚จ็ฑปๅž‹: {', '.join(STORAGE_IMPLEMENTATIONS['GRAPH_STORAGE']['implementations'])}"
)
# ๅˆๅง‹ๅŒ–ๅญ˜ๅ‚จๅฎžไพ‹
storage = await initialize_graph_storage()
if not storage:
ASCIIColors.red("ๅˆๅง‹ๅŒ–ๅญ˜ๅ‚จๅฎžไพ‹ๅคฑ่ดฅ๏ผŒๆต‹่ฏ•็จ‹ๅบ้€€ๅ‡บ")
return
try:
# ๆ˜พ็คบๆต‹่ฏ•้€‰้กน
ASCIIColors.yellow("\n่ฏท้€‰ๆ‹ฉๆต‹่ฏ•็ฑปๅž‹:")
ASCIIColors.white("1. ๅŸบๆœฌๆต‹่ฏ• (่Š‚็‚นๅ’Œ่พน็š„ๆ’ๅ…ฅใ€่ฏปๅ–)")
ASCIIColors.white("2. ้ซ˜็บงๆต‹่ฏ• (ๅบฆๆ•ฐใ€ๆ ‡็ญพใ€็Ÿฅ่ฏ†ๅ›พ่ฐฑใ€ๅˆ ้™คๆ“ไฝœ็ญ‰)")
ASCIIColors.white("3. ๆ‰น้‡ๆ“ไฝœๆต‹่ฏ• (ๆ‰น้‡่Žทๅ–่Š‚็‚นใ€่พนๅฑžๆ€งๅ’Œๅบฆๆ•ฐ็ญ‰)")
ASCIIColors.white("4. ๆ— ๅ‘ๅ›พ็‰นๆ€งๆต‹่ฏ• (้ชŒ่ฏๅญ˜ๅ‚จ็š„ๆ— ๅ‘ๅ›พ็‰นๆ€ง)")
ASCIIColors.white("5. ็‰นๆฎŠๅญ—็ฌฆๆต‹่ฏ• (้ชŒ่ฏๅ•ๅผ•ๅทใ€ๅŒๅผ•ๅทๅ’Œๅๆ–œๆ ็ญ‰็‰นๆฎŠๅญ—็ฌฆ)")
ASCIIColors.white("6. ๅ…จ้ƒจๆต‹่ฏ•")
choice = input("\n่ฏท่พ“ๅ…ฅ้€‰้กน (1/2/3/4/5/6): ")
# ๅœจๆ‰ง่กŒๆต‹่ฏ•ๅ‰ๆธ…็†ๆ•ฐๆฎ
if choice in ["1", "2", "3", "4", "5", "6"]:
ASCIIColors.yellow("\nๆ‰ง่กŒๆต‹่ฏ•ๅ‰ๆธ…็†ๆ•ฐๆฎ...")
await storage.drop()
ASCIIColors.green("ๆ•ฐๆฎๆธ…็†ๅฎŒๆˆ\n")
if choice == "1":
await test_graph_basic(storage)
elif choice == "2":
await test_graph_advanced(storage)
elif choice == "3":
await test_graph_batch_operations(storage)
elif choice == "4":
await test_graph_undirected_property(storage)
elif choice == "5":
await test_graph_special_characters(storage)
elif choice == "6":
ASCIIColors.cyan("\n=== ๅผ€ๅง‹ๅŸบๆœฌๆต‹่ฏ• ===")
basic_result = await test_graph_basic(storage)
if basic_result:
ASCIIColors.cyan("\n=== ๅผ€ๅง‹้ซ˜็บงๆต‹่ฏ• ===")
advanced_result = await test_graph_advanced(storage)
if advanced_result:
ASCIIColors.cyan("\n=== ๅผ€ๅง‹ๆ‰น้‡ๆ“ไฝœๆต‹่ฏ• ===")
batch_result = await test_graph_batch_operations(storage)
if batch_result:
ASCIIColors.cyan("\n=== ๅผ€ๅง‹ๆ— ๅ‘ๅ›พ็‰นๆ€งๆต‹่ฏ• ===")
undirected_result = await test_graph_undirected_property(
storage
)
if undirected_result:
ASCIIColors.cyan("\n=== ๅผ€ๅง‹็‰นๆฎŠๅญ—็ฌฆๆต‹่ฏ• ===")
await test_graph_special_characters(storage)
else:
ASCIIColors.red("ๆ— ๆ•ˆ็š„้€‰้กน")
finally:
# ๅ…ณ้—ญ่ฟžๆŽฅ
if storage:
await storage.finalize()
ASCIIColors.green("\nๅญ˜ๅ‚จ่ฟžๆŽฅๅทฒๅ…ณ้—ญ")
if __name__ == "__main__":
asyncio.run(main())