RAG dengan hy4: menyambung model 4B ke pangkalan pengetahuan dan carian vektor
RAG dengan hy4: menyambung model 4B ke pangkalan pengetahuan dan carian vektor
Soalan "bolehkah model 4B menjalankan RAG" hanya mempunyai jawapan yang jujur jika anda memperjelaskan apa yang model 4B itu lakukan. Jawapannya: untuk peringkat ringan sepanjang saluran, ia sangat memadai; untuk sintesis panjang, ia mudah tersadung. hy4 sangat sesuai untuk peranan pertama: model dense 4.22 bilion parameter, konteks native 256K, dan Q4_K_M hanya 2.6GB, jadi ia berjalan pada kebanyakan mesin. Artikel ini memberikan satu set lengkap: vector store tempatan, embedding bge-m3, dan hy4 yang menulis semula kueri serta menghasilkan jawapan, lengkap dengan lima kesilapan yang anda akan temui sebenarnya.
Ringkasan 30 saat
hy4 mempunyai tiga peranan bernilai tinggi dalam RAG: menulis semula kueri (mengubah soalan santai kepada istilah carian), penghalaan niat (memutuskan pangkalan mana yang hendak dimasuki), dan penghasilan jawapan pendek (jawapan bawah 300 perkataan daripada potongan yang diambil). Sintesis berbilang dokumen dan penaakulan berbilang langkah serahkan kepada model besar di cloud. Bahagian vektor menggunakan embedding terbuka seperti bge-m3, kerana katalog cloud EXAIV buat masa ini belum mempunyai sebarang model embedding.
Tentukan peranan dahulu: 4B patut buat apa dan tidak patut buat apa
Saluran RAG mempunyai sekurang-kurangnya dua peranan: bahagian ambil semula yang "mencari bahan" dan bahagian penjanaan yang "mengatur jawapan". Kedua-duanya memerlukan perkara yang sangat berbeza daripada sesebuah model:
| Peringkat | Apa yang diperlukan daripada model | Adakah hy4 sesuai |
|---|---|---|
| Menulis semula dan mengembangkan kueri | hanya perlu memahami soalan dan menghasilkan kata kunci | sangat sesuai |
| Pengelasan niat dan penghalaan | hanya perlu mengeluarkan satu label | sangat sesuai, malah 0.5B pun boleh |
| Ringkasan dan pengekstrakan | perlu merangkumi perkara utama sumber | sesuai |
| Jawapan pendek yang berlandaskan | perlu setia dan tidak mengada-ngada | sesuai dengan prompt yang ketat |
| Sintesis panjang merentas berbilang dokumen | perlu penaakulan jauh dan konsistensi | tidak sesuai, pilih model besar |
| Penaakulan berbilang langkah | perlu langkah-langkah perantaraan | tidak sesuai |
Mengapa model kecil sesuai pada separuh awal saluran
Separuh awal menghasilkan teks pendek atau label, di mana kesilapan murah dan mudah disahkan; separuh akhir menghasilkan teks panjang, di mana kesilapan mahal dan sukar dikesan. Meletakkan 4B di bahagian depan bermakna penulisan semula yang kurang baik masih ada recall untuk menyelamatkan; meletakkannya di belakang bermakna setiap ayat karangan terus berhadapan dengan pengguna.
Satu set lengkap yang boleh dijalankan
Langkah 1: menjalankan pelayan inferensi tempatan
./llama-server -m ./hunyuan4b/Q4_K_M.gguf \
--host 127.0.0.1 --port 8080 \
--ctx-size 32768 --jinja
Titik akhir yang terbuka ialah API yang serasi dengan OpenAI mengikut piawaian, dan semua kod di bawah menunjuk ke http://127.0.0.1:8080/v1.
Langkah 2: memotong dokumen
from pathlib import Path
import re
def load_docs(folder: str) -> list[str]:
chunks = []
for p in sorted(Path(folder).glob("**/*.md")):
text = p.read_text(encoding="utf-8")
sections = re.split(r"\n(?=#{1,3} )", text)
for sec in sections:
if len(sec) < 200:
continue
for i in range(0, len(sec), 1200):
piece = sec[i:i + 1200]
if len(piece.strip()) > 50:
chunks.append(sec.split("\n")[0] + "\n" + piece)
return chunks
chunks = load_docs("./docs")
print(len(chunks))
Prinsip pertama memotong: jangan memutuskan unit makna
Memotong mengikut bilangan aksara tetap akan membahagikan dua sebuah jadual atau perincian API, menjadikan potongan yang diambil terbaca tak lengkap dan model hanya bisa meneka. Potong mengikut hierarki tajuk dahulu, baru mengikut panjang, dan kekalkan tajuk sebagai awalan untuk dicantumkan semula, kerana tajuk adalah penyangga recall terbaik yang anda ada.
Langkah 3: menanam vektor (embedding tempatan)
from sentence_transformers import SentenceTransformer
embed_model = SentenceTransformer("BAAI/bge-m3")
vectors = embed_model.encode(chunks, normalize_embeddings=True, batch_size=32)
bge-m3 ialah salah satu model embedding berbilang bahasa terbuka yang paling banyak dimuat turun dalam komuniti, dan menyokong campuran Cina-Inggeris serta teks panjang.
Mengapa tidak menggunakan embedding di cloud
Pertama, katalog cloud EXAIV buat masa ini tiada model jenis embedding langsung. Kedua, volume permintaan embedding besar tetapi nilai setiap permintaan kecil, jadi membawanya ke cloud menjadi bahagian kos yang paling mahal. Ketiga, model embedding hanya beberapa ratus MB hingga sedikit melebihi 1GB, menjalankannya di tempatan nyaris tiada kos operasi dan biasanya lebih cepat secara keseluruhan.
Langkah 4: mengambil semula dan menyusun semula
import numpy as np
query_vec = embed_model.encode([query], normalize_embeddings=True)[0]
scores = np.dot(vectors, query_vec)
top_idx = np.argsort(-scores)[:20]
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
pairs = [[query, chunks[i]] for i in top_idx]
rerank_scores = reranker.predict(pairs)
final_idx = [top_idx[i] for i in np.argsort(-rerank_scores)[:4]]
Penyusunan semula ialah langkah dengan leverage tertinggi
Recall vektor ialah penapis kasar (murah, cepat, liputan luas), manakala penyusunan semula dengan cross-encoder ialah penapis halus (lebih lambat, lebih mahal, tetapi tertibannya jauh lebih tepat). Banyak sistem RAG tersadung justeru pada tertib recall, bukan pada model penjana. Mengubah top-20 kepada top-4 yang bersih selalunya lebih berkesan daripada menaikkan penjana dari 4B kepada 7B.
Langkah 5: menulis semula kueri dan menghasilkan jawapan dengan hy4
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="local")
def rewrite(query: str) -> str:
r = client.chat.completions.create(
model="local-model",
messages=[
{"role": "system", "content": "Tulis semula soalan pengguna kepada 3 frasa kata kunci untuk carian vektor, satu setiap baris, tanpa penerangan."},
{"role": "user", "content": query},
],
temperature=0.1,
)
return r.choices[0].message.content
def answer(query: str, context_chunks: list[str]) -> str:
context = "\n\n---\n\n".join(context_chunks)
r = client.chat.completions.create(
model="local-model",
messages=[
{"role": "system", "content":
"Anda ialah pembantu pangkalan pengetahuan. Jawab hanya daripada bahan yang diberikan. "
"Jika bahan tidak mengandungi maklumat itu, nyatakan dengan jelas bahawa bahan belum menyebutnya, jangan berspekulasi. "
"Jawab dalam 300 perkataan dan tanda sumber pada akhir ayat dengan [petikan N]."},
{"role": "user", "content": f"Bahan:\n{context}\n\nSoalan: {query}"},
],
temperature=0.2,
)
return r.choices[0].message.content
rewritten = rewrite(query)
print(answer(query, [chunks[i] for i in final_idx]))
Kunci tiga ikatan dalam prompt
Jawab hanya daripada bahan, nyatakan apabila bahan tidak mengandungi maklumat itu, dan sebut nombor petikan. Tiga baris ini mengurangkan kadar mengada-ngada model 4B dengan ketara. Model 4B tidak memutuskan sendiri sama ada ia harus mengada-ngada, tetapi boleh diikat oleh arahan.
Lima kesilapan yang anda akan temui
Kesilapan satu: pemotongan memutuskan makna
Gejalanya ialah petikan yang diambil terbaca tak lengkap dan jawapan mengandungi separuh ayat. Betulkan dengan memotong mengikut hierarki tajuk dan mengekalkan tajuk sebagai awalan, kemudian memotong semula mengikut sempadan ayat.
Kesilapan dua: hanya recall tanpa penyusunan semula
Gejalanya ialah dokumen yang betul berjaya diambil tetapi berada pada kedudukan 12 dan dipotong oleh penapis top-4. Betulkan dengan menambah jumlah recall dan menambah reranker, atau menggunakan beberapa versi penulisan semula kueri dan menggabungkan keputusannya.
Kesilapan tiga: prompt tanpa ikatan
Gejalanya ialah model melengkapkan dengan pengetahuan latihan dan kekal yakin walaupun bahan tidak mengandungi maklumat itu. Betulkan dengan arahan eksplisit "nyatakan sahaja jika tiada dalam bahan", menyebut nombor petikan, dan menurunkan temperature di bawah 0.2.
Kesilapan empat: menganggap recall sebagai soal jawab
Gejalanya ialah pengguna bertanya bagaimana menggunakan sesuatu ciri dan model menjawab dengan perenggan pengenalan produk tentang apa fungsi ciri itu. Betulkan dengan mengelaskan soalan terlebih dahulu (cari fakta, panduan langkah, penyelesaian masalah) dan menggunakan templat prompt yang berbeza bagi setiap jenis.
Kesilapan lima: memenuhi konteks berlebihan
Gejalanya ialah hy4 gagal mencari ayat utama di sebalik banyak bahan dan mula berulang. hy4 memang menyokong konteks 256K secara native, tetapi boleh dimasukkan tidak bermaksud boleh digunakan dengan baik. Setiap panggilan sebaiknya hanya menerima 4 hingga 8 petikan, dan mampatkan dahulu jika lebih.
Bila sebaiknya tidak menggunakan model 4B untuk penjanaan
| Situasi | Pilihan yang lebih baik |
|---|---|
| Perlu sintesis merentas lebih 5 sumber | Model besar di cloud |
| Hasilnya laporan panjang atau kertas kerja | Model besar di cloud |
| Recall buruk dan dokumen tidak pernah muncul | Betulkan recall, jangan tukar penjana |
| Soal jawab bervolume tinggi dengan keperluan latensi rendah | hy4 atau model ringan seumpamanya |
| Dokumen sumber panjang yang perlu ringkasan panjang | Model yang lebih kuat dalam konteks, atau ringkaskan peringkat dahulu |
Catatan tambahan sebelum digunakan sebenar
Tiga perkara yang mudah dilupakan ketika berpindah daripada ujian kepada penggunaan harian:
- Simpan rekod ukuran recall. Jalankan satu set soalan ujian setiap kali anda mengubah cara memotong dokumen atau menukar embedding, kerana angka recall@k lah yang memberitahu apa yang berjaya.
- Pastikan petikan masih boleh dikesan. Simpan tajuk dan laluan dokumen bagi setiap petikan, supaya jawapan yang salah boleh ditelusuri kembali ke sumbernya.
- Sediakan laluan sandaran. Bagi perkhidmatan dalaman, sediakan model ringan lain sebagai sandaran apabila hy4 sedang sibuk atau sedang dimuatkan semula.
Dengan ketiga-tiganya, perjalanan daripada ujian kepada penggunaan harian menjadi jauh lebih pendek.
FAQ
Adakah model 4B cukup untuk RAG?
Berapa lama konteks yang disokong hy4?
Model embedding manakah yang patut digunakan?
Adakah reranking diperlukan?
Bagaimana mengurangkan pengada-ngadaan model?
Bagaimana menyambung endpoint hy4 tempatan kepada aplikasi sedia ada?
Bacaan lanjutan
- Halaman model hy4 β spesifikasi, matriks quantization dan pengiraan memori
- Nota saluran hy4-preview β saluran konteks 1M
- Pemasangan hy4 dengan GGUF β langkah lengkap agar pelayan berjalan
- Menjalankan hy4 dengan Ollama β menyambung endpoint tempatan kepada alat pembangunan
- Open WebUI dengan Hunyuan tempatan β antara muka perbualan yang dihos sendiri
- Panduan kejuruteraan konteks β mengatur maklumat dalam belanjawan tetingkap
- Panduan pemilihan model embedding β bagaimana bge, gte, jina, dan e5 berbeza
- Panduan pemilihan model hy4 β saiz dan pembahagian dengan A13B
Sumber data
Angka muat turun dan spesifikasi mengikut repositori rasmi yang berlaku semasa, disampel November 2026.