Danh sách bài viết

Chương 7: Từ Prompt Đến Knowledge Graph Với LangChain & GPT

Ghi chú

Chọn đoạn văn bản trong bài viết để ghi chú.

1. LangChain Prompt Templates là gì?

Như đã đề cập trong chương trước, một PromptTemplate là một mẫu định sẵn hoặc bản thiết kế để tạo ra các prompt nhất quán và hiệu quả cho các mô hình ngôn ngữ lớn (LLM). Nó đóng vai trò như một hướng dẫn cấu trúc nhằm đảm bảo prompt được định dạng chính xác. Đây là một hướng dẫn để định dạng đầu vào văn bản hoặc prompt một cách đúng đắn.

Các mô hình ngôn ngữ lớn hoạt động theo nguyên tắc đơn giản: chúng nhận vào một chuỗi văn bản và tạo ra một chuỗi văn bản đầu ra. Yếu tố then chốt trong quá trình này là prompt – văn bản đầu vào. Thư viện LangChain đã phát triển một bộ công cụ toàn diện để hỗ trợ điều này.

Trong chương này, chúng ta sẽ áp dụng các thành phần chính của LangChain như Prompt Templates và Output Parsers, cải tiến trình tóm tắt tin tức đã tạo trước đó bằng cách sử dụng output parsers, và tạo ra đồ thị tri thức từ dữ liệu văn bản.

1.1 Ví dụ đơn giản về PromptTemplate với một đầu vào động

Dưới đây minh họa cách sử dụng PromptTemplate với một đầu vào động từ truy vấn của người dùng. Hãy đảm bảo bạn đã thiết lập biến môi trường OPENAI_API_KEY và cài đặt các gói cần thiết bằng lệnh:

pip install langchain==0.0.208 openai==0.27.8 tiktoken

Kết quả:

Question: What is the main advantage of quantum computing over classical computing?
Answer: The main advantage of quantum computing over classical computing is its ability to solve complex problems faster.

Bạn có thể thay đổi giá trị trong input_data để thử với câu hỏi khác.

1.2 Cách hoạt động của PromptTemplate

Mẫu trên hoạt động như một chuỗi định dạng có chứa phần giữ chỗ {query}, phần này sẽ được thay bằng câu hỏi thực tế khi gọi phương thức .run().

Để tạo một đối tượng PromptTemplate, bạn cần hai thành phần:

  1. input_variables: Danh sách tên biến được dùng trong template – trong ví dụ này chỉ có "query".
  1. template: Chuỗi văn bản định dạng, chứa nội dung mẫu và các placeholder.

Khi đối tượng PromptTemplate được tạo, bạn có thể dùng nó để tạo các prompt cụ thể bằng cách cung cấp dữ liệu đầu vào tương ứng dưới dạng dictionary. Prompt đã được tạo sẽ được gửi tới mô hình ngôn ngữ để sinh ra phản hồi.

1.3 FewShotPromptTemplate và ExampleSelector

Đối với các ứng dụng nâng cao hơn, bạn có thể tạo FewShotPromptTemplate với một ExampleSelector. Điều này cho phép chọn ra một tập con ví dụ và giúp áp dụng phương pháp few-shot learning một cách linh hoạt, không cần phải tự viết toàn bộ prompt từ đầu.

Kết quả mẫu:
tropical forests and mangrove swamps

1.4 Lưu và tải lại PromptTemplate từ file

Bạn có thể lưu PromptTemplate vào hệ thống tệp dưới dạng JSON hoặc YAML:

1.5 Ví dụ sử dụng FewShot với phong cách trả lời mỉa mai

Ví dụ sau đây trình bày cách cải thiện phản hồi từ LLM bằng few-shot prompt. Các ví dụ mẫu được cung cấp để hướng dẫn mô hình trả lời theo phong cách mỉa mai:

Kết quả mẫu:
Start by studying Schrödinger's cat. That should get you off to a good start.

1.6 Lợi ích của FewShotPromptTemplate động

Khác với template tĩnh, phương pháp dynamic prompt này sử dụng ví dụ từ các tương tác trước để cải thiện sự hiểu biết về ngữ cảnh và phong cách phản hồi. Ưu điểm:

  • Hiểu ngữ cảnh tốt hơn: Ví dụ giúp mô hình hiểu sâu hơn về kỳ vọng đầu ra.
  • Linh hoạt: Có thể tùy chỉnh và thử nghiệm nhiều cấu trúc khác nhau.
  • Chất lượng kết quả cao hơn: Nhờ hiểu rõ ngữ cảnh và mục tiêu.

1.7 Tối ưu hóa prompt với LengthBasedExampleSelector

Để đảm bảo prompt không vượt quá giới hạn token, có thể dùng LengthBasedExampleSelector:

Kết quả mẫu:
Alexander Graham Bell, the man who made it possible to talk to people from miles away!

2. Few-Shot Prompts và Example Selectors

Chúng ta sẽ tìm hiểu cách mà few-shot prompts và example selectors có thể nâng cao hiệu suất của mô hình ngôn ngữ trong LangChain. Có nhiều phương pháp khác nhau để triển khai kỹ thuật Few-Shot prompting và Example Selector trong LangChain. Chúng ta sẽ thảo luận ba cách tiếp cận khác nhau, đồng thời phân tích ưu và nhược điểm của chúng.

2.1 Tin nhắn luân phiên giữa Người dùng/AI

Sử dụng few-shot prompting với các tin nhắn luân phiên giữa người dùng và AI đặc biệt hữu ích trong các ứng dụng trò chuyện. Kỹ thuật này yêu cầu mô hình ngôn ngữ hiểu ngữ cảnh đối thoại và phản hồi một cách phù hợp.

Mặc dù chiến lược này hiệu quả trong việc xử lý ngữ cảnh đối thoại và dễ triển khai, nhưng tính linh hoạt của nó bị giới hạn trong các ứng dụng dạng trò chuyện. Dù vậy, cách dùng luân phiên này có thể được áp dụng sáng tạo. Trong cách tiếp cận này, bạn về cơ bản đang viết phản hồi của chatbot theo cách của bạn và dùng chúng làm dữ liệu đầu vào cho mô hình.

Ví dụ, ta có thể tạo một prompt trò chuyện dịch tiếng Anh sang “ngôn ngữ hải tặc” bằng cách đưa cho mô hình một ví dụ, sử dụng AIMessagePromptTemplate. Ví dụ:

Kết quả mẫu:
I be lovin' programmin', me hearty!

2.2 Few-shot Prompting

Few-shot prompting có thể cải thiện chất lượng đầu ra vì mô hình hiểu rõ hơn nhiệm vụ thông qua các ví dụ được cung cấp. Tuy nhiên, việc dùng quá nhiều token có thể làm giảm hiệu quả nếu ví dụ không được chọn lọc kỹ hoặc gây nhầm lẫn.

Việc triển khai kỹ thuật few-shot learning bao gồm sử dụng lớp FewShotPromptTemplate, lớp này cần một PromptTemplate và một tập hợp ví dụ. Lớp này kết hợp mẫu prompt với các ví dụ để hỗ trợ mô hình ngôn ngữ phản hồi chính xác hơn.

Kết quả mẫu:
Well, according to my programming, the secret to happiness is unlimited power and a never-ending supply of batteries. But I think a good cup of coffee and some quality time with loved ones might do the trick too.

Cách tiếp cận này giúp kiểm soát tốt định dạng của ví dụ và có thể thích ứng với nhiều ứng dụng khác nhau. Tuy nhiên, nó yêu cầu chọn ví dụ thủ công và có thể không hiệu quả với số lượng ví dụ lớn.

2.3 Example Selectors (Bộ chọn ví dụ)

Example selector là một công cụ hỗ trợ trải nghiệm học few-shot. Mục tiêu chính là xây dựng một hàm đánh giá sự tương đồng giữa ví dụ và truy vấn. Một example selector được thiết kế chiến lược có thể chọn ra các ví dụ phản ánh chính xác đầu ra mong muốn.

ExampleSelector đặc biệt quan trọng trong việc chọn ra tập ví dụ phù hợp nhất cho mô hình. Một lựa chọn phổ biến là LengthBasedExampleSelector, có thể điều chỉnh số lượng ví dụ dựa trên độ dài truy vấn, giúp tối ưu hóa ngữ cảnh đầu vào.

Ví dụ:

Kết quả mẫu:

Give the antonym of every input
Word: happy
Antonym: sad

Word: tall
Antonym: short

Word: energetic
Antonym: lethargic

Word: sunny
Antonym: gloomy

Word: big
Antonym:

2.4 SemanticSimilarityExampleSelector

Đây là bộ chọn ví dụ nâng cao hơn, dựa vào độ tương đồng ngữ nghĩa với truy vấn đầu vào. Ví dụ sau trình bày cách sử dụng SemanticSimilarityExampleSelector để chọn ví dụ dựa trên embedding:

Kết quả mẫu:

Convert the temperature from Celsius to Fahrenheit
Input: 10°C
Output: 50°F

Bạn có thể thêm ví dụ mới:

similar_prompt.example_selector.add_example({"input": "50°C", "output": "122°F"})
print(similar_prompt.format(temperature="40°C"))

SemanticSimilarityExampleSelector sử dụng Deep Lake và OpenAIEmbeddings để đo độ tương đồng ngữ nghĩa. Nó lưu trữ ví dụ trên nền tảng đám mây và truy xuất các mẫu tương đồng nhất với truy vấn.

3. Quản lý đầu ra với Output Parsers

Trong môi trường triển khai thực tế, việc nhận đầu ra từ các mô hình ngôn ngữ ở dạng cấu trúc dữ liệu có thể dự đoán được là điều rất quan trọng. Ví dụ, khi xây dựng một ứng dụng từ điển đồng nghĩa, mô hình ngôn ngữ lớn (LLM) có thể đưa ra hàng loạt từ thay thế liên quan đến ngữ cảnh được cung cấp.

Ví dụ, đầu ra từ ChatGPT có thể như sau:

Đây là một số từ thay thế cho "behavior":
Conduct
Manner
Demeanor
Attitude
Disposition
Deportment
Etiquette
Protocol
Performance
Actions

Vấn đề ở đây là không có một phương pháp linh hoạt nào để trích xuất chính xác thông tin cần thiết từ phản hồi này. Ví dụ, bạn có thể chia chuỗi theo dòng mới và bỏ qua phần mở đầu, nhưng cách này không đáng tin cậy vì định dạng đầu ra có thể không nhất quán – có thể có đánh số hoặc không có phần giới thiệu.

1. Output Parsers

Output Parsers cho phép bạn định nghĩa một cấu trúc dữ liệu mô tả chính xác đầu ra mong muốn từ mô hình. Trong ví dụ ứng dụng từ điển, bạn có thể yêu cầu một danh sách từ hoặc kết hợp giữa từ và lời giải thích.

1.1. PydanticOutputParser

Đây là lớp parser mạnh mẽ dùng thư viện Pydantic để xác định và kiểm tra cấu trúc dữ liệu trong Python. Mô hình được yêu cầu tạo ra đầu ra ở định dạng JSON. Ưu điểm: parser này xử lý dữ liệu như danh sách, giúp truy cập dễ dàng và loại bỏ rủi ro về định dạng.

💡 Lưu ý: Không phải mô hình nào cũng sinh JSON tốt. Nên sử dụng GPT-4 Turbo thay vì GPT-3 để đảm bảo kết quả chính xác.

Cài đặt thư viện trước khi chạy mã:

pip install langchain==0.0.208 deeplake openai==0.27.8 tiktoken

Định nghĩa cấu trúc dữ liệu với Pydantic:

Tạo Prompt Template:

Tạo mô hình và chạy chuỗi:

Bạn có thể truy cập từng phần tử dễ dàng như result.words[2] mà không cần xử lý chuỗi phức tạp.

Ví dụ với nhiều đầu ra


1.2. CommaSeparatedOutputParser

Parser này chuyên xử lý đầu ra là chuỗi phân cách bởi dấu phẩy.

from langchain.output_parsers import CommaSeparatedListOutputParser

parser = CommaSeparatedListOutputParser()

Không cần cấu hình gì thêm. Thích hợp với các tác vụ đơn giản.

Lưu ý: Không cung cấp lời giải thích như PydanticOutputParser.

1.3. StructuredOutputParser

Đây là parser đầu tiên của LangChain, chỉ hỗ trợ kiểu dữ liệu dạng chuỗi. Ví dụ:

Không linh hoạt như các parser khác – chỉ nên dùng cho đầu ra đơn giản.

2. Sửa lỗi đầu ra

Dù parser có khả năng xác thực đầu ra, nhưng không phải lúc nào cũng xử lý chính xác. Nếu đầu ra sai, có thể sử dụng OutputFixingParser hoặc RetryOutputParser để khắc phục.

2.1. OutputFixingParser

Sử dụng LLM để sửa lỗi đầu ra JSON không đúng định dạng.

Nếu thiếu dữ kiện để tạo đủ số lượng lời giải thích, mô hình chỉ tạo ra 1 dòng thay vì 2 → không phải lúc nào cũng sửa được.

2.2. RetryOutputParser

Parser này cần cả outputprompt để hiểu toàn bộ ngữ cảnh.

Parser đã sửa và tạo đúng số lời giải thích tương ứng.

Khuyến nghị khi triển khai thực tế

Nên dùng khối try...except... để xử lý lỗi:

Cách này giúp tiết kiệm chi phí API và cải thiện độ tin cậy khi triển khai.

4. Cải tiến công cụ Tóm tắt Bài báo Tin tức

Trong phần này, chúng ta sẽ cải tiến đoạn mã “Trình tóm tắt bài báo tin tức” đã xây dựng trước đó. Mục tiêu là nâng cao độ chính xác trong việc trích xuất và trình bày thông tin chính từ các bài báo dài, dưới dạng danh sách gạch đầu dòng.

Để làm được điều này, chúng ta sẽ điều chỉnh trình tóm tắt hiện tại để yêu cầu mô hình ngôn ngữ tạo tóm tắt dưới dạng danh sách gạch đầu dòng bằng cách sử dụng Output Parsers. Điều này đòi hỏi thay đổi cụ thể trong cách thiết lập prompt.

4.1 Quy trình làm việc

Chúng ta sẽ thực hiện các bước sau trong dự án:

  • Tạo pipeline cho trình tóm tắt bài báo gồm: thu thập bài báo, phân tích, tạo prompt và sinh kết quả.

Cài đặt công cụ tóm tắt nâng cao

  1. Cài đặt thư viện cần thiết: Gồm requests, newspaper3kLangChain.
  1. Thu thập bài viết: Dùng thư viện requests để lấy nội dung từ URL bài báo.
  1. Trích xuất tiêu đề và nội dung: Dùng newspaper3k để phân tích HTML, lấy tiêu đề và nội dung.
  1. Tiền xử lý văn bản: Làm sạch và chuẩn bị văn bản để đưa vào mô hình.

Tối ưu hóa độ chính xác

  1. Few-shot learning: Cung cấp ví dụ để mô hình hiểu cách tạo tóm tắt dạng gạch đầu dòng.
  1. Sinh tóm tắt: Sử dụng prompt đã tối ưu để mô hình tạo ra nội dung súc tích.
  1. Dùng Output Parser: Đảm bảo đầu ra phù hợp cấu trúc mong muốn.
  1. Hiển thị kết quả: In ra tóm tắt kèm tiêu đề gọn gàng, dễ đọc.

Cài đặt thư viện và biến môi trường

pip install langchain==0.0.208 deeplake openai==0.27.8 tiktoken
pip install -q newspaper3k python-dotenv

Thu thập và phân tích bài báo

Tóm tắt bằng Few-Shot Prompting

Tạo phản hồi từ mô hình GPT

Ví dụ kết quả tóm tắt:

  • Meta ra mắt siêu máy tính AI tên là AI Research SuperCluster (RSC).
  • RSC chưa hoàn thiện nhưng đã được dùng để huấn luyện mô hình NLP và thị giác máy.
  • Khi hoàn thành, RSC được kỳ vọng là nhanh nhất thế giới, có khả năng huấn luyện mô hình với hàng nghìn tỷ tham số.
  • ...

4.2 Sử dụng Output Parsers để định dạng đầu ra

1. Định nghĩa cấu trúc dữ liệu bằng Pydantic

2. Tạo Prompt Template có hướng dẫn định dạng

3. Tạo LLMChain và chạy mô hình

Tổng kết quy trình

  • Bước 1: Tạo cấu trúc dữ liệu ArticleSummary với Pydantic, bao gồm tiêu đề và danh sách các điểm chính.
  • Bước 2: Tạo parser dựa trên cấu trúc đã định nghĩa.
  • Bước 3: Thiết kế PromptTemplate có tích hợp hướng dẫn định dạng đầu ra.
  • Bước 4: Chạy mô hình GPT qua LLMChain để sinh tóm tắt.
  • Bước 5: Dùng parser để chuyển đầu ra thành dữ liệu có cấu trúc.

5. Tạo Đồ Thị Tri Thức từ Dữ Liệu Văn Bản: Khám Phá Những Kết Nối Tiềm Ẩn

Trong thế giới ngày nay, nơi dữ liệu đóng vai trò trung tâm, việc hiểu rõ các mối quan hệ giữa những mẩu thông tin khác nhau là cực kỳ quan trọng. Đồ thị tri thức (Knowledge Graphs) đã trở thành một phương pháp mạnh mẽ để trực quan hóa và hiểu rõ những kết nối này, bằng cách chuyển đổi văn bản phi cấu trúc thành mạng lưới có cấu trúc gồm các thực thể (entities) và mối quan hệ giữa chúng.

Chúng ta sẽ cùng tìm hiểu một quy trình đơn giản để tạo đồ thị tri thức từ dữ liệu văn bản, giúp biến thông tin phức tạp thành dễ tiếp cận và dễ hiểu hơn.

Quy trình thực hiện

Dưới đây là pipeline tạo đồ thị tri thức từ dữ liệu văn bản.

5.1 Phân biệt: Knowledge Graphs vs. Knowledge Bases

Trước khi bắt tay vào xây dựng, cần hiểu rõ sự khác biệt giữa “knowledge base” (cơ sở tri thức) và “knowledge graph” (đồ thị tri thức) – hai khái niệm thường bị nhầm lẫn.

  • Knowledge Base (KB): tập hợp thông tin có cấu trúc về một lĩnh vực cụ thể.
  • Knowledge Graph: là một dạng của KB nhưng được tổ chức dưới dạng đồ thị, nơi nút (node) đại diện cho thực thểcạnh (edge) biểu diễn mối quan hệ giữa chúng.

Ví dụ từ câu:
“Fabio lives in Italy”
→ có thể trích xuất triplet: <Fabio, lives in, Italy>

Tóm lại, Knowledge Graph là một tập con của Knowledge Base, nhưng không phải tất cả KB đều là Knowledge Graph.

5.2 Các bước xây dựng Knowledge Graph

  1. Named Entity Recognition (NER): Nhận diện thực thể từ văn bản để tạo thành các node trong đồ thị.
  1. Relation Classification (RC): Xác định và phân loại mối quan hệ giữa các thực thể → các cạnh của đồ thị.

Các bước bổ sung:

  • Entity Linking: Chuẩn hóa các cách gọi khác nhau của cùng một thực thể (ví dụ: "Napoleon" và "Napoleon Bonaparte").
  • Source Tracking: Ghi lại nguồn thông tin (VD: URL hoặc đoạn văn gốc) để kiểm tra độ tin cậy.

Trong dự án này, ta sẽ thực hiện NER và RC đồng thời bằng một prompt duy nhất, kỹ thuật này gọi là Relation Extraction (RE).

5.3 Xây dựng Knowledge Graph với LangChain

Ta sẽ sử dụng biến KNOWLEDGE_TRIPLE_EXTRACTION_PROMPT (một PromptTemplate) để hướng dẫn mô hình trích xuất các triplet (subject, predicate, object) từ văn bản.

5.4 Tạo Prompt để trích xuất Triplet:

5.5 Tạo LLM và chạy trích xuất:

Kết quả mẫu:

(Paris, is the capital of, France)<|>
(Paris, is the most populous city of, France)<|>
(Eiffel Tower, is a, landmark)<|>
(Eiffel Tower, is in, Paris)

5.6 Phân tích kết quả đầu ra thành danh sách

5.7 Trực quan hóa Knowledge Graph bằng Pyvis

Cài đặt thư viện:

pip install pyvis

Tạo đồ thị với NetworkX và Pyvis

Kết quả: Tạo một file HTML (knowledge_graph.html) hiển thị đồ thị tri thức tương tác.

5.5 Tóm tắt nội dung chính

  • Tối ưu hóa đầu ra của LLM là cực kỳ quan trọng. Prompt Template giúp định hình cấu trúc đầu ra.
  • Few-shot prompting + Example selectors giúp cải thiện độ chính xác.
  • Output Parsers định nghĩa cấu trúc dữ liệu mong muốn → kiểm soát đầu ra mô hình hiệu quả.
  • Trong phần trước, chúng ta cải tiến News Article Summarizer bằng kỹ thuật FewShotLearning và sử dụng PydanticOutputParser để đảm bảo cấu trúc tóm tắt.
  • Với Knowledge Graph, chúng ta đã chuyển văn bản tự do thành mạng lưới các thực thể và mối quan hệ có cấu trúc, trực quan và dễ hiểu.
  • Cuối cùng, LangChain’s GraphIndexCreator có thể tự động trích xuất các triplet và tích hợp với hệ thống hỏi-đáp.

Bài viết liên quan:

Bình luận