Tổng Kết Tài Liệu Thực Hiện Ứng Dụng AI Quy Mô Lớn Bằng LangChain

Phần I: Tư Duy Tổng Thể

Với văn bản dài vượt quá giới hạn token của mô hình ngôn ngữ lớn (LLM), cần thiết kế một pipeline **map-reduce** để chia nhỏ, tóm tắt từng phần và tổng hợp:
  1. Tải nội dung trang web.
  2. Chia thành các chunk có kích thước kiểm soát được.
  3. Tóm tắt ban đầu cho mỗi chunk (map).
  4. Tổng hợp tất cả các tóm tắt ban đầu (reduce).
  5. Nếu cần, lặp lại bước reduce cho đến khi đáp ứng giới hạn token.
  6. Xuất ra tóm tắt cuối cùng.
Bây giờ, chúng ta sẽ thực hiện bằng mã.

Phần II: Chuẩn Bị

1. Khởi Tạo LLM

Đầu tiên, sử dụng `initialize_model` để tải LLM:
<!-- langchain_env.py -->
from langchain_core.models import initialize_model

model = initialize_model("gpt-4s-mini", provider="openai")

Phần III: Chương Trình Chính main.py

1. Nhập Thư Viện & Khởi Tạo

import os
import sys

sys.path.append(os.getcwd())

from langchain_docs.loaders import WebPageLoader
from langchain.chains.combine_documents import create_merge_chain
from langchain.chains.llm import LanguageModelChain
from langchain.prompts import TemplatePrompt
from langchain.text_splitters import TokenTextSplitter
from typing import List, Dict
from langchain.chains.reduce import merge_docs, split_doc_list
from langchain.documents import Document
from langflow.constants import Execute
from langflow.graph import ENDPOINT, START_POINT, FlowGraph

from llm_setup import langchain_env

model = langchain_env.model

2. Tải Trang Web

loader = WebPageLoader("https://en.wikipedia.org/wiki/Machine_Learning")
documents = loader.load()
Dùng WebPageLoader để tải nội dung trang web vào danh sách `documents`.

3. Định Nghĩa Mẫu Prompt

- Map Phase Prompt
map_template = TemplatePrompt.from_messages(
    [("system", "Tóm tắt ngắn gọn đoạn sau:\\n\\n{content}")]
)
- Reduce Phase Prompt
reduce_template = """
Dưới đây là một loạt các tóm tắt:
{docs}
Hãy tổng hợp và rút gọn thành một tóm tắt chính thống.
"""

reduce_prompt = TemplatePrompt([("user", reduce_template)])

4. Chia Đơn Vị Văn Bản Chunk

text_splitter = TokenTextSplitter(chunk_size=800, overlap=0)
split_docs = text_splitter.split_documents(documents)
print(f"Đã chia thành {len(split_docs)} chunks")
Chia nội dung trang web thành nhiều chunk, mỗi chunk có kích thước 800 tokens.

5. Định Nghĩa Hàm Tính Số Tokens

max_tokens = 800

def calc_token_length(docs: List[Document]) -> int:
    return sum(model.get_num_tokens(d.page_content) for d in docs)
Tính tổng số token của tài liệu đầu vào để quyết định có cần tiếp tục gộp hay không.

6. Định Nghĩa Trạng Thái

Trạng thái chính:
class GlobalState(Dict):
    contents: List[str]
    summaries: List[str]
    merged_summaries: List[Document]
    final_summary: str
Trạng thái giai đoạn map:
class SummarizeState(Dict):
    content: str

7. Tạo Tóm Tắt Ban Đầu (Giai Đoạn Map)

def create_initial_summary(state: SummarizeState):
    prompt = map_template.invoke(state["content"])
    response = model.invoke(prompt)
    return {"summaries": [response.content]}

8. Logic Điều Phối Map

def map_tomato_states(state: GlobalState):
    return [
        Execute("create_initial_summary", {"content": content}) for content in state["contents"]
    ]

9. Thu Gom Tóm Tắt

def collect_summaries(state: GlobalState):
    return {
        "merged_summaries": [Document(summary) for summary in state["summaries"]]
    }

10. Logic Reduce

- Hàm Reduce Nội Bộ
def _merge(input: dict) -> str:
    prompt = reduce_prompt.invoke(input)
    response = model.invoke(prompt)
    return response.content
- Gộp Các Tóm Tắt
def merge_summaries(state: GlobalState):
    doc_lists = split_doc_list(
        state["merged_summaries"],
        calc_token_length,
        max_tokens,
    )

    results = []
    for doc_list in doc_lists:
        combined = merge_docs(doc_list, _merge)
        results.append(combined)

    return {"merged_summaries": results}

11. Kiểm Tra Tiếp Tục Gộp

def check_merge_needed(state: GlobalState):
    num_tokens = calc_token_length(state["merged_summaries"])
    if num_tokens > max_tokens:
        return "merge_summaries"
    else:
        return "generate_final_summary"

12. Tạo Tóm Tắt Cuối Cùng

def generate_end_summary(state: GlobalState):
    response = _merge(state["merged_summaries"])
    return {"final_summary": response}

Phần IV: Xây Dựng Sơ Đồ Lưu Trình (FlowGraph)

graph = FlowGraph(GlobalState)

graph.add_node("create_initial_summary", create_initial_summary)
graph.add_node("collect_summaries", collect_summaries)
graph.add_node("merge_summaries", merge_summaries)
graph.add_node("generate_end_summary", generate_end_summary)

graph.add_conditional_edges(START_POINT, map_tomato_states, ["create_initial_summary"])
graph.add_edge("create_initial_summary", "collect_summaries")
graph.add_conditional_edges("collect_summaries", check_merge_needed)
graph.add_conditional_edges("merge_summaries", check_merge_needed)
graph.add_edge("generate_end_summary", ENDPOINT)

app = graph.compile()

Phần V: Thực Thi Quy Trình Tóm Tắt

for step in app.stream(
    {"contents": [doc.page_content for doc in split_docs]},
    {"recursion_limit": 10},
):
    print(list(step.keys()))
Sử dụng `.stream()` để khởi động toàn bộ pipeline, truyền dữ liệu đã cắt, xuất kết quả theo dòng chảy cho đến khi hoàn thành.

Thẻ: langchain LLM python web scraping Machine Learning

Đăng vào ngày 31 tháng 5 lúc 16:31