การรวม Lexical Graph กับ Vector Search

Graph RAG ด้วย LangChain และ Neo4j

Adam Cowley

Manager, Developer Education at Neo4j

การใช้ความสัมพันธ์ใน Semantic Search

การทำงานที่ Neo4j เป็นอย่างไร?

ไดอะแกรมกราฟที่มี Review node และ text property ว่า "Neo4j is a great place to work"

Graph RAG ด้วย LangChain และ Neo4j

การใช้ความสัมพันธ์ใน Semantic Search

การทำงานที่ Neo4j เป็นอย่างไร?

รีวิวนี้โพสต์โดย Person ที่มี screen name ว่า @emileifrem

Graph RAG ด้วย LangChain และ Neo4j

การใช้ความสัมพันธ์ใน Semantic Search

การทำงานที่ Neo4j เป็นอย่างไร?

Emil Eifrem มีความสัมพันธ์ WORKS_AT ไปยัง Company node ที่มีชื่อว่า Neo4j

Graph RAG ด้วย LangChain และ Neo4j

แปลง Text Property เป็น Embedding

 

  • สร้าง node embedding จาก property text

ฉากที่มีความสัมพันธ์ HAS_CHUNK ไปยัง Chunk node ที่มี string property

Graph RAG ด้วย LangChain และ Neo4j

แปลง Text Property เป็น Embedding

 

  • สร้าง node embedding จาก property text
  • ทำ Vector Search บน embedding
  • ใช้ความสัมพันธ์เพื่อเพิ่มบริบท

text property บน node ถูกนำมาสร้าง embedding

Graph RAG ด้วย LangChain และ Neo4j

Neo4j ในฐานะ Vector Store

from langchain_neo4j import Neo4jVector

 

  • Neo4jVector.from_documents(): สร้าง node และ index จาก Document
  • Neo4jVector.from_existing_graph(): สร้าง index บน label และ property ที่มีอยู่แล้ว
Graph RAG ด้วย LangChain และ Neo4j

การแบ่ง Chunk จาก Node Property ที่มีอยู่

ไดอะแกรม knowledge graph ที่เน้นความสัมพันธ์ HAS_SCENE จาก Act node ไปยัง Scene node

res = graph.query("""

MATCH (s:Scene)
WHERE NOT {(s)-[:HAS_LINE]->()}
RETURN s.id AS id, s.text AS text
""")
for scene in res: # Create chunks from scene['text']
Graph RAG ด้วย LangChain และ Neo4j

การแบ่ง Chunk จาก Node Property ที่มีอยู่

  • แบ่ง text ด้วย "\n\n"
  • คำสั่งฉากมีหนึ่งบรรทัด
  • บทพูดขึ้นต้นด้วยชื่อตัวละคร
    • บรรทัดถัดไปคือเนื้อหาบทพูด
 Enter Sampson and Gregory armed with swords..

SAMPSON.
Gregory, on my word...
GREGORY. No, for then we should...
SAMPSON. I mean, if we be in choler, we'll draw...
Graph RAG ด้วย LangChain และ Neo4j

การแบ่ง Chunk จาก Node Property ที่มีอยู่

# Split text into lines
lines = [
    line.strip() for line in text.split("\n\n")

if "\n" in line
]
for line in lines: parts = line.split("\n")
character = parts[0]
text = "\n".join(parts[1:])
Graph RAG ด้วย LangChain และ Neo4j

การแบ่ง Chunk จาก Node Property ที่มีอยู่

# ...Continuing loop over scenes

line_node = Node(type="Line", id=f"{scene.id}-line-{i}", properties={})
character_node = Node(type="Character", id=character, properties={})


# (:Scene)-[:HAS_LINE]->(:Line) graph_document.relationships.append( Relationship(source=scene, target=line_node, type="HAS_LINE"))
# (:Line)-[:SPOKEN_BY]->(:Character) graph_document.relationships.append(Relationship( source=line_node, target=characters[character], type="SPOKEN_BY"))
Graph RAG ด้วย LangChain และ Neo4j

การสร้าง Vector Index บนกราฟที่มีอยู่

from langchain.embeddings import init_embeddings
store = Neo4jVector.from_existing_graph(

init_embeddings("openai:text-embedding-3-small"),
url=NEO4J_URI, username=NEO4J_USERNAME, password=NEO4J_PASSWORD,
node_label="Line",
text_node_properties=["text"],
embedding_node_property="embedding",
index_name="lines",
)
Graph RAG ด้วย LangChain และ Neo4j

Vector Retrieval ด้วย LCEL

# Create retriever
retriever = store.as_retriever()

# Invoke manually retriever.invoke("What does Romeo think of Juliet?") # [ Document, Document, ... ]
Graph RAG ด้วย LangChain และ Neo4j

มาฝึกกันเถอะ!

Graph RAG ด้วย LangChain และ Neo4j

Preparing Video For Download...