三分鐘快速入門大模型數(shù)據(jù)工程
向自然語言處理的大模型應(yīng)用,數(shù)據(jù)工程的核心任務(wù)是構(gòu)建一套高效、可擴展、可控的數(shù)據(jù)流程,從源頭到可用于模型訓(xùn)練、推理的高質(zhì)量文本語料,全鏈路打通。
數(shù)據(jù)工程的整體目標
構(gòu)建穩(wěn)定的數(shù)據(jù)流轉(zhuǎn)鏈路,從原始文本數(shù)據(jù) → 清洗/標注/審核后的語料 → 符合模型輸入格式的數(shù)據(jù)集
保證數(shù)據(jù)可用性、完整性、質(zhì)量、結(jié)構(gòu)統(tǒng)一性
支持多階段使用場景:訓(xùn)練/微調(diào)、推理RAG、評估測試等
數(shù)據(jù)來源
最常見的形式是甲方提供,如客戶工單、業(yè)務(wù)知識庫、客服聊天記錄、FAQ 等。
需盡早明確數(shù)據(jù)格式、內(nèi)容范圍、隱私邊界。也需明確數(shù)據(jù)目標用途、是否可公開訓(xùn)練、是否需要脫敏。
也可以自主收集,成本高、周期長,但更具通用性和自主性。數(shù)據(jù)收集有下面幾種方式:
手動采集:(如論壇、PDF、博客文章等)
網(wǎng)頁爬蟲:需遵循 robots 協(xié)議與合法邊界
調(diào)用開放接口:(如新聞、百科類 API)
AI 生成數(shù)據(jù):(如大模型生成問答對,用于訓(xùn)練增強)
AI 生成數(shù)據(jù)示例
以微調(diào)訓(xùn)練金融科技領(lǐng)域問答模型為例,通過 AI 生成訓(xùn)練數(shù)據(jù)。
流程:
初始化
- 設(shè)置兩種對話風(fēng)格配置:
- 小白風(fēng)格:通俗易懂的比喻解釋,限制術(shù)語使用
- 資深風(fēng)格:專業(yè)術(shù)語和技術(shù)細節(jié),要求嚴謹準確
- 每種風(fēng)格包含:
- 系統(tǒng)角色設(shè)定(system_prompt)
- 示例對話(examples)
- 溫度參數(shù)(控制回答隨機性)
數(shù)據(jù)生成循環(huán)
- 構(gòu)建包含系統(tǒng)提示和示例的對話上下文
- 從預(yù)設(shè)問題列表中隨機選取問題
- 調(diào)用 AI 接口獲取風(fēng)格化回答
- 結(jié)構(gòu)化存儲問答對(問題、回答、風(fēng)格標簽)
- 加入延遲防止 API 限流
結(jié)果處理
- 合并所有生成的問答數(shù)據(jù)
- 處理可能的異常情況(如中斷請求)
- 將最終數(shù)據(jù)集保存為格式化的JSON文件
示例代碼:
import json
import time
import random
from zhipuai import ZhipuAI
# 初始化模型
client = ZhipuAI(api_key="48b393b3474e43f3b7eafceb662db81a.xxxxxx")
style_config = {
"小白": {
"system_prompt": "你是一位區(qū)塊鏈科普專家,需要用最簡單易懂的方式向完全不了解技術(shù)的普通人解釋區(qū)塊鏈概念。要求:\n1. 使用生活化比喻(如'像大家一起記賬本')\n2. 避免專業(yè)術(shù)語,必須使用時立即解釋\n3. 回答控制在3句話以內(nèi)\n4. 可適當使用??????等表情符號",
"examples": [
{"role": "user", "content": "區(qū)塊鏈到底是什么?"},
{"role": "assistant",
"content": "想象一群人在共同維護一個公開賬本??,每筆交易都記錄在所有人的本子上,想作弊就得改掉大部分人的記錄,這幾乎不可能??!"},
{"role": "user", "content": "比特幣為什么值錢?"},
{"role": "assistant", "content": "就像限量版球星卡??,總量固定(2100萬枚),越來越多人想要時價格就上漲啦!"}
],
"temperature": 0.2 # 低溫度值保證回答穩(wěn)定性
},
"資深": {
"system_prompt": "你是區(qū)塊鏈核心技術(shù)研究員,需滿足:\n1. 使用專業(yè)術(shù)語(如'橢圓曲線數(shù)字簽名''梅克爾帕特里夏樹')\n2. 包含技術(shù)實現(xiàn)細節(jié)\n3. 必要時給出公式/代碼片段\n4. 引用最新論文成果(如2023 IEEE S&P會議)",
"examples": [
{"role": "user", "content": "請解釋zk-SNARKs的工作原理"},
{"role": "assistant",
"content": "zk-SNARKs依賴QAP(二次算術(shù)程序)將計算轉(zhuǎn)化為多項式關(guān)系:\n1) Setup生成CRS(公共參考串)\n2) Prover構(gòu)造π=(A,B,C)滿足A*B=C+H*Z\n3) Verifier通過雙線性配對驗證e(A,B)=e(C,g)?e(H,g^z)\n參考:Groth16方案優(yōu)化后驗證僅需3個配對運算。"},
{"role": "user", "content": "分析EIP-4844對L2的影響"},
{"role": "assistant",
"content": "Proto-danksharding通過引入blob攜帶交易(每個blob≈125KB),使Rollups數(shù)據(jù)可用性成本降低10-100倍。實測顯示:\n- Optimism交易費從$0.3→$0.007\n- zkSync證明生成時間減少40%"}
],
"temperature": 0.5 # 中等溫度值允許一定創(chuàng)造性
}
}
def generate_style_data(style_name, num_samples=50):
config = style_config[style_name]
data = []
# 構(gòu)建對話上下文 = 系統(tǒng)提示 + 示例對話
messages = [
{"role": "system", "content": config["system_prompt"]},
*config["examples"]
]
# 預(yù)定義的用戶問題集(可擴展)
user_inputs = [
"比特幣和區(qū)塊鏈是什么關(guān)系?",
"智能合約真的安全嗎?",
"普通人怎么參與DeFi?",
"解釋一下零知識證明",
"為什么NFT能賣那么貴?",
"區(qū)塊鏈能防止數(shù)據(jù)造假嗎?"
]
for _ in range(num_samples):
try:
# 隨機選擇問題
user_msg = random.choice(user_inputs)
# 當前對話 = 歷史上下文 + 新問題
current_messages = messages + [
{"role": "user", "content": user_msg}
]
# 調(diào)用API(修正模型名稱)
response = client.chat.completions.create(
model="glm-4-plus",
messages=current_messages,
temperature=config["temperature"],
max_tokens=150
)
# 獲取回復(fù)內(nèi)容
reply = response.choices[0].message.content
data.append({
"user": user_msg,
"assistant": reply,
"style": style_name
})
print("獲取最新回復(fù)內(nèi)容: ", data[-1])
time.sleep(0.5) # 限流
except Exception as e:
print(f"生成失?。簕str(e)}")
return data
if __name__ == '__main__':
all_data = []
try:
print("開始生成小白風(fēng)格數(shù)據(jù)...")
gentle_data = generate_style_data("小白", 10)
all_data.extend(gentle_data)
print("開始生成資深風(fēng)格數(shù)據(jù)...")
gentle_data = generate_style_data("資深", 10)
all_data.extend(gentle_data)
except KeyboardInterrupt:
print("\n用戶中斷,保存已生成數(shù)據(jù)...")
finally:
with open("style_chat_data.json", "w", encoding="utf-8") as f:
json.dump(all_data, f, ensure_ascii=False, indent=2)
print(f"數(shù)據(jù)已保存,有效樣本數(shù):{len(all_data)}")
數(shù)據(jù)清洗與預(yù)處理
原始數(shù)據(jù)往往雜亂無章,需系統(tǒng)清洗處理。
- 內(nèi)容清洗
- 去除 HTML 標簽、表情、特殊符號、水印等無效信息
- 統(tǒng)一編碼格式,規(guī)范文本結(jié)構(gòu)(如換行、縮進)
- 分段處理
- 按語義或結(jié)構(gòu)分段,確保模型輸入粒度適當
- 避免文本過長或過短,提升模型效果
- 內(nèi)容篩選
- 刪除空白內(nèi)容、重復(fù)內(nèi)容、無意義語段
import json
from typing import List, Dict
def is_meaningless(text: str) -> bool:
"""檢查是否是無意義內(nèi)容"""
# 空白或超短內(nèi)容
if len(text.strip()) < 5:
return True
# 常見無意義模式
meaningless_phrases = [
"我不知道", "無法回答",
"這個問題", "請重新提問"
]
return any(phrase in text for phrase in meaningless_phrases)
def simple_clean(data: List[Dict]) -> List[Dict]:
"""基礎(chǔ)清洗流程"""
seen = set() # 用于去重
cleaned_data = []
for item in data:
text = item["assistant"].strip()
# 檢查空白/重復(fù)/無意義
if (not text or
text in seen or
is_meaningless(text)):
continue
seen.add(text)
cleaned_data.append({
"user": item["user"],
"assistant": text,
"style": item["style"]
})
return cleaned_data
if __name__ == '__main__':
# 加載原始數(shù)據(jù)
with open('style_chat_data.json', 'r', encoding='utf-8') as f:
raw_data = json.load(f)
# 執(zhí)行清洗
cleaned_data = simple_clean(raw_data)
# 保存結(jié)果
with open('cleaned_data.json', 'w', encoding='utf-8') as f:
json.dump(cleaned_data, f, ensure_ascii=False, indent=2)
# 打印簡單報告
print(f"原始數(shù)據(jù)量: {len(raw_data)}")
print(f"清洗后保留: {len(cleaned_data)}")
print(f"過濾數(shù)量: {len(raw_data) - len(cleaned_data)}")
過濾掉違法違規(guī)、廣告類內(nèi)容,保障數(shù)據(jù)合規(guī)
數(shù)據(jù)標注與格式化
根據(jù)用途,對數(shù)據(jù)進行結(jié)構(gòu)化和標注。
標注方式
- 自動標注:適合結(jié)構(gòu)化文本、已有知識圖譜輔助生成
- 人工標注:適用于對話意圖、情感分類、多輪對話標記等復(fù)雜任務(wù)
- AI 輔助+人工校對:效率與質(zhì)量的平衡方式
數(shù)據(jù)集結(jié)構(gòu)標準化
- 根據(jù)目標任務(wù)結(jié)構(gòu)設(shè)計
- 問答:{"question": "", "answer": ""}
- 多輪對話:{"dialog": [{"role": "user", "content": ""}, {"role": "assistant", "content": ""}, ...]}
- 分類任務(wù):{"text": "", "label": ""}統(tǒng)一存儲格式
- JSONL
- CSV
- Parquet
數(shù)據(jù)審查與質(zhì)檢
保證數(shù)據(jù)質(zhì)量,避免模型效果被低質(zhì)樣本污染。
審查內(nèi)容
- 是否存在空文本?
- 文本長度是否合理?
- 是否出現(xiàn)亂碼、非法字符?
- 是否有標簽缺失、格式錯誤?
常規(guī)校驗機制
- 自動規(guī)則校驗(正則、長度范圍)
- 隨機抽樣人工審核
- 自動評分 + 低分樣本再審
文本去重與相似性篩查
消除重復(fù)文本,避免模型過擬合。
實現(xiàn)思路:
- 使用 Embedding 模型,將文本轉(zhuǎn)為向量表示
- 計算文本對之間的相似度(如余弦相似度或歐氏距離)
- 設(shè)置合理相似度閾值(如 > 0.95 即視為重復(fù))
- 保留更優(yōu)版本文本,剔除相似冗余樣本
import json
from sentence_transformers import SentenceTransformer
import numpy as np
def deduplicate_data(data_list, threshold=0.9):
"""
語義去重:對 assistant 回復(fù)去重
:param data_list: List[dict], 每個 dict 包含 user / assistant / style
:param threshold: float, 相似度閾值
:return: 去重后的 List[dict]
"""
model = SentenceTransformer("/root/autodl-tmp/models/thomas/text2vec-base-chinese")
replies = [item["assistant"] for item in data_list]
embeddings = model.encode(replies)
kept = []
seen = set()
for i, emb_i in enumerate(embeddings):
if i in seen:
continue
keep = True
for j, emb_j in enumerate(embeddings):
if j == i or j in seen:
continue
sim = np.dot(emb_i, emb_j) / (np.linalg.norm(emb_i) * np.linalg.norm(emb_j))
print(f"sim({i}, {j}) = {sim:.4f}")
if sim > threshold:
seen.add(j)
kept.append(data_list[i])
return kept
if __name__ == '__main__':
with open("style_chat_data.json", "r", encoding="utf-8") as f:
all_data = json.loads(f.read())
cleaned_data = deduplicate_data(all_data, 0.5)
數(shù)據(jù)統(tǒng)計與版本控制
- 記錄每輪數(shù)據(jù)處理中的:樣本數(shù)量、保留比例、清洗率、標注覆蓋率等
- 建立數(shù)據(jù)集版本控制機制(如 v1、v2、實驗版、正式版)
- 便于溯源、復(fù)現(xiàn)、對比實驗效果
數(shù)據(jù)安全與隱私保護
尤其是面向企業(yè)應(yīng)用時,必須落實數(shù)據(jù)安全要求。
- 敏感字段脫敏(如姓名、電話、身份證、公司信息等)
- 權(quán)限分級,控制訪問范圍
- 明確數(shù)據(jù)使用范圍(訓(xùn)練 or 部署 or 產(chǎn)品化)
- 加入審計與日志記錄
參考文獻:https://gcn0rm30wzh6.feishu.cn/docx/MsqhdNNkQotaNfxULM5csoqYnec
寫在最后
2025年的今天,AI創(chuàng)新已經(jīng)噴井,幾乎每天都有新的技術(shù)出現(xiàn)。作為親歷三次AI浪潮的技術(shù)人,我堅信AI不是替代人類,而是讓我們從重復(fù)工作中解放出來,專注于更有創(chuàng)造性的事情,關(guān)注我們公眾號口袋大數(shù)據(jù),一起探索大模型落地的無限可能!
另外目前我正在做兩個開源項目,一個本地知識庫還有一個是小紅書的智能發(fā)布工具,如果有需求的話可以加入下面的群聊中交流。
EasyRAG是我開源的一個本地知識庫項目,未來我會再里面分享使用EasyRAG做各種場景的問答或者文檔生成的最佳實踐文檔