iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
生成式 AI

阿,又是一個RAG系列 第 6

Day5: 從 Youtube 下載的字幕生成問題與答案對

  • 分享至 

  • xImage
  •  

Situation:

  • 我們想要替RAG系統獲得成對的 (context, question, answer) 供後續方法論的驗證
  • 在day1-get_context_from_YT,我們已經從youtube url獲取了字幕,並存成txt檔
  • 在day2-RagDatasetGenerator,我們成功從切好的context 生成 question

Task:

  • 今天要我們會更進一步的把 (context, question, answer) 生成出來。

Action:

  1. 開頭還是先設置環境,還有 llm 的 setup
from dotenv import find_dotenv
from dotenv import load_dotenv
print(find_dotenv())
succ = load_dotenv(find_dotenv())
if not succ:
    raise ValueError('load_dotenv FALSE')

# llm setup
from llama_index.llms.openai import OpenAI
# set context for llm provider
llm = OpenAI(model="gpt-5-mini", temperature=0.0)
  1. 把我們的先前載回來的字幕檔讀取成 list of Llama-index 的 document
# document setup
# read document
from llama_index.core import SimpleDirectoryReader
source_dir = '../data/'
reader = SimpleDirectoryReader(source_dir, required_exts=['.txt'])
documents = reader.load_data()
  1. 把讀進來的 list of document 切成 nodes
  • 我們上回是直接用 RagDatasetGenerator.from_documents 生成問題,這回是打算從 node 開始
  • 好處就是可以自己切,然後壞處是要自己切,河河。
  • 基本上 llamaindex 有一大堆有的沒的 splitter 你可以放輕鬆的任意選一個
# simple node parser
## reference: https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/
## https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/
from llama_index.core.node_parser import SentenceSplitter
CHUNK_SIZE = 1024
CHUNK_OVERLAP = 20
SEPARATOR = " ?!;。!?;\n"

node_parser = SentenceSplitter(chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP, separator=SEPARATOR)

nodes = node_parser.get_nodes_from_documents(
    documents, show_progress=False
)
  1. 配置 prompt
from llama_index.core.prompts.base import PromptTemplate
num_questions_per_chunk = 1

text_question_template = PromptTemplate(
    f"""你是一位專業的課程助教,你的任務是根據上課內容的片段,設計 {num_questions_per_chunk} 個問題來問學生。
問題風格以單一且直接的問句為主,並且需要在上課內容中找得到答案。
若是要求出複數題,則問題應該盡可能涵蓋不同的面向。

範例輸入:
以下是上課內容片段:
---------------------
"業設計成這樣呢\n為什麼作業要跑三個小時呢\n我只允許這個作業三分鐘\n就應該要>跑完\n我們有當然可以把這些特別花時間\n需要特別花時間訓練的作業拿掉\n但是我還是選>擇在這門課裡面\n保留那一些\n需要一定訓練時間的作業\n因為焦躁的等待人工智慧訓練的結果\n迷茫的調參數\n不知道會不會成功\n這個就是人工智慧的醍醐味\n所以大家需要學習\n在迷茫中前進\n這個就是模型的訓練\n我們特別把這一部分保留在課程裡面\n讓你體驗說\n模型訓練不出來的焦躁\n到底是什麼樣的感覺\n而且我必須要強調啊\n什麼三四個小時的等待訓練時間\n真的不算什麼\n我們過去有很多作業訓練時間都是\n至少三天起跳\n你要至少訓練三天\n你才能夠拿到成績\n那我知道說很多同學在做作業的時候\n往往你都在實現\n最後一天才開始做作業\n但那一種啊\n需要訓練三天以上的模型\n你只在前一天才開始做作業\n你是絕不可能完成的\n這個時候我告訴你\n你唯一可以做的事情\n就是放棄這樣子\n還好我們這堂課裡面呢\n現在是沒有需要訓練一天以上的作業啦\n我們把那種\n特別需要花時間訓練的作業\n還是拿掉了\n只保留了需要訓練三四個小時的作業\n但我只想要強調說\n三四個小時的訓練時間\n真的不算什麼\n如果你要真正用大量的資料\n大規模的訓練模型\n訓練個數週\n其實都是常見的事情\n而這一些\n需要一點訓練時間的作業\n它的定位就像是預防針\n幫助你在未來面對更大的挑戰\n幫助你在未來面對挑戰的時候\n做好心理準備\n另外呢\n鼓勵大家如果有空的話\n可以先看一些線上的錄影進行預習\n那假設你對於生成式AI一無所知的話\n那你可以先看生成式AI導論2024的課程\n那如果2024的課程看完\n你想要進一步了解\n這些AI是怎麼被訓練出來的"
---------------------
範例輸出:
什麼是深度學習的醍醐味?

輸入:
以下是上課內容片段:
---------------------
{{context_str}}
---------------------{{query_str}}
"""
)

text_qa_template = PromptTemplate("""以下是背景資訊。
---------------------
{context_str}
---------------------
僅根據上述背景資訊,而非先驗知識,回答下列問題。
問題:{query_str}
答案:""")

question_gen_query = '輸出:\n'
  • 這邊有 3 個變數:
    • text_question_template
      • 這個是生成問題用的
      • 他是 PromptTemplate
      • 包的是 f-string 所以這邊 num_questions_per_chunk 就會被填上了
      • 他的 input variable 有 context_str 跟 query_str
    • question_gen_query
      • 這個也是生成問題用的
      • 他是string
      • 基本上它就是會被當成 text_question_template 的 query_str 變數填進去
    • text_qa_template
      • 這個是生成答案用的
      • 他是 PromptTemplate
  1. 這邊是預設的 prompt 提供參照
DEFAULT_QUESTION_GENERATION_PROMPT = """\
Context information is below.
---------------------
{context_str}
---------------------
Given the context information and not prior knowledge.
generate only questions based on the below query.
{query_str}
"""

DEFAULT_TEXT_QA_PROMPT_TMPL = (
    "Context information is below.\n"
    "---------------------\n"
    "{context_str}\n"
    "---------------------\n"
    "Given the context information and not prior knowledge, "
    "answer the query.\n"
    "Query: {query_str}\n"
    "Answer: "
)
DEFAULT_TEXT_QA_PROMPT = PromptTemplate(
    DEFAULT_TEXT_QA_PROMPT_TMPL, prompt_type=PromptType.QUESTION_ANSWER
)

self.question_gen_query = (
            question_gen_query
            or f"You are a Teacher/Professor. Your task is to setup {num_questions_per_chunk} questions for an upcoming quiz/examination. The questions should be diverse in nature across the document. Restrict the questions to the context information provided."
        )
  1. 初始化 RagDatasetGenerator
from llama_index.core.llama_dataset.generator import RagDatasetGenerator
dataset_generator = RagDatasetGenerator(
    nodes,  # 第 3 步切的
    llm=llm,  # 第 1 步配置了
    num_questions_per_chunk=num_questions_per_chunk,  # 第 4 步  
    text_question_template = text_question_template,  # 第 4 步
    text_qa_template = text_qa_template,  # 第 4 步
    question_gen_query = question_gen_query,  # 第 4 步
    show_progress=True,
)
  1. generate_dataset and dump
rag_dataset = dataset_generator.generate_dataset_from_nodes()
df = rag_dataset.to_pandas()
df.to_csv(save_file_path, index=False)
  1. 結果
    結果的dataframe 看起來會是這個樣子:
    https://ithelp.ithome.com.tw/upload/images/20250920/20177855fgaSA2jwNA.jpg

會有 5 個欄位,分別是:

  • query: 就是生成的問題
  • reference_contexts: 就是前面的 node
  • refenrece_answer: 就是第二部分生成的 answer
  • reference_answer_by: 是誰提供這個 answer 的
  • query_by: 是誰提供這個query的

關於這些欄位哪來的,可以參考 官網介紹

  • 後續用其他方法造的 dataset 也會盡量對齊這個格式,來讓我們更後面的 evaluation 可以順利一點
  1. Langfuse Result
  • 問題生成部分的 Langfuse trace 在 這裡
  • 答案生成部分的 Langfuse trace 在 這裡
  • 這個就是在呼叫的時候把 day3_observability 的設置套上去就可以跑出來的結果
  1. RagDatasetGenerator
  • 基本上使用 RagDatasetGenerator 的過程就是
    • initial: 這個我們在 day2 和 day5 總共做了兩次
    • question_gen: 參考 day2
    • dataset_gen: 這個就是今天新增的結果,在問題生成的基礎上,再用配好的 context 來 prompt llm 回答
  • 有興趣深挖的可以看:llama_dataset/generator.py/RagDatasetGenerator
    • 當然是貼給chatgpt叫他幫你看

Summary:

  • 我們今天完成了當初規劃的 主題 1.1: 從 context 生成 (question, answer, context) pair
  • RagDatasetGenerator 生成的主要路徑是: documents -> node -> question -> answer
    • 這部分應該也可以輕易的做到從 node -> (question, answer) 阿你就 prompt llm 做
  • 多認識了 llama_dataset 這樣的格式,後續也會有意識的把我們這次的資料集統一成這個格式。

Reference


上一篇
Day4: Langfuse 上的 Tracing 是怎麼來的,以及怎麼從 Langfuse 拿資料
下一篇
Day6: pdf2txt 使用 llama-parse 與 mistral-ocr
系列文
阿,又是一個RAG8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言