“Graph Engineering” đang được nhắc tới khắp nơi, vậy nó có thật không?

Dạo này đi đâu cũng nghe nhắc tới “Graph Engineering”, như thể đây là một ngành kỹ thuật mới toanh, ngang hàng với prompt engineering hay context engineering, harness engineering. Nhưng khi mình ngồi soi kỹ lại các nguồn, hoá ra câu chuyện không hẳn vậy. Bài này là vài phân tích của mình về chuyện đó, rồi mình sẽ đi sâu vào cách dùng graph cho đúng chỗ, đúng lúc.

Trước hết, “Graph Engineering” có phải một ngành riêng không?

Theo mình mình là: không hẳn. Nếu tách bạch ra thì ngành công nghệ AI hiện đang xoay quanh bốn “lớp” kỹ thuật, xây chồng lên nhau như bốn tầng của một cái tháp. Prompt engineering là tầng thấp nhất, lo chuyện viết một câu lệnh cho thật rõ ràng, đúng ý. Context engineering là tầng quyết định model được “nhìn thấy” cái gì, kiến thức nào, dữ liệu nào, cấu trúc ra sao trước khi nó trả lời. Harness engineering lo phần “sân chơi” cho AI hoạt động: công cụ, bộ nhớ, cơ chế phản hồi. Và loop engineering là tầng trên cùng, thiết kế cái vòng lặp quan sát, hành động, kiểm tra, sửa sai, để AI có thể tự chạy mà không cần người nhắc từng bước.

Vậy graph nằm ở đâu? Nó không phải tầng thứ năm. Graph chỉ là một kỹ thuật nằm bên trong tầng context engineering, một cách để nói cho AI biết “cái này liên quan tới cái kia như thế nào”. Gọi nó là “graph engineering” và xếp ngang hàng với bốn tầng kia là chưa hợp lý, giống như gọi “viết SQL” là một ngành kỹ thuật riêng ngang với backend engineering vậy.

Bốn tầng kỹ thuật xây chồng lên nhau và khép thành một vòng lặp. Graph chỉ là một kỹ thuật nằm trong context engineering, đứng cạnh agentic search và vector RAG, không phải một ngành riêng.

Ba cách để đưa ngữ cảnh vào cho AI

Bên trong tầng context engineering, có ba cách chính để tìm và định hình thông tin. Không cách nào thay thế được cách nào, mỗi cách hợp với một loại nội dung khác nhau. Chọn sai chỗ là lỗi phổ biến nhất mình thấy các team hay mắc.

Graph có cấu trúc: Nối các thứ lại với nhau bằng liên kết rõ ràng, có thể là cấu trúc dự án của mình, hoặc entity rút ra từ tài liệu (GraphRAG). Trả lời “cái này liên quan gì tới cái kia”, “đổi cái này thì cái gì bị ảnh hưởng”.

Agentic search: Grep, duyệt cây thư mục, tra symbol, chạy trực tiếp trên mã nguồn thật. Mặc định cho code. Luôn chính xác, không bao giờ lỗi thời vì chẳng có gì được xây trước để mà lỗi thời.

Vector RAG: Embedding và so khớp theo nghĩa. Văn bản ít thay đổi: RFP, policy, tài liệu kiến thức, nơi ý nghĩa quan trọng hơn từ ngữ chính xác.

Hai kiểu graph mà người ta hay gọi chung là “graph”

Nói tới graph, thực ra người ta đang gộp chung hai thứ khác nhau. Một graph đơn giản là một tập các node có kiểu (như Story, Module, Test Case, ADR, Skill) nối với nhau bằng các edge có kiểu (như implements, depends_on, traces_to, constrains, owns). Ý tưởng không có gì phức tạp. Nhưng trong thực tế, nó xuất hiện dưới hai dạng, và tách bạch ra sẽ dễ nói chuyện với nhau hơn.

Graph cấu trúc dự ánGraphRAG (graph tri thức từ tài liệu)
Map cái gìCodebase và các sản phẩm bàn giao của chính dự án: story, requirement, module, test, quyết định thiết kế.Entity và relationship rút ra từ một tập tài liệu hay kho tri thức.
Dùng để làm gìPhân tích tác động, truy vết, hỗ trợ người mới. Ví dụ: “sửa cái này thì gãy chỗ nào?”, “story này được test bởi gì?”, “module này bị ràng buộc bởi quyết định nào?”Trả lời câu hỏi trải rộng trên nhiều tài liệu, nơi câu trả lời phải ghép thông tin từ nhiều nơi. Ví dụ: “người này liên quan gì tới dự án kia?”
Quy mô thường thấyNhỏ: vài trăm node, cập nhật theo nhịp sprint.Có thể rất lớn, phục vụ truy xuất trên khối lượng văn bản lớn.
Xây bằng cách nàoChủ yếu phân tích tĩnh (static analysis) cộng thêm chút chỉnh tay.Trích xuất entity bằng LLM, gộp trùng lặp, nối relationship, rồi ép theo schema.
Graph cấu trúc dự án: mỗi edge trả lời một câu hỏi mà nếu không có graph, AI phải tự lần mò qua nhiều file mới ra được.
Graph GraphRAG: entity và liên kết rút ra từ văn bản, để một câu hỏi có thể nhảy qua nhiều tài liệu cùng lúc.

Xây graph nào thì cũng chỉ có ba việc phải làm

Dù là graph cấu trúc dự án hay GraphRAG, quy trình xây dựng đều quy về ba việc giống nhau.

1. Thiết kế schema: Chọn loại node và loại edge trước tiên, dựa trên câu hỏi thật sự cần trả lời. Đừng mô hình hoá thứ mà mình sẽ chẳng bao giờ hỏi tới. Nếu không bao giờ hỏi “ai đang phụ trách cái này?”, thì chưa cần edge owns vội.

2. Đổ dữ liệu vào: Lấy các relationship vào graph, thường phối hợp ba nguồn: phân tích tĩnh cho liên kết chính xác trong code, LLM trích xuất cho liên kết nằm trong văn bản, và con người chỉnh tay cho những chỗ cần phán đoán. Import trong code lấy từ phân tích tĩnh; “ADR này ảnh hưởng module kia” có khi cần người xác nhận.

3. Giữ cho graph luôn mới: Định kỳ kiểm tra lại graph so với thực tế. Đây là việc các team hay bỏ qua nhất, mà lại là việc quan trọng nhất. Một graph không ai kiểm tra lại sẽ âm thầm trở thành một câu chuyện nghe có vẻ đúng nhưng hóa ra sai.

Schema của graph cấu trúc dự án trông như thế nào?

Đây là hình mẫu khởi điểm cho một graph phủ lên công việc bàn giao của chính team: story, requirement, code, test, và các quyết định thiết kế. Giữ nó gọn nhẹ, và để câu hỏi thật sự cần trả lời quyết định loại node và loại edge nào xứng đáng có mặt.

Node

NodeĐại diện choTrường dữ liệu chính
StoryMột hạng mục công việc.id, title, status, sprint
RequirementĐiều hệ thống phải làm được.id, text, priority
ModuleMột thành phần trong code.id, name, path
Test CaseMột phép kiểm tra hành vi.id, name, result
ADRMột quyết định kiến trúc.id, title, status
SkillMột automation tái sử dụng được.id, name, purpose

Edge: Mỗi edge chỉ nên tồn tại nếu nó trả lời được một câu hỏi thật.

EdgeNối gì với gìTrả lời câu hỏi
traces_toStory → RequirementStory này đáp ứng requirement nào?
realizesModule → StoryCode nào hiện thực hoá story này?
verifiesTest Case → StoryTest nào đang phủ story này?
depends_onModule → ModuleĐổi module này thì gãy chỗ nào?
constrainsADR → ModuleQuyết định nào đang ràng buộc thành phần này?
ownsSkill → ArtifactAutomation nào đang bảo trì cái này?

Schema cho graph tri thức rút ra từ tài liệu (GraphRAG)

Khi mình trích xuất entity và relationship từ một tập tài liệu (cách làm của GraphRAG) và quyết định lưu chúng vào một graph database, schema chính là thứ giữ cho kết quả có thể truy vấn được, thay vì trở thành một mớ bòng bong. Đây là hình mẫu khởi điểm cho entity và relationship rút ra từ một tài liệu hay kho tri thức.

Node

EntityĐại diện choTrường dữ liệu chính
DocumentMột file nguồn hay bài viết.id, title, source, date
ChunkMột đoạn văn bản trong tài liệu, giữ lại để truy vết ngược về nguyên văn.id, text, embedding
PersonMột cá nhân có tên.id, name, role
OrganizationMột công ty hoặc team.id, name, type
TopicMột chủ đề hay khái niệm.id, label
EventMột sự kiện xảy ra tại một thời điểm.id, name, date

Edge

RelationshipNối gì với gìÝ nghĩa
part_ofChunk → DocumentĐoạn văn này thuộc tài liệu đó.
mentionsChunk → Person / Org / TopicĐoạn văn này nhắc tới entity đó.
authored_byDocument → PersonAi là người viết.
works_forPerson → OrganizationTrực thuộc tổ chức nào.
related_toTopic → TopicCác khái niệm liên quan tới nhau.
occurred_onEvent → DateXảy ra khi nào.

Có thật sự cần một graph database không

Thường là không cần. Graph chỉ là node và edge, còn graph database chỉ là một cách để lưu chúng. Chỉ nên tính tới một graph database thật sự (hay cả pipeline GraphRAG) khi một trong các điều sau đúng:

  • Câu hỏi cần duyệt multi-hop thật sự, mà nếu làm bằng join lặp đi lặp lại thì rất cực.
  • Graph quá lớn, không thể nhét vừa vào context window hay một lần truy vấn.
  • Cần các thuật toán graph có sẵn như shortest path, community detection.
  • Nhiều agent hoặc hệ thống cùng đọc và ghi vào một graph đang thay đổi liên tục.

Còn nếu không cần database, thì lưu graph kiểu gì?

Node và edge mới là điều quan trọng, còn cách lưu chỉ là chi tiết kỹ thuật. Nếu không rơi vào bốn trường hợp ở trên, một trong các lựa chọn nhẹ nhàng sau thường là đủ, và tất cả vẫn giữ nguyên schema y như trên.

Lựa chọnTrông như thế nàoTruy vấn ra saoHợp khi nào
File phẳng (YAML / JSON)Một danh sách node và edge, commit thẳng vào git cạnh code.Load cả file, lọc bằng một script ngắn, hoặc đưa thẳng vào context của model.Vài trăm node, cập nhật theo nhịp sprint. Dễ đọc, dễ so sánh diff.
Bảng quan hệ (relational)Một bảng source, relationship, target trong database mình đã có sẵn (ví dụ Postgres).SQL thuần. Mỗi hop là một self-join.Đã có sẵn database quan hệ và ít khi cần hơn một, hai hop.
Graph trong bộ nhớ (in-memory)Xây lại từ nguồn mỗi lần chạy, giữ trong một đối tượng graph, rồi bỏ đi.Duyệt bằng code (ví dụ thư viện nhỏ như networkx).Xây lại rẻ, không cần lưu lại giữa các lần chạy.
Vector store cộng metadataCác đoạn tài liệu vẫn nằm trong vector store bình thường; liên kết entity nằm trong metadata của đoạn đó hoặc một bảng phụ nhỏ.Vector search tìm ra đoạn văn, rồi tra metadata để lần theo liên kết. Đây là kiểu “GraphRAG-lite”.Muốn phần lớn lợi ích “nối các điểm lại với nhau” của GraphRAG mà không cần dựng graph database.

Một lộ trình thực tế: bắt đầu với file phẳng, chuyển sang bảng quan hệ khi có nhiều công cụ cùng cần đọc nó, và chỉ chuyển sang graph database thật sự khi thật sự chạm tới nhu cầu multi-hop, quy mô lớn, hoặc thuật toán graph. Dù chọn cách nào, hãy đi kèm một lịch kiểm tra định kỳ và một ngày “kiểm tra lần cuối” hiển thị rõ ràng, vì một graph cũ còn tệ hơn không có graph.

Vậy có cần nhúng (embed) toàn bộ file vào vector store không?

Không cần, và với code thì cả ngành đang đi ngược lại với những gì mọi người hay mặc định. Claude Code và các công cụ tương tự không hề dựng sẵn một index nào cả. Chúng duyệt hệ thống file, đọc file, grep đúng thứ cần tìm, và lần theo tham chiếu, y như một kỹ sư thật sự làm, tất cả chạy tại chỗ, không cần index nào phải xây, bảo trì, hay upload lên đâu cả.

Vì sao embed toàn bộ codebase là rủi ro

Các công cụ dùng vector sẽ embed code và lấy các đoạn theo độ tương đồng lúc truy vấn. Với một team đang code liên tục, pipeline embed không theo kịp, nên một câu truy vấn có thể trả về một hàm đã bị đổi tên hai tuần trước, hoặc một module đã bị xoá từ sprint trước, mà chẳng có gì báo hiệu là nó đã lỗi thời. Chính đội ngũ Anthropic từng chia sẻ rằng bản đầu của Claude Code có thử dùng vector database, và nhận ra agentic search hoạt động tốt hơn hẳn khi thử nghiệm thật, một kết quả mà chính họ cũng thấy bất ngờ.

Vậy Claude dùng gì thay vào đó?

Cơ chếVai trò
CLAUDE.md / bản đồ repoChỉ cho agent đúng thư mục cần nhìn trước khi bắt đầu.
Grep trực tiếpKhớp chính xác trên cây thư mục hiện tại, không bao giờ lỗi thời.
Tra symbol (LSP)Lọc theo symbol thật, để một tên hàm phổ biến không trả về hàng trăm kết quả sai.
MCP serverKết nối tới công cụ nội bộ, ticket, tài liệu, hoặc để tự expose search như một tool gọi được.
SubagentGiữ cho một lần tìm kiếm lớn không làm rối context của agent đang thực sự làm việc.

Vậy vector retrieval có còn chỗ đứng không?

Không phải “RAG đã chết”. Khi mình không biết chính xác tên của thứ cần tìm, hoặc từ ngữ trong spec không khớp với từ ngữ trong code, một index theo nghĩa sẽ tìm ra thứ mà grep không thể. Đó chính xác là thứ embedding sinh ra để làm, và văn bản tự nhiên thay đổi chậm, nên vấn đề lỗi thời gần như không đáng lo ở đây.

Loại nội dungCách tiếp cận mặc địnhVì sao
Code và repo có cấu trúcAgentic search trước (bản đồ repo, grep, symbol). Chỉ thêm index ngữ nghĩa khi có một điểm đau cụ thể.Khớp chính xác thắng khớp mờ, và lỗi thời là rủi ro thật trên một repo đang hoạt động.
Kho văn bản (RFP, BRD, slide, blog)Kết hợp tìm theo từ khoá và vector, có rerank.Ý nghĩa quan trọng hơn từ ngữ chính xác, và nội dung thay đổi chậm.
Relationship giữa các artifactNgữ cảnh dạng graph, không phải search hay embedding.Chỉ một graph rõ ràng mới trả lời được “cái này phụ thuộc vào cái gì”.

Còn mấy công cụ như Graphify hay Understand-Anything thì sao?

Cả hai đều là công cụ mã nguồn mở (giấy phép MIT), gắn thêm vào các trợ lý code AI như Claude Code, Cursor, Copilot. Chúng quét một dự án, dựng một knowledge graph bền vững gồm file, hàm, class, và dependency, rồi cho phép trợ lý truy vấn graph hoặc dò đường đi thay vì grep từng file thô. Graphify nói rõ họ “không phải vector index, không embedding, mà là một graph thật sự có thể duyệt được”, xây chủ yếu từ cây cú pháp (syntax tree) cộng thêm một ít trích xuất bằng LLM, commit kết quả vào git, và có thể đẩy tuỳ chọn sang Neo4j. Understand-Anything làm tương tự và có thêm một dashboard tương tác để khám phá graph.

Nói theo ngôn ngữ ở phần trên, hai công cụ này chính là graph cấu trúc dự án, chỉ khác là được đóng gói sẵn để cài vào, thay vì mình tự xây tay. Nên câu trả lời thành thật là “còn tuỳ”, và cái được, cái mất đáng nói thẳng ra như sau:

Điểm đượcĐiểm cần cân nhắc
Cho câu trả lời multi-hop và phụ thuộc (“cái này nối gì với cái kia”) mà grep một mình không làm được, mà mình không cần tự thiết kế schema từ đầu.Đây là thêm một artifact nữa phải xây, giữ mới, và tin tưởng. Một graph bị cũ còn tệ hơn không có graph, đó là lý do cả hai đều dựa vào git hook để tự xây lại.
Phần lõi dựa trên cây cú pháp (deterministic) giữ cho phần lớn graph là sự thật, không phải đoán mò.Lớp trích xuất bằng LLM vẫn tốn token và có thể tạo nhiễu, cả hai dự án còn khá non trẻ với đội duy trì nhỏ.
Giấy phép MIT, commit được vào git, để cả team cùng xuất phát từ một bản đồ chung.Thêm bất kỳ công cụ AI của bên thứ ba nào cũng là một quyết định về chuỗi cung ứng và quản trị. Nên rà soát kỹ (ví dụ bằng một lượt quét độ tin cậy repo) trước khi dùng.

Tóm lại: với phần lớn công việc tìm kiếm code hàng ngày, các cách làm ở mục Claude dùng gì thay vào đó (bản đồ repo, grep trực tiếp, tra symbol) đơn giản hơn, miễn phí, và không bao giờ lỗi thời, nên hãy bắt đầu từ đó. Xem một công cụ graph như một thử nghiệm có phạm vi rõ ràng, dành cho trường hợp cụ thể là câu hỏi phụ thuộc và tác động xuất hiện thường xuyên, và việc onboard đang thật sự đau đầu, chứ đừng coi nó là nâng cấp mặc định. Nếu có thử, hãy tính luôn chi phí bảo trì, và xác nhận lợi ích về độ chính xác là có thật trước khi phụ thuộc vào nó.

Vậy dự án ngắn hạn, nhỏ và dự án dài hạn, lớn thì có khác nhau không?

Có, cách làm nên thay đổi theo quy mô và thời gian sống của dự án.

 Dự án ngắn hạn, quy mô nhỏDự án dài hạn, quy mô lớn
Tìm kiếm codeChỉ cần agentic search: bản đồ repo, grep, tra symbol. Không cần index dựng sẵn, không cần công cụ graph.Vẫn agentic search làm nền, thêm tra symbol khi grep bắt đầu nhiễu, và dùng subagent để tìm kiếm lớn không làm rối context chính.
Graph cấu trúcBỏ qua, hoặc chỉ cần một file nhỏ tự viết tay nếu thật sự cần câu trả lời về phụ thuộc.Đáng để đầu tư một graph được commit, tự cập nhật (tự xây tay hoặc dùng công cụ như trên) để phân tích tác động và giúp người mới onboard nhanh hơn.
Tài liệuĐọc trực tiếp, hoặc search từ khoá đơn giản là đủ.Kết hợp tìm từ khoá và vector trên các kho tài liệu thay đổi chậm (RFP, chính sách, kho tri thức).
Nơi dồn công sứcGiữ mọi thứ tinh gọn, tránh dựng hạ tầng mà mình sẽ không bảo trì nổi.Đầu tư vào vòng lặp bảo trì và kiểm tra định kỳ, vì đó mới là thứ giữ cho bất kỳ index hay graph nào còn đáng tin theo thời gian.

Tóm lại

Quay lại câu hỏi ban đầu: “Graph Engineering” có phải một ngành riêng không? Theo mình thì không, nó là một kỹ thuật rất hữu ích nằm bên trong context engineering, chứ không đứng ngang hàng với prompt, harness, hay loop engineering. Cách kiểm tra đơn giản mình hay dùng cho mọi thuật ngữ mới nghe được: thử diễn giải ý tưởng đó bằng lời thường, không dùng chính thuật ngữ đó. Nếu diễn giải được dễ dàng, có khi đó là một khái niệm thật, đáng học, giống như context, harness, hay loop engineering. Nếu không diễn giải nổi, cứ tạm coi nó là marketing cho tới khi nó qua được bài kiểm tra này.

Còn về graph cụ thể, ưu tiên xây nhẹ trước (file phẳng, kiểm tra định kỳ), chỉ leo thang lên graph database hay công cụ chuyên dụng khi thật sự chạm ngưỡng. Và luôn nhớ: một graph không ai kiểm tra lại còn nguy hiểm hơn không có graph nào cả.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.