Lompat ke konten
dokumentasi.id
Commit a3048a3
v1
Star929

8

Model Lokal dan HuggingFace

Halaman ini membahas dua jalur menjalankan model open-weight di mesin sendiri: 05_hf.py memakai gpt2 lewat HuggingFacePipeline di LangChain, sedangkan 07_custom.py membungkus facebook/opt-iml-1.3b ke dalam CustomLLM milik LlamaIndex. Keduanya tidak mengirim request ke penyedia model berbayar. Mekanisme index dan query LlamaIndex yang tidak spesifik ke model lokal dibahas di Indeks dan Query dengan LlamaIndex.

Migrasi dari Inference API ke eksekusi lokal

Komentar di kepala 05_hf.py menyatakan kode asli memakai remote HuggingFace Inference API, yang tidak kompatibel dengan versi paket sekarang, lalu beralih ke eksekusi lokal dengan HuggingFacePipeline 05_hf.py:14-16. Blok kode lama yang dikomentari menyebut dua sebab konkret: "HuggingFaceHub is deprecated and broken with huggingface_hub>=1.0" dan "HuggingFaceEndpoint (recommended replacement) has compatibility issues" 05_hf.py:21-32. Jalur remote juga menuntut HUGGINGFACEHUB_API_TOKEN di .env, sedangkan jalur lokal tidak memerlukan kredensial apa pun.

graph TD
    A["HuggingFaceHub (remote Inference API)"] -->|deprecated| B["broken with huggingface_hub 1.0+"]
    A --> C["HuggingFaceEndpoint (recommended replacement)"]
    C --> D["compatibility issues"]
    E["HuggingFacePipeline (local)"] --> F["AutoTokenizer + AutoModelForCausalLM: gpt2"]
    F --> G["pipeline(text-generation)"]
    G --> H["HuggingFacePipeline(pipeline=pipe)"]
    H --> I["hub_chain (LCEL)"]
    I --> J["hub_chain.invoke"]
    style A fill:#f59e0b,color:#000
    style B fill:#dc2626,color:#fff
    style C fill:#f59e0b,color:#000
    style D fill:#dc2626,color:#fff
    style E fill:#2d7d46,color:#fff
    style F fill:#336791,color:#fff
    style G fill:#336791,color:#fff
    style H fill:#8b5cf6,color:#fff
    style I fill:#8b5cf6,color:#fff
    style J fill:#2d7d46,color:#fff
%% fig: Migrasi dari Inference API ke eksekusi lokal
%% desc: Jalur remote HuggingFaceHub dan HuggingFaceEndpoint berakhir pada kegagalan, sedangkan jalur lokal membangun pipeline gpt2 sampai hub_chain.invoke.
Fig. 1: Migrasi dari Inference API ke eksekusi lokalJalur remote HuggingFaceHub dan HuggingFaceEndpoint berakhir pada kegagalan, sedangkan jalur lokal membangun pipeline gpt2 sampai hub_chain.invoke.

Perbandingan kedua pendekatan sebagaimana tertulis di berkas:

AspekHuggingFaceHub (remote)HuggingFacePipeline (lokal)
Modul importlangchain_community.llmslangchain_huggingface
Argumen modelrepo_id='gpt2', model_kwargs={'temperature': 0.7, 'max_length': 100}model_id = 'gpt2' lewat AutoTokenizer dan AutoModelForCausalLM
KredensialHUGGINGFACEHUB_API_TOKEN di .envtidak ada
Unduhan modeltidak adasekitar 500MB pada run pertama
Status di repositoryseluruh blok dikomentaridipakai oleh skrip

Menjalankan gpt2 dengan HuggingFacePipeline

Jalur yang aktif menyiapkan tiga objek berurutan: AutoTokenizer.from_pretrained(model_id), AutoModelForCausalLM.from_pretrained(model_id), lalu pipeline("text-generation", ...) yang dibungkus menjadi HuggingFacePipeline(pipeline=pipe) 05_hf.py:38-56. Komentar di berkas menandai bahwa run pertama mengunduh model sekitar 500MB 05_hf.py:38-56.

Parameter pipelineNilai di 05_hf.py
task"text-generation"
modelAutoModelForCausalLM.from_pretrained('gpt2')
tokenizerAutoTokenizer.from_pretrained('gpt2')
max_length100 dengan komentar # Total length (not new tokens)
do_sampleTrue
temperature0.7
pad_token_idtokenizer.eos_token_id untuk menekan peringatan pad_token

PromptTemplate hanya menerima satu variabel, yaitu profession, dan chain disusun dengan sintaks LCEL hub_chain = prompt | hub_llm. Skrip memanggil hub_chain.invoke empat kali dengan nilai customer service agent, politician, Fintech CEO, dan insurance agent 05_hf.py:59-68.

⚠️ max_length=100 adalah panjang total, bukan jumlah token baru, seperti ditulis pada komentar # Total length (not new tokens). Nilai itu membatasi gabungan prompt dan keluaran, sehingga prompt panjang menyisakan sedikit ruang bagi teks yang dihasilkan.

Versi paket yang dipakai terkunci di requirements.txt: langchain-huggingface==0.1.2, torch==2.10.0, dan transformers==5.2.0 requirements.txt:65, requirements.txt:147, requirements.txt:151.

Membungkus model lokal sebagai CustomLLM

07_custom.py mendefinisikan LocalOPT sebagai subclass CustomLLM dari llama_index.core.llms, sehingga LlamaIndex dapat memakai pipeline transformers sebagai LLM tanpa endpoint HTTP 07_custom.py:14-23. Seluruh kontrak kelas berada di satu tempat 07_custom.py:59-80.

Anggota LocalOPTNilai atau perilaku
model_nameClassVar[str] = "facebook/opt-iml-1.3b" dengan komentar ~2.63gb model
_pipelinepipeline("text-generation", model=model_name, device="cpu", dtype=torch.float32)
metadataLLMMetadata(model_name=self.model_name)
completememanggil pipeline dengan max_new_tokens=256, lalu mengembalikan response[len(prompt):]
stream_completeraise NotImplementedError

Model facebook/opt-iml-max-30b hanya muncul sebagai komentar karena berukuran 60gb, sedangkan yang benar-benar dimuat adalah facebook/opt-iml-1.3b 07_custom.py:59-80.

⚠️ stream_complete hanya melempar NotImplementedError 07_custom.py:59-80. Query engine yang meminta streaming=True tidak akan menerima token bertahap dari LocalOPT.

⚠️ device="cpu" dan dtype=torch.float32 membuat inferensi berjalan sepenuhnya di CPU. CHANGES.md mencatat bahwa device="cuda:0" dihapus demi kompatibilitas lintas platform, sehingga waktu eksekusi complete bergantung pada CPU mesin 07_custom.py:59-80, CHANGES.md:111-114.

load_dotenv() dikomentari dan diganti os.environ["OPENAI_API_KEY"] = "random". Nilai itu hanya kunci dummy agar LlamaIndex tidak gagal saat memvalidasi konfigurasi 07_custom.py:26.

Cache model dan index lokal

PromptHelper diatur sebelum index dibuat, dengan context_window=2048, num_output=256, dan chunk_overlap_ratio=0.1 07_custom.py:49-56. Kedua fungsi utama, create_index dan execute_query, dihias @timeit() yang mencetak durasi eksekusi dalam detik 07_custom.py:29-46.

Parameter PromptHelperNilaiKomentar di kode
context_window2048maximum input size
num_output256number of output tokens
chunk_overlap_ratio0.1the maximum overlap between chunks

create_index menetapkan Settings.llm = LocalOPT() dan Settings.prompt_helper = prompt_helper, membaca news lewat SimpleDirectoryReader, lalu membangun SummaryIndex.from_documents(docs) 07_custom.py:83-92. execute_query mengambil index.as_query_engine() dan mengirim satu pertanyaan, "Who does Indonesia export its coal to in 2023?", lalu mengembalikan response 07_custom.py:95-101.

graph TD
    MAIN["__main__"] --> CHK{"7_custom_opt exists?"}
    CHK -->|no| MISS["No local cache of model found, downloading from huggingface"]
    MISS --> CI["create_index()"]
    CI --> L1["Settings.llm = LocalOPT()"]
    CI --> L2["Settings.prompt_helper = prompt_helper"]
    CI --> RD["SimpleDirectoryReader('news').load_data()"]
    RD --> SI["SummaryIndex.from_documents(docs)"]
    SI --> PER["storage_context.persist('./7_custom_opt')"]
    CHK -->|yes| HIT["Loading local cache of model"]
    HIT --> SC["StorageContext.from_defaults(persist_dir='./7_custom_opt')"]
    SC --> LI["load_index_from_storage(storage_context)"]
    PER --> Q["execute_query()"]
    LI --> Q
    Q --> OUT["print(response) dan print(response.source_nodes)"]
    style MAIN fill:#f59e0b,color:#000
    style CHK fill:#f59e0b,color:#000
    style MISS fill:#dc2626,color:#fff
    style CI fill:#2d7d46,color:#fff
    style L1 fill:#f59e0b,color:#000
    style L2 fill:#f59e0b,color:#000
    style RD fill:#336791,color:#fff
    style SI fill:#336791,color:#fff
    style PER fill:#8b5cf6,color:#fff
    style HIT fill:#2d7d46,color:#fff
    style SC fill:#8b5cf6,color:#fff
    style LI fill:#8b5cf6,color:#fff
    style Q fill:#2d7d46,color:#fff
    style OUT fill:#2d7d46,color:#fff
%% fig: Siklus hidup index lokal di 07_custom.py
%% desc: Skrip memilih antara membangun SummaryIndex baru atau memuat cache dari direktori 7_custom_opt, lalu menjalankan satu query dan mencetak source_nodes.
Fig. 2: Siklus hidup index lokal di 07_custom.pySkrip memilih antara membangun SummaryIndex baru atau memuat cache dari direktori 7_custom_opt, lalu menjalankan satu query dan mencetak source_nodes.

Percabangan __main__ memeriksa os.path.exists("7_custom_opt"). Bila direktori belum ada, skrip mencetak "No local cache of model found, downloading from huggingface", membangun index, lalu menyimpannya dengan index.storage_context.persist(persist_dir="./7_custom_opt"). Bila sudah ada, skrip mencetak "Loading local cache of model", menetapkan ulang Settings.llm = LocalOPT(), dan memuat index lewat load_index_from_storage(storage_context) 07_custom.py:104-121. Hasil persist itu tersimpan sebagai 07_custom_opt.json dengan index_struct bertipe list dan tiga node, yaitu a2a2a221-0443-4b2b-bc2f-4e1f85005f24, 85248e83-b41a-4d6f-aca0-c2e5e92ba45d, dan 36208109-aea9-4c40-b18b-5a39debd32fb 07_custom_opt.json:1.

Lokasi unduhan model dapat dipindahkan lewat variabel lingkungan TRANSFORMERS_CACHE, misalnya export TRANSFORMERS_CACHE=/whatever/path/you/want 07_custom.py:1-4. Jalur ini yang membuat sesi kedua tidak perlu mengunduh ulang model. Tutorial video untuk bagian ini tercatat sebagai "Locally-hosted, offline LLM w/LlamaIndex + OPT (open source, instruction-tuning LLM)" README.md:25.