ปริมาณการวิจัยที่เพิ่มขึ้นเรื่อย ๆ จำเป็นต้องมีวิธีการที่มีประสิทธิภาพสำหรับการจัดโครงสร้างความรู้ด้านวิชาการ งานนี้มักเกี่ยวข้องกับการพัฒนารูปแบบพื้นฐานของชั้นเรียนและจัดสรรสิ่งพิมพ์ให้กับชั้นเรียนที่เกี่ยวข้องมากที่สุด ในบทความนี้เราใช้โซลูชันอัตโนมัติแบบ end-to-end โดยใช้การสร้างปริมาณและท่อโมเดลภาษาขนาดใหญ่ (LLM) กรณีศึกษาของเราเริ่มต้นด้วยชุดข้อมูลที่มีสิ่งพิมพ์ arxiv 25,000 รายการจากภาษาศาสตร์เชิงคำนวณ (CS.CL) เผยแพร่ก่อนเดือนกรกฎาคม 2567 ซึ่งเราจัดระเบียบภายใต้รูปแบบใหม่ของชั้นเรียน
แนวทางของเรามุ่งเน้นไปที่งานสำคัญสามประการ: (i) การจัดกลุ่มที่ไม่ได้รับการดูแลของชุดข้อมูล ARXIV ลงในคอลเลกชันที่เกี่ยวข้อง (ii) ค้นพบโครงสร้างเฉพาะเรื่องแฝงภายในแต่ละคลัสเตอร์และ (iii) สร้างรูปแบบอนุกรมวิธานของผู้สมัครตามโครงสร้างเฉพาะเรื่องดังกล่าว
ที่แกนกลางของมันงานการจัดกลุ่มต้องระบุจำนวนตัวอย่างที่คล้ายกันเพียงพอภายในชุดข้อมูล ที่ไม่มีป้ายกำกับ นี่เป็นงานที่เป็นธรรมชาติสำหรับการฝังตัวในขณะที่พวกเขาจับความสัมพันธ์เชิงความหมายในคลังข้อมูลและสามารถให้เป็นคุณสมบัติการป้อนข้อมูลไปยังอัลกอริทึมการจัดกลุ่มเพื่อสร้างการเชื่อมโยงความคล้ายคลึงกันระหว่างตัวอย่าง เราเริ่มต้นด้วยการเปลี่ยนคู่ ( ชื่อ : นามธรรม ) ของชุดข้อมูลของเราให้เป็นตัวแทน Embeddings โดยใช้ Jina-Embeddings-V2 ซึ่งเป็นแบบจำลองความสนใจตาม Bert-Alibi และการใช้ควอนตัมสเกลาร์โดยใช้ทั้งหม้อแปลงประโยคและการใช้งานที่กำหนดเอง
สำหรับการจัดกลุ่มเราเรียกใช้ HDBSCAN ในพื้นที่มิติที่ลดลงเปรียบเทียบผลลัพธ์โดยใช้ eom และวิธีการจัดกลุ่ม leaf นอกจากนี้เราตรวจสอบว่าการใช้ (u)int8 embeddings quantization แทนที่จะเป็นตัวแทน float32 ส่งผลกระทบต่อกระบวนการนี้หรือไม่
เพื่อเปิดเผยหัวข้อแฝงภายในแต่ละกลุ่มของสิ่งพิมพ์ ArxIV เราได้รวม Langchain และ Pydantic เข้ากับ Mistral-7b-Instruct-V0.3 (และ GPT-4O รวมไว้สำหรับการเปรียบเทียบ) ลงใน Pipeline LLM ผลลัพธ์จะถูกรวมไว้ในเทมเพลตพรอมต์ที่ได้รับการกลั่นซึ่งเป็นแนวทางใน Claude Sonnet 3.5 ในการสร้างอนุกรมวิธานแบบลำดับชั้น
ผลลัพธ์ที่ได้รับการบอกใบ้ถึง 35 หัวข้อการวิจัยที่เกิดขึ้นใหม่ซึ่งแต่ละหัวข้อประกอบด้วยสิ่งพิมพ์อย่างน้อย 100 ฉบับ สิ่งเหล่านี้ถูกจัดระเบียบภายใน 7 คลาสแม่ในสาขาภาษาศาสตร์เชิงคำนวณ (CS.CL) วิธีการนี้อาจทำหน้าที่เป็นพื้นฐานสำหรับการสร้างแผนการผู้สมัครตามลำดับชั้นโดยอัตโนมัติในหมวดหมู่ arxiv ระดับสูงและทำ taxonomies ให้เสร็จสมบูรณ์อย่างมีประสิทธิภาพ
อนุกรมวิธานเสร็จสิ้นของวรรณคดีเชิงวิชาการด้วยการฝังปริมาณและ LLM-pipeline
Embeddings เป็นตัวแทนเชิงตัวเลขของวัตถุในโลกแห่งความเป็นจริงเช่นข้อความรูปภาพและเสียงที่ห่อหุ้มข้อมูลความหมายของข้อมูลที่เป็นตัวแทน พวกเขาถูกใช้โดยแบบจำลอง AI เพื่อทำความเข้าใจโดเมนความรู้ที่ซับซ้อนในแอปพลิเคชันดาวน์สตรีมเช่นการจัดกลุ่มการดึงข้อมูลและงานทำความเข้าใจความหมาย
เราจะทำแผนที่ ( ชื่อเรื่อง : บทคัดย่อ ) คู่จากสิ่งพิมพ์ Arxiv ไปจนถึงพื้นที่ 768 มิติโดยใช้ Jina-Embeddings-V2 [1] โมเดลการฝังข้อความโอเพนซอร์ซที่สามารถรองรับโทเค็นได้สูงถึง 8192 สิ่งนี้ให้ความยาวลำดับที่มีขนาดใหญ่พอสมควรสำหรับชื่อเรื่องบทคัดย่อและส่วนเอกสารอื่น ๆ ที่อาจเกี่ยวข้อง เพื่อเอาชนะขีด จำกัด 512-token ทั่วไปที่มีอยู่ในรุ่นอื่น ๆ Jina-embeddings-V2 ได้รวมข้อแก้ตัวสองทิศทาง [2] ลงในกรอบ Bert Alibi (ให้ความสนใจกับอคติเชิงเส้น) ช่วยให้การคาดการณ์ความยาวอินพุต (เช่นลำดับที่เกิน 2048 โทเค็น) โดยการเข้ารหัสข้อมูลตำแหน่งโดยตรงภายในชั้นการควบคุมตนเองแทนที่จะแนะนำการฝังตำแหน่ง ในทางปฏิบัติคะแนนความสนใจแบบสอบถามแบบสอบถามด้วยการลงโทษที่เป็นสัดส่วนกับระยะทางของพวกเขา
ขั้นตอนแรกในการใช้โมเดล Jina-Embeddings-V2 คือการโหลดผ่านหม้อแปลงประโยคซึ่งเป็นกรอบสำหรับการเข้าถึงโมเดลที่ล้ำสมัยที่มีอยู่ที่ Hugging Face Hub:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer ( 'jinaai/jina-embeddings-v2-base-en' , trust_remote_code = True ) ตอนนี้เราเข้ารหัส ( ชื่อ : บทคัดย่อ ) คู่ของชุดข้อมูลของเราโดยใช้ batch_size = 64 สิ่งนี้ช่วยให้การคำนวณแบบขนานบนตัวเร่งฮาร์ดแวร์เช่น GPU (แม้ว่าจะมีค่าใช้จ่ายในการต้องการหน่วยความจำมากขึ้น):
from datasets import load_dataset
ds = load_dataset ( "dcarpintero/arxiv.cs.CL.25k" , split = "train" )
corpus = [ title + ':' + abstract for title , abstract in zip ( ds [ 'title' ], ds [ 'abstract' ])]
f32_embeddings = model . encode ( corpus ,
batch_size = 64 ,
show_progress_bar = True )ความคล้ายคลึงกันทางความหมายระหว่าง Corpora สามารถคำนวณได้เล็กน้อยเป็นผลิตภัณฑ์ภายในของ Embeddings ในแผนที่ความร้อนต่อไปนี้แต่ละรายการ [x, y] มีสีตามผลิตภัณฑ์ Embeddings ดังกล่าวสำหรับประโยค ' ชื่อ ' ที่เป็นแบบอย่าง [x] และ [y]
Semantic Similary ใน cs.cl arxiv-titles โดยใช้ embeddings
การปรับขนาดการฝังตัวอาจเป็นเรื่องที่ท้าทาย ปัจจุบันโมเดลที่ทันสมัยแสดงให้เห็นว่าการฝังแต่ละครั้งเป็น float32 ซึ่งต้องใช้หน่วยความจำ 4 ไบต์ เนื่องจาก Jina-Embeddings-V2 แมปข้อความไปยังพื้นที่ 768 มิติข้อกำหนดของหน่วยความจำสำหรับชุดข้อมูลของเราจะอยู่ที่ประมาณ 73 MB โดยไม่มีดัชนีและข้อมูลเมตาอื่น ๆ ที่เกี่ยวข้องกับบันทึกสิ่งพิมพ์:
25 , 000 embeddings * 768 dimensions / embedding * 4 bytes / dimension = 76 , 800 , 000 bytes
76 , 800 , 000 bytes / ( 1024 ^ 2 ) ≈ 73.24 MBอย่างไรก็ตามการทำงานกับชุดข้อมูลขนาดใหญ่อาจเพิ่มความต้องการหน่วยความจำและค่าใช้จ่ายที่เกี่ยวข้องอย่างมีนัยสำคัญ:
| การฝัง มิติ | การฝัง แบบอย่าง | 2.5m บทคัดย่อ arxiv | 60.9m หน้า Wikipedia | 100 เมตร การฝัง |
|---|---|---|---|---|
| 384 | All-Minilm-L12-V2 | 3.57 GB | 85.26 GB | 142.88 GB |
| 768 | All-MPNET-BASE-V2 | 7.15 GB | 170.52 GB | 285.76 GB |
| 768 | jina-embeddings-v2 | 7.15 GB | 170.52 GB | 285.76 GB |
| ค.ศ. 1536 | Openai-text-embedding-3-small | 14.31 GB | 341.04 GB | 571.53 GB |
| 3072 | Openai-text-embedding-3 ขนาดใหญ่ | 28.61 GB | 682.08 GB | 1.143 TB |
เทคนิคที่ใช้เพื่อให้ได้การประหยัดหน่วยความจำคือ การหาปริมาณ สัญชาตญาณที่อยู่เบื้องหลังวิธีการนี้คือเราสามารถแยกค่าจุดลอยตัวได้โดยการแมปช่วงของพวกเขา [ f_max , f_min ] เป็นช่วงที่เล็กกว่าของตัวเลขจุดคงที่ [ q_max , q_min ] และการกระจายค่าทั้งหมดระหว่างช่วงเหล่านี้ ในทางปฏิบัติสิ่งนี้มักจะช่วยลดความแม่นยำของจุดลอยตัว 32 บิตถึงความกว้างบิตที่ต่ำกว่าเช่น 8 บิต (ปริมาณสเกลาร์) หรือค่า 1 บิต (การหาปริมาณแบบไบนารี)
สเกลาร์ฝังปริมาณ - จาก float32 ถึง (u) int8
โดยการวางแผนการกระจายความถี่ของการฝังตัว ที่สร้างขึ้นของ Jina เราสังเกตว่าค่านั้นมีความเข้มข้นในช่วงที่ค่อนข้างแคบ [-2.0, +2.0] ซึ่งหมายความว่าเราสามารถแมปค่า float32 ได้อย่างมีประสิทธิภาพกับ 256 (u)int8 โดยไม่สูญเสียข้อมูลอย่างมีนัยสำคัญ:
import matplotlib . pyplot as plt
plt . hist ( f32_embeddings . flatten (), bins = 250 , edgecolor = 'C0' )
plt . xlabel ( 'float-32 jina-embeddings-v2' )
plt . title ( 'distribution' )
plt . show ()การแจกแจง แบบ Float32 jina-embeddings-v2 ดั้งเดิม
เราสามารถคำนวณค่า [min, max] ของการแจกแจง:
> >> np . min ( f32_embeddings ), np . max ( f32_embeddings )
( - 2.0162134 , 2.074683 ) ขั้นตอนแรกในการใช้การหาปริมาณสเกลาร์คือการกำหนดชุดการสอบเทียบของการฝัง จุดเริ่มต้นทั่วไปคือชุดย่อยของการฝัง 10k ซึ่งในกรณีของเราจะครอบคลุมเกือบ 99.98% ของค่าการฝังแบบดั้งเดิม float32 การใช้การสอบเทียบมีวัตถุประสงค์เพื่อให้ได้ค่าตัวแทน f_min และ f_max ตามแต่ละมิติเพื่อลดค่าใช้จ่ายในการคำนวณและปัญหาที่อาจเกิดขึ้นจากค่าผิดปกติที่อาจปรากฏในชุดข้อมูลขนาดใหญ่
def calibration_accuracy ( embeddings : np . ndarray , k : int = 10000 ) -> float :
calibration_embeddings = embeddings [: k ]
f_min = np . min ( calibration_embeddings , axis = 0 )
f_max = np . max ( calibration_embeddings , axis = 0 )
# Calculate percentage in range for each dimension
size = embeddings . shape [ 0 ]
avg = []
for i in range ( embeddings . shape [ 1 ]):
in_range = np . sum (( embeddings [:, i ] >= f_min [ i ]) & ( embeddings [:, i ] <= f_max [ i ]))
dim_percentage = ( in_range / size ) * 100
avg . append ( dim_percentage )
return np . mean ( avg )
acc = calibration_accuracy ( f32_embeddings , k = 10000 )
print ( f"Average percentage of embeddings within [f_min, f_max] calibration: { acc :.5f } %" )
> >> Average percentage of embeddings within [ f_min , f_max ] calibration : 99.98636 % ขั้นตอนที่สองและสามของการหาปริมาณสเกลาร์ - เครื่องชั่งคอมพิวเตอร์และจุดศูนย์ และ การเข้ารหัส - สามารถนำไปใช้กับหม้อแปลงประโยคได้อย่างง่ายดายส่งผลให้การประหยัดหน่วยความจำ 4x เมื่อเทียบกับการเป็นตัวแทน float32 ดั้งเดิม ยิ่งกว่านั้นเราจะได้รับประโยชน์จากการดำเนินการทางคณิตศาสตร์ที่เร็วขึ้นเนื่องจากการคูณเมทริกซ์สามารถทำได้เร็วขึ้นด้วยเลขคณิตจำนวนเต็ม
from sentence_transformers . quantization import quantize_embeddings
# quantization is applied in a post-processing step
int8_embeddings = quantize_embeddings (
np . array ( f32_embeddings ),
precision = "int8" ,
calibration_embeddings = np . array ( f32_embeddings [: 10000 ]),
) f32_embeddings . dtype , f32_embeddings . shape , f32_embeddings . nbytes
>> > ( dtype ( 'float32' ), ( 25107 , 768 ), 77128704 ) # 73.5 MB
int8_embeddings . dtype , int8_embeddings . shape , int8_embeddings . nbytes
>> > ( dtype ( 'int8' ), ( 25107 , 768 ), 19282176 ) # 18.3 MB
# calculate compression
( f32_embeddings . nbytes - int8_embeddings . nbytes ) / f32_embeddings . nbytes * 100
>> > 75.0เพื่อความสมบูรณ์เราใช้วิธีการหาปริมาณสเกลาร์เพื่อแสดงสามขั้นตอนเหล่านั้น:
def scalar_quantize_embeddings ( embeddings : np . ndarray ,
calibration_embeddings : np . ndarray ) -> np . ndarray :
# Step 1: Calculate [f_min, f_max] per dimension from the calibration set
f_min = np . min ( calibration_embeddings , axis = 0 )
f_max = np . max ( calibration_embeddings , axis = 0 )
# Step 2: Map [f_min, f_max] to [q_min, q_max] => (scaling factors, zero point)
q_min = 0
q_max = 255
scales = ( f_max - f_min ) / ( q_max - q_min )
zero_point = 0 # uint8 quantization maps inherently min_values to zero
# Step 3: encode (scale, round)
quantized_embeddings = (( embeddings - f_min ) / scales ). astype ( np . uint8 )
return quantized_embeddings calibration_embeddings = f32_embeddings [: 10000 ]
beta_uint8_embeddings = scalar_quantize_embeddings ( f32_embeddings , calibration_embeddings ) beta_uint8_embeddings [ 5000 ][ 64 : 128 ]. reshape ( 8 , 8 )
array ([[ 187 , 111 , 96 , 128 , 116 , 129 , 130 , 122 ],
[ 132 , 153 , 72 , 136 , 94 , 120 , 112 , 93 ],
[ 143 , 121 , 137 , 143 , 195 , 159 , 90 , 93 ],
[ 178 , 189 , 143 , 99 , 99 , 151 , 93 , 102 ],
[ 179 , 104 , 146 , 150 , 176 , 94 , 148 , 118 ],
[ 161 , 138 , 90 , 122 , 93 , 146 , 140 , 129 ],
[ 121 , 115 , 153 , 118 , 107 , 45 , 70 , 171 ],
[ 207 , 53 , 67 , 115 , 223 , 105 , 124 , 158 ]], dtype = uint8 )เราจะดำเนินการต่อกับรุ่นของ embeddings ที่ได้รับการวัดปริมาณโดยใช้หม้อแปลงประโยค (การใช้งานที่กำหนดเองของเรารวมอยู่ในการวิเคราะห์ผลลัพธ์):
# `f32_embeddings` => if you prefer to not use quantization
# `beta_uint8_embeddings` => to check our custom implemention
embeddings = int8_embeddings ในส่วนนี้เราทำการฉายภาพสองขั้นตอนของ ( ชื่อ : นามธรรม ) การฝังคู่จากพื้นที่มิติสูงดั้งเดิม (768) ไปจนถึงมิติที่ต่ำกว่าคือ::
5 dimensions สำหรับการลดความซับซ้อนในการคำนวณในระหว่างการจัดกลุ่มและ2 dimensions สำหรับการเปิดใช้งานการแสดงภาพในพิกัด (x, y)สำหรับการคาดการณ์ทั้งสองเราใช้ UMAP [3] ซึ่งเป็นเทคนิคการลดมิติที่เป็นที่นิยมที่รู้จักกันดีในการรักษาโครงสร้างข้อมูลทั้งในท้องถิ่นและระดับโลก ในทางปฏิบัติสิ่งนี้ทำให้เป็นตัวเลือกที่ต้องการสำหรับการจัดการชุดข้อมูลที่ซับซ้อนด้วยการฝังในมิติสูง:
import umap
embedding_5d = umap . UMAP ( n_neighbors = 100 , # consider 100 nearest neighbors for each point
n_components = 5 , # reduce embedding space from 768 to 5 dimensions
min_dist = 0.1 , # maintain local and global balance
metric = 'cosine' ). fit_transform ( embeddings )
embedding_2d = umap . UMAP ( n_neighbors = 100 ,
n_components = 2 ,
min_dist = 0.1 ,
metric = 'cosine' ). fit_transform ( embeddings ) โปรดทราบว่าเมื่อเราใช้การจัดกลุ่ม HDBSCAN ในขั้นตอนต่อไปกลุ่มที่พบจะได้รับอิทธิพลจากวิธีที่ UMAP เก็บรักษาโครงสร้างท้องถิ่น ค่า n_neighbors ที่เล็กกว่าหมายความว่า UMAP จะมุ่งเน้นไปที่โครงสร้างท้องถิ่นมากขึ้นในขณะที่ค่าที่มากขึ้นช่วยให้สามารถจับภาพการเป็นตัวแทนระดับโลกได้มากขึ้นซึ่งอาจเป็นประโยชน์สำหรับการทำความเข้าใจรูปแบบโดยรวมในข้อมูล
ตอนนี้การลดลง ( ชื่อ : นามธรรม ) สามารถใช้เป็นคุณสมบัติอินพุตของอัลกอริทึมการจัดกลุ่มทำให้สามารถระบุหมวดหมู่ที่เกี่ยวข้องได้ตามระยะทางฝัง
เราเลือกใช้ HDBSCAN (การจัดกลุ่มเชิงพื้นที่ความหนาแน่นตามลำดับชั้นของแอปพลิเคชันที่มีเสียงรบกวน) [4] อัลกอริทึมการจัดกลุ่มขั้นสูงที่ขยาย DBSCAN โดยปรับให้เข้ากับคลัสเตอร์ความหนาแน่นที่แตกต่างกัน ซึ่งแตกต่างจาก k n mean ซึ่งต้องใช้จำนวนกลุ่มก่อนที่จะระบุจำนวนกลุ่ม HDBSCAN มี hyperparameter ที่สำคัญเพียงหนึ่งเดียวเท่านั้นซึ่งกำหนดจำนวนตัวอย่างขั้นต่ำเพื่อรวมไว้ในคลัสเตอร์
HDBSCAN ทำงานโดยการแปลงพื้นที่ข้อมูลเป็นครั้งแรกตามความหนาแน่นของจุดข้อมูลทำให้ภูมิภาคที่หนาแน่นขึ้น (พื้นที่ที่จุดข้อมูลอยู่ใกล้กันเป็นจำนวนมาก) น่าสนใจยิ่งขึ้นสำหรับการสร้างคลัสเตอร์ อัลกอริทึมจะสร้างลำดับชั้นของกลุ่มตามขนาดคลัสเตอร์ขั้นต่ำที่กำหนดโดย hyperparameter n สิ่งนี้ช่วยให้สามารถแยกแยะความแตกต่างระหว่างเสียงรบกวน (พื้นที่กระจัดกระจาย) และภูมิภาคที่หนาแน่น (กลุ่มที่มีศักยภาพ) ในที่สุด HDBSCAN จะควบแน่นลำดับชั้นนี้เพื่อให้ได้กลุ่มที่ถาวรที่สุดโดยระบุกลุ่มที่มีความหนาแน่นและรูปร่างที่แตกต่างกัน เป็นวิธีที่ใช้ความหนาแน่นมันยังสามารถตรวจจับค่าผิดปกติ
import hdbscan
hdbs = hdbscan . HDBSCAN ( min_cluster_size = 100 , # conservative clusters' size
metric = 'euclidean' , # points distance metric
cluster_selection_method = 'leaf' ) # favour fine grained clustering
clusters = hdbs . fit_predict ( embedding_5d ) # apply HDBSCAN on reduced UMAP cluster_selection_method กำหนดวิธีที่ HDBSCAN เลือกกลุ่มแบนจากลำดับชั้นของต้นไม้ ในกรณีของเราการใช้วิธีการเลือกคลัสเตอร์ eom (ส่วนเกิน) ร่วมกับการสร้างปริมาณการฝังมีแนวโน้มที่จะสร้างกลุ่มที่ใหญ่กว่าและเฉพาะเจาะจงน้อยกว่า กลุ่มเหล่านี้จะต้องใช้ กระบวนการปรับตัวใหม่ เพิ่มเติมเพื่อแยกหัวข้อแฝงที่มีความหมาย แต่โดยการเปลี่ยนไปใช้วิธีการเลือก leaf เราจะแนะนำอัลกอริทึมในการเลือกโหนดใบจากลำดับชั้นของคลัสเตอร์ซึ่งทำให้เกิดการจัดกลุ่มที่ละเอียดยิ่งขึ้นเมื่อเทียบกับวิธีมวลเกิน
HDBSCAN EOM & LEAF การเปรียบเทียบวิธีการเปรียบเทียบโดยใช้ Int8-embedding-Quantization
หลังจากดำเนินการขั้นตอนการจัดกลุ่มตอนนี้เราแสดงให้เห็นถึงวิธีการอนุมานหัวข้อแฝงของแต่ละคลัสเตอร์โดยการรวม LLM เช่น Mistral-7b-Instruct [5] กับ Pydantic และ Langchain เพื่อสร้างท่อ LLM ที่สร้างเอาต์พุตในรูปแบบโครงสร้างแบบคอมโพสิต
โมเดล Pydantic เป็นคลาสที่ได้มาจาก pydantic.BaseModel กำหนดฟิลด์เป็นแอตทริบิวต์ประเภท พวกเขาคล้ายกับ Python Dataclasses อย่างไรก็ตามพวกเขาได้รับการออกแบบด้วยความแตกต่างที่ลึกซึ้ง แต่มีนัยสำคัญที่เพิ่มประสิทธิภาพการดำเนินงานที่หลากหลายเช่นการตรวจสอบความถูกต้องการทำให้เป็นอนุกรมและการสร้างสคี JSON คลาส Topic ของเรากำหนดฟิลด์ชื่อ label สิ่งนี้จะสร้างเอาท์พุท LLM ในรูปแบบที่มีโครงสร้างแทนที่จะเป็นบล็อกข้อความแบบอิสระช่วยอำนวยความสะดวกในการประมวลผลและการวิเคราะห์ที่ง่ายขึ้น
from pydantic import BaseModel , Field
class Topic ( BaseModel ):
"""
Pydantic Model to generate an structured Topic Model
"""
label : str = Field (..., description = "Identified topic" )เทมเพลตพรอมต์ Langchain เป็นสูตรที่กำหนดไว้ล่วงหน้าสำหรับการแปลอินพุตของผู้ใช้และพารามิเตอร์เป็นคำแนะนำสำหรับรูปแบบภาษา เรากำหนดพรอมต์ที่นี่สำหรับงานที่เราต้องการ:
from langchain_core . prompts import PromptTemplate
topic_prompt = """
You are a helpful research assistant. Your task is to analyze a set of research paper
titles related to Natural Language Processing, and determine the overarching topic.
INSTRUCTIONS:
1. Based on the titles provided, identify the most relevant topic:
- Ensure the topic is concise and clear.
2. Format Respose:
- Ensure the title response is in JSON as in the 'OUTPUT OUTPUT' section below.
- No follow up questions are needed.
OUTPUT FORMAT:
{{"label": "Topic Name"}}
TITLES:
{titles}
""" ตอนนี้มาเขียนหัวข้อการสร้างแบบจำลองหัวข้อโดยใช้ Langchain Expression Language (LCEL) เพื่อแสดงเทมเพลตพรอมต์ของเราลงในอินพุต LLM และแยกวิเคราะห์เอาต์พุตการอนุมานเป็น JSON :
from langchain . chains import LLMChain
from langchain_huggingface import HuggingFaceEndpoint
from langchain_core . output_parsers import PydanticOutputParser
from typing import List
def TopicModeling ( titles : List [ str ]) -> str :
"""
Infer the common topic of the given titles w/ LangChain, Pydantic, OpenAI
"""
repo_id = "mistralai/Mistral-7B-Instruct-v0.3"
llm = HuggingFaceEndpoint (
repo_id = repo_id ,
temperature = 0.2 ,
huggingfacehub_api_token = os . environ [ "HUGGINGFACEHUB_API_TOKEN" ]
)
prompt = PromptTemplate . from_template ( topic_prompt )
parser = PydanticOutputParser ( pydantic_object = Topic )
topic_chain = prompt | llm | parser
return topic_chain . invoke ({ "titles" : titles })ในการเปิดใช้งานโมเดลเพื่ออนุมานหัวข้อของแต่ละคลัสเตอร์เราได้รวมชุดย่อย 25 ชื่อกระดาษจากแต่ละคลัสเตอร์เป็นส่วนหนึ่งของอินพุต LLM:
topics = []
for i , cluster in df . groupby ( 'cluster' ):
titles = cluster [ 'title' ]. sample ( 25 ). tolist ()
topic = TopicModeling ( titles )
topics . append ( topic . label )มากำหนดสิ่งพิมพ์ arxiv แต่ละรายการให้กับคลัสเตอร์ที่เกี่ยวข้อง:
n_clusters = len ( df [ 'cluster' ]. unique ())
topic_map = dict ( zip ( range ( n_clusters ), topics ))
df [ 'topic' ] = df [ 'cluster' ]. map ( topic_map )ในการสร้างอนุกรมวิธานแบบลำดับชั้นเราได้สร้างคำแนะนำให้เป็นแนวทางในการแนะนำ Claude Sonnet 3.5 ในการจัดระเบียบหัวข้อการวิจัยที่ระบุไว้ซึ่งสอดคล้องกับแต่ละคลัสเตอร์ในรูปแบบลำดับชั้น:
from langchain_core . prompts import PromptTemplate
taxonomy_prompt = """
Create a comprehensive and well-structured taxonomy
for the ArXiv cs.CL (Computational Linguistics) category.
This taxonomy should organize subtopics in a logical manner.
INSTRUCTIONS:
1. Review and Refine Subtopics:
- Examine the provided list of subtopics in computational linguistics.
- Ensure each subtopic is clearly defined and distinct from others.
2. Create Definitions:
- For each subtopic, provide a concise definition (1-2 sentences).
3. Develop a Hierarchical Structure:
- Group related subtopics into broader categories.
- Create a multi-level hierarchy, with top-level categories and nested subcategories.
- Ensure that the structure is logical and intuitive for researchers in the field.
4. Validate and Refine:
- Review the entire taxonomy for consistency, completeness, and clarity.
OUTPUT FORMAT:
- Present the final taxonomy in a clear, hierarchical format, with:
. Main categories
.. Subcategories
... Individual topics with their definitions
SUBTOPICS:
{taxonomy_subtopics}
""" มาสร้างพล็อตการกระจายแบบโต้ตอบกัน:
chart = alt . Chart ( df ). mark_circle ( size = 5 ). encode (
x = 'x' ,
y = 'y' ,
color = 'topic:N' ,
tooltip = [ 'title' , 'topic' ]
). interactive (). properties (
title = 'Clustering and Topic Modeling | 25k arXiv cs.CL publications)' ,
width = 600 ,
height = 400 ,
)
chart . display () และเปรียบเทียบผลลัพธ์การจัดกลุ่มโดยใช้การแสดงแบบฝังตัว float32 และการวัดปริมาณ int8 ประโยค:
HDBSCAN Leaf-clustering โดยใช้ Float32 & Quantized-INT8 EMBEDDING
ตอนนี้เราทำการเปรียบเทียบเดียวกันกับการใช้งานเชิงปริมาณที่กำหนดเองของเรา:
HDBSCAN Leaf-Clustering โดยใช้ Float32 & Quantized-Uint8 Embeddings (Custom-Quantization-Emplementation)
ผลลัพธ์การจัดกลุ่มโดยใช้ float32 และ (u)int8 เชิงปริมาณฝังตัวแสดงเลย์เอาต์ทั่วไปที่คล้ายกันของกลุ่มที่กำหนดไว้อย่างดีแสดงให้เห็นว่า (i) อัลกอริทึมการจัดกลุ่ม HDBSCAN นั้นมีประสิทธิภาพในทั้งสองกรณีและ (ii) ความสัมพันธ์หลักในข้อมูล
โดยเฉพาะอย่างยิ่งมันสามารถสังเกตได้ว่าการใช้ปริมาณการฝังควอนตัมส่งผลให้ทั้งสองกรณีในการจัดกลุ่มเม็ดเล็ก ๆ เล็กน้อย (35 กลุ่มเทียบกับ 31) ที่ดูเหมือนจะเชื่อมโยงกันทางความหมาย สมมติฐานเบื้องต้นของเราสำหรับความแตกต่างนี้คือปริมาณสเกลาร์อาจเป็น แนวทางที่ ขัดแย้งกับอัลกอริทึมการจัดกลุ่ม HDBSCAN เพื่อแยกจุดที่แยกกันก่อนหน้านี้
นี่อาจเป็นเพราะ (i) เสียง (การหาปริมาณสามารถสร้างการเปลี่ยนแปลง ที่มีเสียงดัง ขนาดเล็กในข้อมูลซึ่งอาจมีผลกระทบของ การทำให้เป็นมาตรฐาน และนำไปสู่การตัดสินใจการจัดกลุ่มที่ละเอียดอ่อนมากขึ้น) หรือเนื่องจาก (ii) ความแตกต่างในความแม่นยำเชิงตัวเลขและการเปลี่ยนแปลงการคำนวณระยะ float32 การตรวจสอบเพิ่มเติมจะต้องเข้าใจอย่างถ่องแท้ถึงผลกระทบของการหาปริมาณในการจัดกลุ่ม
โครงการทั้งหมดมีอยู่ที่ cs.cl.taxonomy วิธีการนี้อาจทำหน้าที่เป็นพื้นฐานสำหรับการระบุแผนการผู้สมัครของชั้นเรียนโดยอัตโนมัติในหมวดหมู่ arxiv ระดับสูง:
. Foundations of Language Models
.. Model Architectures and Mechanisms
... Transformer Models and Attention Mechanisms
... Large Language Models (LLMs)
.. Model Optimization and Efficiency
... Compression and Quantization
... Parameter-Efficient Fine-Tuning
... Knowledge Distillation
.. Learning Paradigms
... In-Context Learning
... Instruction Tuning
. AI Ethics, Safety, and Societal Impact
.. Ethical Considerations
... Bias and Fairness in Models
... Alignment and Preference Optimization
.. Safety and Security
... Hallucination in LLMs
... Adversarial Attacks and Robustness
... Detection of AI-Generated Text
.. Social Impact
... Hate Speech and Offensive Language Detection
... Fake News Detection
[...]
@article{carpintero2024
author = { Diego Carpintero},
title = {Taxonomy Completion with Embedding Quantization and an LLM-Pipeline: A Case Study in Computational Linguistics},
journal = {Hugging Face Blog},
year = {2024},
note = {https://huggingface.co/blog/dcarpintero/taxonomy-completion},
}