利用 OpenAI 的強大微調功能,可以針對特定領域知識,例如科學問答,開發專屬的 AI 模型。首先,需要準備高品質的訓練資料集,SciQ 資料集就是一個不錯的選擇。接著,將資料集轉換成 OpenAI 接受的 JSONL 格式,並上傳至 OpenAI 平台進行微調訓練。訓練過程中,可以透過 OpenAI 提供的 API 監控任務進度和狀態。訓練完成後,即可使用微調後的模型進行科學問答。過程中,向量資料函式庫技術可以有效提升查詢效率,快速找到相關資訊。

解鎖 RAG 的力量:建構客製化增強生成式 AI 知識函式庫

遠古植物的能量轉換與化石燃料的形成

數百萬年前,植物如何利用太陽能?它們又是如何轉變為我們今天使用的化石燃料?讓我們一起探索這個奇妙的過程。

玄貓在研究古植物能量轉換時,發現了一個有趣的現象:遠古植物利用太陽能形成葉綠體,將光能轉化為化學能儲存在食物中。這些食物不僅滋養了植物本身,也為食用植物的生物提供了能量來源。

圖表翻譯: 上圖展示了太陽能如何透過葉綠體轉化為食物,並滋養植物及其他生物的過程。太陽能首先被葉綠體捕捉,接著轉化為化學能儲存在食物中。這些食物一部分被植物用於自身生長,另一部分則供給其他生物作為能量來源。

隨著時間推移,植物和其他生物死亡後,它們的遺骸逐漸被沉積物覆寫和壓縮,最終轉化為化石燃料。海洋生物形成了石油和天然氣,而巨大的樹蕨和其他沼澤植物則形成了煤炭。

圖表翻譯: 此圖表說明瞭不同型別的生物遺骸如何在地質作用下轉化為不同的化石燃料。植物和生物的遺骸在被沉積物覆寫和壓縮後,根據其來源的不同,分別形成了石油、天然氣和煤炭等化石燃料。

玄貓認為,深入研究古植物的能量轉換機制,不僅能幫助我們理解地球的歷史,還能啟發我們開發新的可再生能源技術。例如,模仿葉綠體的光合作用原理,可以開發人工光合作用系統,將太陽能轉化為化學能,為人類提供清潔能源。

以下程式碼示範如何使用 spaCy 計算兩個文字之間的相似度:

# 匯入必要的函式庫
import spacy

# 載入英文語言模型
nlp = spacy.load("en_core_web_sm")

# 定義計算文字相似度的函式
def simple_text_similarity(text1, text2):
    # 將輸入文字轉換為 spaCy 的 Doc 物件
    doc1 = nlp(text1)
    doc2 = nlp(text2)
    # 計算並傳回兩個 Doc 物件之間的相似度
    return doc1.similarity(doc2)

# 定義兩個範例文字
original_completion = "Mesophilic organisms because Mesophiles grow best in moderate temperature"
retrieved_document = "lactic acid because Bacteria can be used to make lactic acid"

# 呼叫函式計算相似度並儲存結果
similarity_score = simple_text_similarity(original_completion, retrieved_document)

# 列印相似度得分
print(f"Similarity Score: {similarity_score:.2f}")

內容解密:

這段程式碼使用了 spaCy 函式庫來計算兩個文字之間的相似度。首先,它載入了一個預訓練的英文語言模型 en_core_web_sm。接著,定義了一個名為 simple_text_similarity 的函式,該函式接受兩個文字字串,透過 spaCy 將它們轉換為 Doc 物件,並計算它們之間的相似度。最後,程式碼使用兩個範例文字呼叫該函式,並列印出計算得到的相似度得分。

以下程式碼示範如何使用 Llama 2 生成文字摘要:

# 匯入必要的函式庫
from transformers import pipeline

# 設定並載入 Llama 2 模型,用於文字生成任務
pipeline = pipeline(
    "text-generation",
    model="meta-llama/Llama-2-7b-chat-hf",
    device_map="auto",
)

# 定義使用 Llama 2 模型生成文字的函式
def LLaMA2(prompt):
    # 使用設定的引數生成文字序列
    sequences = pipeline(
        prompt,
        do_sample=True,
        top_k=10,
        num_return_sequences=1,
        max_new_tokens=100,
        temperature=0.5,
        repetition_penalty=2.0,
        truncation=True
    )
    # 傳回生成的文字序列
    return sequences

# 定義輸入提示
prompt = "Millions of years ago, plants used energy from the sun to form what?"

# 呼叫 LLaMA2 函式生成摘要並儲存結果
summary = LLaMA2(prompt)[0]['generated_text']

# 列印生成的摘要
print(summary)

內容解密:

這段程式碼使用了 Hugging Face 的 Transformers 函式庫來載入並使用預訓練的 Llama 2 模型進行文字生成。首先,它設定了一個 pipeline 物件,用於執行文字生成任務,並指定了使用的模型和裝置。接著,定義了一個名為 LLaMA2 的函式,該函式接受一個提示詞,利用 Llama 2 模型生成對應的文字。最後,使用一個範例提示詞呼叫該函式,並列印出生成的摘要。

從技術角度看,使用向量搜尋和大語言模型可以快速有效地從大量文字資料中提取關鍵訊息。然而,模型的效能受到提示品質和引數設定的影響,需要不斷調整和最佳化。

總之,理解遠古植物的能量轉換和化石燃料的形成過程,對於我們認識地球歷史和開發可再生能源至關重要。透過結合向量搜尋和大語言模型等先進技術,我們可以更有效地探索和利用這些知識。

動態 RAG:開發敏捷高效的會議 AI 助理

在瞬息萬變的商業環境中,快速取得資訊並做出決策至關重要。如何將 AI 引入會議室,使其成為高效與低成本的輔助工具?本文將探討動態 RAG(Retrieval Augmented Generation)技術,並以一個模擬案例示範如何建構一個能快速解答科學問題的會議 AI 助理。

系統架構與 SciQ 資料集

我們的目標是模擬在日常會議中,需要快速解答專業科學問題的場景。與會者不希望浪費時間在網路搜尋上,而是需要一個能立即提供答案的工具,無論是市場行銷活動、文章事實查核,或任何需要專業科學知識的場合。

系統的核心是 Chroma 向量資料函式庫。我們使用 all-MiniLM-L6-v2 模型將超過 10,000 篇 SciQ 科學問答資料集檔案嵌入向量空間,並將資料和向量儲存到本機的 Chroma 資料函式庫中。這個過程快速與經濟高效,因為資料函式庫是本機建立的,沒有儲存成本,與資料函式庫是暫時的,不會造成空間浪費。

圖表翻譯:

上圖展示了動態 RAG 系統的工作流程。當使用者提出問題時,系統首先查詢向量資料函式庫以擷取相關檔案,接著將查詢結果提交給大語言模型(LLM),最終生成簡潔的總結並傳回給使用者。

微調 OpenAI 模型開發專屬問答系統

在這個技術中,玄貓將會分享如何微調 OpenAI 模型,建立一個專屬的科學問答系統。這個過程包含資料集準備、模型微調、以及監控微調任務等步驟。

1. 準備微調資料集

微調 OpenAI 模型需要精心準備資料集,否則微調任務將會失敗。以下步驟說明如何準備資料集:

  1. 從 Hugging Face 下載資料集並進行預處理。
  2. 將資料集串流至 JSONL 格式的檔案。

1.1 下載與檢視資料集

我們將使用 SciQ 資料集,如同在之前的中使用過的一樣。這次我們不會嵌入資料集,而是讓 OpenAI 模型在微調過程中處理。

# 匯入必要的函式庫
from datasets import load_dataset
import pandas as pd

# 從 Hugging Face 下載 SciQ 資料集
dataset_view = load_dataset("sciq", split="train")

# 過濾資料集,僅包含具有支援文字的問答
filtered_dataset = dataset_view.filter(lambda x: x["support"] != "")

# 顯示具有支援文字的問答數量
print("Number of questions with support: ", len(filtered_dataset))

內容解密:

這段程式碼會下載 SciQ 資料集,並過濾出包含支援文字的訓練資料。輸出顯示共有多少筆資料。

接著,我們將資料集載入 Pandas DataFrame 並移除幹擾選項的欄位:

# 將過濾後的資料集轉換為 Pandas DataFrame
df_view = pd.DataFrame(filtered_dataset)

# 要移除的欄位
columns_to_drop = ['distractor3', 'distractor1', 'distractor2']

# 從 DataFrame 中移除欄位
df_view = df_view.drop(columns=columns_to_drop)

# 顯示 DataFrame
df_view.head()

內容解密:

輸出顯示我們需要的 questioncorrect_answersupport 三個欄位。question 作為提示,correct_answersupport 則用於完成。

1.2 將資料集轉換為 JSONL 格式

為了訓練模型,我們需要將資料集寫入 JSONL 格式的檔案。

import jsonlines

# 準備 JSONL 檔案的資料專案
items = []
for idx, row in df_view.iterrows():
    detailed_answer = row['correct_answer'] + " Explanation: " + row['support']
    items.append({
        "messages": [
            {"role": "system", "content": "Given a science question, provide a detailed answer with supporting explanation."},
            {"role": "user", "content": row['question']},
            {"role": "assistant", "content": detailed_answer}
        ]
    })

# 寫入 JSONL 檔案
with jsonlines.open('QA_prompts_and_completions.jsonl', 'w') as writer:
    writer.write_all(items)

內容解密:

程式碼首先定義了包含正確答案和支援解釋的 detailed_answer。接著,定義了 GPT-4o-mini 模型所需的 messages

  • "role": "system":設定模型的初始指令,指示其提供詳細的科學問題答案。
  • "role": "user":代表使用者提問,內容來自 DataFrame 的 question 欄位。
  • "role": "assistant":代表模型的回覆,提供先前建構的詳細答案。

最後,將 JSONL 資料集寫入檔案。

圖表翻譯: 此圖示展示了從準備資料集到轉換為 JSONL 格式,再到微調模型的流程。

2. 微調模型

from openai import OpenAI
import jsonlines

client = OpenAI()

# 上傳訓練檔案
result_file = client.files.create(
    file=open("QA_prompts_and_completions.jsonl", "rb"),
    purpose="fine-tune"
)

# 顯示檔案資訊
print(result_file)
param_training_file_name = result_file.id
print(param_training_file_name)

# 建立微調任務
ft_job = client.fine_tuning.jobs.create(
    training_file=param_training_file_name,
    model="gpt-4o-mini-2024-07-18"
)

# 顯示微調任務資訊
print(ft_job)

內容解密:

程式碼首先建立 OpenAI 客戶端,接著使用生成的檔案建立訓練檔案並上傳至 OpenAI。輸出顯示檔案名稱、用途、狀態和 OpenAI 檔案 ID。接著,建立並顯示微調任務的詳細資訊,包含任務 ID、狀態、模型、訓練檔案等。

2.1 監控微調任務

以下程式碼片段展示如何監控微調任務:

import pandas as pd
from openai import OpenAI

client = OpenAI()

response = client.fine_tuning.jobs.list(limit=3)

# 初始化要顯示的資訊列表
job_ids = []
created_ats = []
statuses = []
models = []
training_files = []
error_messages = []
fine_tuned_models = []

# 迭代 response 並擷取所需資訊
for job in response.data:
    job_ids.append(job.id)
    created_ats.append(job.created_at)
    statuses.append(job.status)
    models.append(job.model)
    training_files.append(job.training_file)
    error_messages.append(job.error)
    fine_tuned_models.append(job.fine_tuned_model)

# 建立 DataFrame
df = pd.DataFrame({
    'Job ID': job_ids,
    'Created At': created_ats,
    'Status': statuses,
    'Model': models,
    'Training File': training_files,
    'Error': error_messages,
    'Fine-Tuned Model': fine_tuned_models
})

# 將時間戳記轉換為可讀格式
df['Created At'] = pd.to_datetime(df['Created At'], unit='s')
df = df.sort_values(by='Created At', ascending=False)

# 顯示 DataFrame
df

內容解密:

這段程式碼擷取微調任務的相關資訊,例如任務 ID、建立時間、狀態、模型、訓練檔案等,並將其儲存到 DataFrame 中。最後,將時間戳記轉換為可讀格式並顯示 DataFrame,方便監控任務狀態。

透過以上步驟,我們成功地微調了一個 OpenAI 模型,並建立了一個專屬的科學問答系統。

圖表翻譯: 此圖示展示了從準備資料集到轉換為 JSONL 格式,再到微調模型,最後監控微調任務的完整流程。

這個系統可以根據提供的科學問題,給出詳細的答案和支援解釋。這只是一個基礎的範例,您可以根據自己的需求調整資料集和模型引數,開發更精確、更符合特定領域的問答系統。

持續更新這個區塊,你就能看到狀態。現在,我們將擷取在「微調模型」欄位中訓練的最新模型。如果訓練失敗,此欄位將會是空的。如果沒有,我們可以這樣擷取它:

import pandas as pd

generation = False  # 直到目前的模型完成微調

內容解密:

這段程式碼初始化了一個布林變數 generation,用於追蹤目前的模型是否完成微調。根據這個變數,可以決定是否繼續等待或進行下一步操作。

使用微調的 OpenAI GPT-4o-mini 模型進行自然語言處理任務

3.1 尋找第一個非空的微調模型

在進行自然語言處理任務時,首先需要確定是否有可用的微調模型。以下程式碼用於檢查 DataFrame 中是否有非空的微調模型:

# 篩選出 DataFrame 中 '微調模型' 欄位非空的資料列
non_empty_models = df[df['微調模型'].notna() & (df['微調模型'] != '')]

# 檢查是否有非空的微調模型
if not non_empty_models.empty:
    # 取出第一個非空的微調模型名稱
    first_non_empty_model = non_empty_models['微調模型'].iloc[0]
    print("最新的微調模型是:", first_non_empty_model)
    generation = True
else:
    # 如果沒有非空的微調模型,則將 generation 設為 False
    first_non_empty_model = 'None'
    print("找不到微調模型。")
    generation = False

內容解密:

  1. df['微調模型'].notna() 用於檢查 ‘微調模型’ 欄位是否不為空值(NaN)。
  2. df['微調模型'] != '' 用於檢查 ‘微調模型’ 欄位是否不為空字串。
  3. non_empty_models.empty 用於檢查篩選後的 DataFrame 是否為空。
  4. 如果有非空的微調模型,則取出第一個模型的名稱並將 generation 設為 True,否則設為 False

3.2 使用微調的 OpenAI 模型

當確定有可用的微調模型後,可以使用該模型進行自然語言處理任務。首先,定義一個提示(prompt):

# 定義提示
prompt = "是什麼現象讓全球風從東北吹向西南?"

內容解密:

  1. prompt 變數用於儲存要輸入給模型的提示陳述式。
  2. 在此範例中,提示陳述式是關於全球風向的問題。

接下來,使用微調的 OpenAI GPT-4o-mini 模型進行完成任務:

# 使用微調模型進行完成任務
if generation:
    response = client.chat.completions.create(
        model=first_non_empty_model,
        temperature=0.0,  # 設定溫度引數,控制輸出的隨機性
        messages=[
            {"role": "system", "content": "給定一個問題,回答問題。"},
            {"role": "user", "content": prompt}
        ]
    )
else:
    print("錯誤:模型為 None,無法繼續 API 請求。")

內容解密:

  1. client.chat.completions.create() 是 OpenAI API 的呼叫方法,用於建立完成任務。
  2. model=first_non_empty_model 指定使用之前找到的微調模型。
  3. temperature=0.0 設定輸出結果的隨機性,值越低輸出越確定。
  4. messages 引數包含對話的角色和內容,其中 role="system" 表示系統提示,role="user" 表示使用者輸入。

3.3 處理和顯示回應結果

執行請求後,可以格式化並顯示回應結果。首先,列印原始回應:

if generation:
    print(response)

輸出包含回應和相關的元資料,例如:

ChatCompletion(id='chatcmpl-A32pvH9wLvNsSRmB1sUjxOW4Z6Xr6',...

然後,擷取回應的文字內容:

if generation:
    # 從第一個選項中擷取回應文字
    response_text = response.choices[0].message.content
    # 列印回應文字
    print(response_text)

輸出是一個字串,例如:

科氏力效應 解釋:科氏力效應是…

最後,使用 textwrap 模組將回應文字格式化成易於閱讀的段落:

import textwrap

if generation:
    # 將回應文字格式化成段落
    wrapped_text = textwrap.fill(response_text.strip(), 60)
    print(wrapped_text)

輸出結果如下:

科氏力效應 解釋:科氏力效應是一種現象,
會導致移動的物體,例如空氣和水,
因應地球自轉而轉動和扭曲。
它造成了大型天氣系統(例如颶風)的旋轉,
以及信風和洋流的方向。
在北半球,這種效應會導致移動的物體向右轉,
而在南半球,物體則向左轉。
科氏力效應與移動物體的速度和地球自轉的強度成正比,
對於小規模運動(例如水槽中的水流)來說,
它的影響可以忽略不計。

3.4 分析初始完成結果

(圖 9.6:初始完成)
(此處請插入 Plantuml 圖表以呈現初始完成的流程或結構)

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 微調OpenAI模型建構科學問答系統

package "科學問答系統" {
    package "資料準備" {
        component [SciQ 資料集] as sciq
        component [JSONL 格式化] as jsonl
        component [OpenAI 上傳] as upload
    }

    package "模型微調" {
        component [GPT-4o-mini] as gpt
        component [訓練監控] as monitor
        component [任務狀態] as status
    }
}

package "知識增強" {
    component [向量資料庫] as vector
    component [相似度查詢] as search
    component [RAG 整合] as rag
}

package "問答流程" {
    component [科學問題] as question
    component [知識檢索] as retrieve
    component [答案生成] as answer
}

sciq --> jsonl : 問答對
jsonl --> upload : API 上傳
upload --> gpt : 微調訓練
gpt --> monitor : 進度追蹤
question --> retrieve : 查詢
retrieve --> vector : 向量搜尋
vector --> rag : 上下文
rag --> answer : 生成回應

note right of gpt
  微調優勢:
  - 領域專業知識
  - 準確率提升
  - 快速響應
end note

note right of rag
  RAG 特點:
  - 知識增強
  - 即時更新
  - 可追溯來源
end note

@enduml

圖表翻譯: 此圖表呈現了使用微調的 OpenAI GPT-4o-mini 模型進行自然語言處理任務的主要流程。首先定義提示,然後使用微調模型進行完成任務,接著處理和顯示回應結果,最後分析初始完成結果。