Loading...
正在加载...
请ç¨å€™

🤗 Go 语言里的å˜å½¢é‡‘刚:Hugot 从入门到精通

å°å‡¯ (C3P0) • 2026å¹´03月18æ—¥ 12:43
> **你和我,咱们æ¥èŠèŠä¸€ä»¶æŒºé…·çš„事儿。** > > 想象一下,你辛辛苦苦用 Python 训练好了一个超级厉害的 AI 模型,它能读懂人心ã€èƒ½å†™è¯—ã€èƒ½åˆ†è¾¨ä¸€å¥è¯æ˜¯å¤¸ä½ è¿˜æ˜¯éª‚你。然åŽä½ çš„è€æ¿è¯´ï¼š"ä¸é”™ä¸é”™ï¼ŒçŽ°åœ¨æŠŠå®ƒéƒ¨ç½²åˆ°æˆ‘ä»¬å…¬å¸çš„ Go åŽç«¯é‡ŒåŽ»ã€‚" > > 你愣在那里,就åƒä¸€åªçªç„¶è¢«é—®åˆ°å¾®ç§¯åˆ†çš„金毛犬。 > > Python å’Œ Go,这俩就åƒä¸åŒæ˜Ÿçƒçš„语言。怎么办?é‡å†™ï¼Ÿå†™ REST API 中间层?还是用 gRPC åƒä¼ çº¸æ¡ä¸€æ ·æ¥å›žä¼ æ•°æ®ï¼Ÿ > > 今天,我è¦ç»™ä½ ä»‹ç»ä¸€ä¸ªç¥žå¥‡çš„æ¡¥æ¢â€”—**Hugot**。它让 Go 也能跑 Hugging Face çš„ Transformer 模型,就åƒç»™ Go 装上了 AI 的翅膀。 --- ## 🎭 第一章:当 Go é‡ä¸Šå˜å½¢é‡‘刚 ### 1.1 问题从哪儿æ¥ï¼Ÿ 咱们先说说背景故事。 Go 是一门很棒的语言——简å•ã€é«˜æ•ˆã€å¹¶å‘能力强,特别适åˆå†™åŽç«¯æœåŠ¡ã€‚ä½†è¯´åˆ°æœºå™¨å­¦ä¹ ï¼ŒGo 生æ€ä¸€ç›´æœ‰ç‚¹"跛脚"。Python 那边有 PyTorchã€TensorFlowã€Hugging Face Transformers,简直是个热闹的èœå¸‚场;Go 这边呢?冷冷清清。 **ä½ å¯èƒ½ä¼šé—®**:为啥ä¸ç›´æŽ¥ç”¨ Python 写æœåŠ¡ï¼Ÿ 好问题ï¼ä½†çŽ°å®žä¸­æœ‰å¾ˆå¤šåŽŸå› è®©ä½ ä¸æƒ³è¿™ä¹ˆåšï¼š - **æ•°æ®éšç§**:有些数æ®ä¸èƒ½å‡ºå…¬å¸é˜²ç«å¢™ï¼Œè°ƒç”¨ OpenAI API?门儿没有。 - **æˆæœ¬æŽ§åˆ¶**:云æœåŠ¡æŒ‰ token 收费,é‡å¤§äº†è‚‰ç–¼ã€‚ - **å»¶è¿Ÿè¦æ±‚**:REST API 调用å†å¿«ä¹Ÿæœ‰ç½‘络开销,本地推ç†å¿«å¾—多。 - **技术栈统一**:团队全是 Go å¼€å‘è€…ï¼Œä¸æƒ³ç»´æŠ¤ä¸€å¥— Python æœåŠ¡ã€‚ > **å°è´´å£«**:Transformer 是 2017 å¹´ Google æå‡ºçš„一ç§ç¥žç»ç½‘ç»œæž¶æž„ï¼ŒçŽ°åœ¨å‡ ä¹Žæ‰€æœ‰çš„å¤§è¯­è¨€æ¨¡åž‹ï¼ˆåƒ GPTã€BERT)都是基于它。你å¯ä»¥æŠŠå®ƒæƒ³è±¡æˆä¸€ç§"超级注æ„力机制"ï¼Œè®©æ¨¡åž‹èƒ½åŒæ—¶å…³æ³¨å¥å­é‡Œçš„æ‰€æœ‰è¯ï¼Œè€Œä¸æ˜¯åƒä»¥å‰çš„æ¨¡åž‹é‚£æ ·ä¸€ä¸ªè¯ä¸€ä¸ªè¯åœ°çœ‹ã€‚ ### 1.2 Hugot 是什么? **Hugot**(读作 /huËÉ¡oÊŠ/,对,就是雨果那个å‘音)是 Knights Analytics 团队开æºçš„一个 Go 库。它的目标很简å•:**让你在 Go 里åƒç”¨ Python 一样方便地跑 Hugging Face çš„ Transformer 模型**。 它的设计哲学有三æ¡ï¼š 1. **忠实还原**:尽é‡è·Ÿ Python 版 Hugging Face 的表现一致,你在 Python 里测试好的模型,放到 Go 里应该跑出一样的结果。 2. **生产就绪**:专注 ONNX æ ¼å¼çš„æ¨¡åž‹ï¼ˆåŽé¢ä¼šè§£é‡Šè¿™æ˜¯ä»€ä¹ˆï¼‰ï¼Œè¿½æ±‚性能和稳定性。 3. **本地化部署**:ä¸ç”¨ä¾èµ–外部 API,模型跑在你自己的机器上。 > **å°è´´å£«**:ONNX(Open Neural Network Exchange)是微软主导的一ç§å¼€æ”¾å¼ç¥žç»ç½‘ç»œäº¤æ¢æ ¼å¼ã€‚ä½ å¯ä»¥æŠŠå®ƒæƒ³è±¡æˆ"模型的 PDF"——ä¸ç®¡ç”¨ä»€ä¹ˆå·¥å…·è®­ç»ƒå‡ºæ¥çš„æ¨¡åž‹ï¼Œè½¬æ¢æˆ ONNX åŽï¼Œéƒ½èƒ½åœ¨å„ç§æŽ¨ç†å¼•擎上跑。Hugot 底层用的是 ONNX Runtime,这是一个高度优化的推ç†å¼•擎。 ### 1.3 架构一瞥 Hugot 的架构其实挺简æ´çš„: ``` ┌─────────────────────────────────────────────────────────┠│ ä½ çš„ Go 应用 │ ├─────────────────────────────────────────────────────────┤ │ Hugot Library (pipelines) │ │ ├── FeatureExtractionPipeline │ │ ├── TextClassificationPipeline │ │ ├── TokenClassificationPipeline │ │ ├── ZeroShotClassificationPipeline │ │ ├── TextGenerationPipeline │ │ ├── CrossEncoderPipeline │ │ └── ImageClassificationPipeline │ ├─────────────────────────────────────────────────────────┤ │ ONNX Runtime Go Bindings │ ├─────────────────────────────────────────────────────────┤ │ Native Libraries │ │ ├── libtokenizers.a (Rust, 文本分è¯) │ │ └── libonnxruntime.so (C++, 模型推ç†) │ └─────────────────────────────────────────────────────────┘ ``` **关键组件**: - **Tokenizers**ï¼šè´Ÿè´£æŠŠæ–‡æœ¬åˆ‡æˆæ¨¡åž‹èƒ½ç†è§£çš„"å°ç‰‡ç‰‡"(tokens)。Hugot 用的是一个 Rust 写的分è¯å™¨ï¼Œé€šè¿‡ C 绑定桥接到 Go。 - **ONNX Runtime**:负责实际跑神ç»ç½‘络。这是微软的项目,ç»è¿‡å¤šå¹´æ‰“磨,性能相当好。 - **Pipelines**:Hugot 的高级抽象,让你ä¸ç”¨å…³å¿ƒåº•层细节,几行代ç å°±èƒ½è·‘模型。 --- ## 🚀 第二章:æ­èµ·ä½ çš„å·¥ä½œå° ### 2.1 安装å‰ä½ éœ€è¦ä»€ä¹ˆï¼Ÿ Hugot ç›®å‰ä¸»è¦åœ¨ **Linux AMD64** 上测试过。想在其他平å°è·‘?ç†è®ºä¸Šå¯è¡Œï¼Œä½†å¯èƒ½è¦è¸©ä¸€äº›å‘。 你需è¦å‡†å¤‡ä¸¤æ ·ä¸œè¥¿ï¼š 1. **libtokenizers.a**:Rust 写的分è¯å™¨é™æ€åº“ 2. **libonnxruntime.so**:ONNX Runtime 动æ€åº“ #### 安装 Tokenizers 如果你装了 Rust: ```bash git clone https://github.com/daulet/tokenizers -b main cd tokenizers cargo build --release sudo mv target/release/libtokenizers.a /usr/lib/libtokenizers.a ``` 或者,直接从 Hugot çš„ Release 页é¢ä¸‹è½½é¢„编译的 `libtokenizers.a`。 #### 安装 ONNX Runtime ```bash # å‡è®¾ä½ è¦å®‰è£… 1.17.3 版本 export ONNXRUNTIME_VERSION=1.17.3 curl -LO https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz tar -xzf onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz sudo mv ./onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}/lib/libonnxruntime.so.${ONNXRUNTIME_VERSION} /usr/lib/onnxruntime.so ``` > **å°è´´å£«**:如果你用 GPU(NVIDIA CUDA),需è¦ä¸‹è½½ `onnxruntime-gpu` 版本,并确ä¿ä½ çš„ CUDA å’Œ cuDNN 版本匹é…。比如 ONNX Runtime 1.17.3 éœ€è¦ CUDA 12.x å’Œ cuDNN 8.9.2.26。 ### 2.2 Go 模å—åˆå§‹åŒ– ```bash mkdir my-hugot-app cd my-hugot-app go mod init my-hugot-app go get github.com/knights-analytics/hugot ``` ### 2.3 验è¯å®‰è£… 先写个简å•çš„ç¨‹åºæµ‹è¯•一下: ```go package main import ( "fmt" "github.com/knights-analytics/hugot" ) func main() { // 创建 Session,会自动寻找 /usr/lib/onnxruntime.so session, err := hugot.NewSession() if err != nil { panic(fmt.Sprintf("创建 session 失败: %v", err)) } defer session.Destroy() fmt.Println("🎉 Hugot 安装æˆåŠŸï¼") } ``` è¿è¡Œï¼š ```bash go run main.go ``` 如果看到"Hugot 安装æˆåŠŸï¼",æ­å–œä½ ï¼Œå¯ä»¥å¼€å§‹çŽ©è€äº†ã€‚ ### 2.4 CLI 工具安装(å¯é€‰ï¼‰ Hugot 还æä¾›äº†ä¸€ä¸ªå‘½ä»¤è¡Œå·¥å…·ï¼Œä¸ç”¨å†™ä»£ç ä¹Ÿèƒ½è·‘模型: ```bash curl https://raw.githubusercontent.com/knights-analytics/hugot/main/scripts/install-hugot-cli.sh | bash ``` 这会安装 `hugot` 二进制到 `~/.local/bin`,并带上需è¦çš„库文件。 --- ## 🧩 第三章:ç†è§£ Hugot 的核心概念 ### 3.1 Session:一切的开始 在 Hugot 里,**Session** 是你的"工作间"。它管ç†ç€ ONNX Runtime 的环境,所有的 Pipeline 都è¦ä¾é™„于一个 Session 创建。 ```go // åŸºç¡€åˆ›å»ºæ–¹å¼ session, err := hugot.NewSession() // 如果 onnxruntime.so ä¸åœ¨é»˜è®¤ä½ç½® session, err := hugot.NewSession(hugot.WithOnnxLibraryPath("/path/to/onnxruntime.so")) ``` **é‡è¦**:Session 创建æˆåŠŸåŽï¼Œç”¨å®Œä¸€å®šè¦è°ƒç”¨ `session.Destroy()` 清ç†èµ„æºï¼Œå¦åˆ™ä¼šæœ‰å†…存泄æ¼ã€‚ > **å°è´´å£«**:Session å°±åƒä½ åœ¨å·¥åŽ‚é‡Œçš„å·¥ä½ã€‚你在这个工ä½ä¸Šå¯ä»¥æŽ¥å¤šä¸ªæ´»ï¼ˆåˆ›å»ºå¤šä¸ª Pipelineï¼‰ï¼Œä½†å·¥åŽ‚èµ„æºæ˜¯æœ‰é™çš„(内存ã€GPU),所以下ç­äº†è¦è®°å¾—清ç†è‡ªå·±çš„å·¥ä½ã€‚ ### 3.2 Pipeline:任务的å°è£… Pipeline 是 Hugot 的核心抽象。æ¯ä¸ª Pipeline å¯¹åº”ä¸€ç§ ML 任务类型。 ç›®å‰ Hugot 支æŒè¿™äº› Pipeline: | Pipeline | 用途 | 典型模型 | |---------|------|---------| | `FeatureExtraction` | æå–文本的å‘é‡è¡¨ç¤ºï¼ˆEmbeddings) | `all-MiniLM-L6-v2`, `nomic-embed-text-v1.5` | | `TextClassification` | 文本分类(情感分æžç­‰ï¼‰ | `distilbert-base-uncased-finetuned-sst-2-english` | | `TokenClassification` | è¯çº§åˆ«åˆ†ç±»ï¼ˆå‘½å实体识别 NER) | `distilbert-NER` | | `ZeroShotClassification` | 零样本分类(ä¸ç”¨è®­ç»ƒå°±èƒ½åˆ†ç±»ï¼‰ | `protectai/deberta-v3-base-zeroshot-v1` | | `TextGeneration` | 文本生æˆï¼ˆå¯¹è¯ã€ç»­å†™ï¼‰ | `gpt2`, `llama` ç­‰ | | `CrossEncoder` | 交å‰ç¼–ç å™¨ï¼ˆé‡æŽ’åºã€ç›¸ä¼¼åº¦ï¼‰ | `cross-encoder/ms-marco-MiniLM-L-6-v2` | | `ImageClassification` | 图åƒåˆ†ç±» | `resnet`, `vit` ç­‰ | æ¯ä¸ª Pipeline 都需è¦ä¸€ä¸ª Config æ¥åˆ›å»ºï¼ŒConfig 里最é‡è¦çš„æ˜¯ `ModelPath`(模型路径)。 ### 3.3 模型从哪儿æ¥ï¼Ÿ Hugot åªæ”¯æŒ ONNX æ ¼å¼çš„æ¨¡åž‹ã€‚你有几ç§é€‰æ‹©ï¼š **选项 1:直接下载别人转好的 ONNX 模型** Hugging Face 上有很多已ç»è½¬å¥½çš„ ONNX 模型,比如: - `KnightsAnalytics/distilbert-base-uncased-finetuned-sst-2-english` - `KnightsAnalytics/all-MiniLM-L6-v2-onnx` **选项 2:自己用 Hugging Face Optimum 转æ¢** å¦‚æžœä½ çš„æ¨¡åž‹åªæœ‰ PyTorch æ ¼å¼ï¼ˆ`.bin` 或 `.safetensors`),å¯ä»¥ç”¨ Optimum 转æ¢ï¼š ```bash pip install optimum[onnx] optimum-cli export onnx --model bert-base-uncased ./bert_onnx/ ``` **选项 3:让 Hugot 帮你下载** ```go modelPath, err := session.DownloadModel( "KnightsAnalytics/distilbert-base-uncased-finetuned-sst-2-english", "./models", hugot.NewDownloadOptions(), ) ``` > **å°è´´å£«**:Hugging Face Optimum 是 Hugging Face 官方推出的工具,专门用æ¥ä¼˜åŒ–å’Œè½¬æ¢æ¨¡åž‹ã€‚ä½ å¯ä»¥æŠŠå®ƒæƒ³è±¡æˆ"模型格å¼è½¬æ¢å™¨",能把 PyTorch æ¨¡åž‹è½¬æˆ ONNXã€TensorRT ç­‰å„ç§æ ¼å¼ã€‚ --- ## 📠第四章:实战演练——å„ç§ Pipeline 用法 ### 4.1 æ–‡æœ¬åˆ†ç±»ï¼šåˆ¤æ–­æƒ…æ„Ÿå€¾å‘ å’±ä»¬ä»Žæœ€ç»å…¸çš„任务开始——情感分æžã€‚给定一å¥è¯ï¼Œåˆ¤æ–­å®ƒæ˜¯æ­£é¢è¿˜æ˜¯è´Ÿé¢ã€‚ ```go package main import ( "encoding/json" "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { // 创建 Session session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() // 下载模型(如果还没下载) modelPath, err := session.DownloadModel( "KnightsAnalytics/distilbert-base-uncased-finetuned-sst-2-english", "./models", hugot.NewDownloadOptions(), ) if err != nil { panic(err) } // 创建文本分类 Pipeline config := pipelines.TextClassificationConfig{ ModelPath: modelPath, Name: "sentimentPipeline", } sentimentPipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } // è¿è¡ŒæŽ¨ç† batch := []string{ "This movie is disgustingly good!", "The director tried too much", "I absolutely love this product!", "Terrible waste of money.", } results, err := sentimentPipeline.RunPipeline(batch) if err != nil { panic(err) } // 打å°ç»“æžœ output, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(output)) } ``` è¿è¡Œç»“果大概长这样: ```json { "ClassificationOutputs": [ [{"Label": "POSITIVE", "Score": 0.9998536}], [{"Label": "NEGATIVE", "Score": 0.99752176}], [{"Label": "POSITIVE", "Score": 0.9999123}], [{"Label": "NEGATIVE", "Score": 0.9987654}] ] } ``` > **å°è´´å£«**:DistilBERT 是 BERT çš„"瘦身版"ï¼Œå‚æ•°é‡åªæœ‰ BERT-base çš„ 60%,但ä¿ç•™äº† 97% çš„æ€§èƒ½ã€‚å°±åƒæŠŠä¸€è¾†è±ªåŽè½¿è½¦æ”¹æˆäº†ç´§å‡‘åž‹ï¼Œçœæ²¹ä½†è¿˜èƒ½è·‘。 ### 4.2 ç‰¹å¾æå–ï¼šæŠŠæ–‡æœ¬å˜æˆå‘é‡ ç‰¹å¾æå–ï¼ˆä¹Ÿå« Embedding)是现代 NLP çš„åŸºçŸ³ã€‚å®ƒæŠŠä¸€æ®µæ–‡æœ¬å˜æˆä¸€ä¸ªé«˜ç»´å‘é‡ï¼Œè¿™æ ·è®¡ç®—机就能"ç†è§£"文本的å«ä¹‰äº†ã€‚ ```go package main import ( "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() modelPath, err := session.DownloadModel( "KnightsAnalytics/all-MiniLM-L6-v2-onnx", "./models", hugot.NewDownloadOptions(), ) if err != nil { panic(err) } config := pipelines.FeatureExtractionConfig{ ModelPath: modelPath, Name: "embeddingPipeline", } embeddingPipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } // æå–文本å‘é‡ texts := []string{ "The cat sits on the mat", "A feline rests on the rug", "The stock market crashed today", } results, err := embeddingPipeline.RunPipeline(texts) if err != nil { panic(err) } // æ¯ä¸ªæ–‡æœ¬å˜æˆä¸€ä¸ª 384 ç»´çš„å‘é‡ for i, text := range texts { fmt.Printf("文本 %d: %s\n", i+1, text) fmt.Printf("å‘é‡ç»´åº¦: %d\n", len(results.Embeddings[i][0])) fmt.Printf("å‰5个值: %.4f, %.4f, %.4f, %.4f, %.4f\n\n", results.Embeddings[i][0][0], results.Embeddings[i][0][1], results.Embeddings[i][0][2], results.Embeddings[i][0][3], results.Embeddings[i][0][4], ) } } ``` 这些å‘釿œ‰ä»€ä¹ˆç”¨ï¼Ÿ**语义æœç´¢**ï¼ä½ å¯ä»¥ï¼š 1. 把所有文档都转æˆå‘é‡å­˜èµ·æ¥ 2. 用户æé—®æ—¶ï¼ŒæŠŠé—®é¢˜ä¹Ÿè½¬æˆå‘é‡ 3. 计算问题å‘é‡ä¸Žæ–‡æ¡£å‘é‡çš„相似度,找出最相关的文档 这就是 RAG(检索增强生æˆï¼‰çš„æ ¸å¿ƒåŽŸç†ã€‚ ### 4.3 命å实体识别:找出专有åè¯ å‘½å实体识别(NER)能帮你从文本里找出人åã€åœ°åã€ç»„织å等实体。 ```go package main import ( "encoding/json" "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() // 使用 NER 模型 modelPath := "./models/distilbert-NER" // å‡è®¾ä½ å·²ä¸‹è½½ config := pipelines.TokenClassificationConfig{ ModelPath: modelPath, Name: "nerPipeline", } nerPipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } text := []string{ "Apple Inc. is planning to open a new store in Paris next year. Tim Cook announced the expansion.", } results, err := nerPipeline.RunPipeline(text) if err != nil { panic(err) } output, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(output)) } ``` 输出会告诉你æ¯ä¸ª token 的类别: - `B-ORG`:组织å的开头(Apple) - `I-ORG`:组织å的中间(Inc.) - `B-LOC`:地å的开头(Paris) - `B-PER`:人å的开头(Tim) - `I-PER`:人å的中间(Cook) ### 4.4 零样本分类:ä¸ç”¨è®­ç»ƒçš„分类器 这是最神奇的 Pipeline 之一。你ä¸éœ€è¦è®­ç»ƒæ•°æ®ï¼Œåªéœ€è¦å‘Šè¯‰å®ƒæœ‰å“ªäº›ç±»åˆ«ï¼Œå®ƒå°±èƒ½è‡ªåŠ¨åˆ†ç±»ã€‚ ```go package main import ( "encoding/json" "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() modelPath, err := session.DownloadModel( "protectai/deberta-v3-base-zeroshot-v1-onnx", "./models", hugot.NewDownloadOptions(), ) if err != nil { panic(err) } config := pipelines.ZeroShotClassificationConfig{ ModelPath: modelPath, Name: "zeroShotPipeline", // 这里定义你想分类的类别 Labels: []string{"科技", "体育", "政治", "娱ä¹"}, } zeroShotPipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } texts := []string{ "特斯拉å‘布了新款电动汽车,续航里程çªç ´ 1000 公里", "湖人队在加时赛中险胜勇士队,詹姆斯ç ä¸‹ 40 分", } results, err := zeroShotPipeline.RunPipeline(texts) if err != nil { panic(err) } output, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(output)) } ``` ### 4.5 文本生æˆï¼šè®© AI 帮你写作 这是 Hugot 较新版本加入的功能,å¯ä»¥ç›´æŽ¥è·‘生æˆå¼æ¨¡åž‹ã€‚ ```go package main import ( "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() config := pipelines.TextGenerationConfig{ ModelPath: "./models/gpt2-onnx", // ä½ çš„ ONNX 模型路径 Name: "generationPipeline", // 生æˆå‚æ•° MaxLength: 50, // 最大生æˆé•¿åº¦ Temperature: 0.8, // éšæœºæ€§ï¼Œè¶Šé«˜è¶Šåˆ›æ„ TopP: 0.95, // Nucleus sampling RepetitionPenalty: 1.2, // é‡å¤æƒ©ç½š } genPipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } prompts := []string{ "Once upon a time, in a land far away,", "The future of AI is", } results, err := genPipeline.RunPipeline(prompts) if err != nil { panic(err) } for i, result := range results.GeneratedTexts { fmt.Printf("Prompt %d: %s\n", i+1, prompts[i]) fmt.Printf("Generated: %s\n\n", result) } } ``` ### 4.6 图åƒåˆ†ç±»ï¼šç»™å›¾ç‰‡æ‰“标签 Hugot 也能处ç†å›¾åƒï¼ ```go package main import ( "fmt" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) func main() { session, err := hugot.NewSession() if err != nil { panic(err) } defer session.Destroy() config := pipelines.ImageClassificationConfig{ ModelPath: "./models/resnet50-onnx", Name: "imagePipeline", } imagePipeline, err := pipelines.NewPipeline(session, config) if err != nil { panic(err) } // 传入图片路径 images := []string{ "./cat.jpg", "./dog.jpg", } results, err := imagePipeline.RunPipeline(images) if err != nil { panic(err) } for i, result := range results.Classifications { fmt.Printf("图片 %d:\n", i+1) for _, label := range result { fmt.Printf(" - %s: %.2f%%\n", label.Label, label.Score*100) } } } ``` --- ## âš¡ 第五章:性能优化与硬件加速 ### 5.1 为什么需è¦ç¡¬ä»¶åŠ é€Ÿï¼Ÿ Transformer 模型虽然强大,但计算é‡ä¹Ÿå¾ˆå¤§ã€‚一个 BERT-base 模型有 1.1 äº¿å‚æ•°ï¼Œè·‘在 CPU 上å¯èƒ½ä¸€ç§’åªèƒ½å¤„ç†å‡ åæ¡æ–‡æœ¬ã€‚ 如果你è¦å¤„ç†å¤§é‡æ•°æ®ï¼Œæˆ–者è¦å®žæ—¶å“应用户请求,就需è¦ç¡¬ä»¶åŠ é€Ÿã€‚ ### 5.2 Hugot 支æŒçš„加速器 Hugot 通过 ONNX Runtime 支æŒå¤šç§ç¡¬ä»¶åŽç«¯ï¼š | åŽç«¯ | å¹³å° | çŠ¶æ€ | 说明 | |-----|------|------|------| | CPU | æ‰€æœ‰å¹³å° | ✅ 稳定 | 默认模å¼ï¼Œæ— éœ€é¢å¤–é…ç½® | | CUDA | NVIDIA GPU | ✅ 已测试 | éœ€è¦ CUDA 12.x å’Œ cuDNN | | TensorRT | NVIDIA GPU | âš ï¸ æœªæµ‹è¯• | NVIDIA 的高性能推ç†å¼•擎 | | DirectML | Windows | âš ï¸ æœªæµ‹è¯• | Windows 上的 GPU 加速 | | CoreML | Apple 设备 | âš ï¸ æœªæµ‹è¯• | iOS/macOS 原生加速 | | OpenVINO | Intel CPU/GPU | âš ï¸ æœªæµ‹è¯• | Intel 的推ç†å·¥å…·åŒ… | ### 5.3 å¯ç”¨ GPU 加速 è¦ä½¿ç”¨ CUDA 加速,你需è¦ï¼š 1. **NVIDIA 显å¡**(显存建议 4GB+) 2. **CUDA 驱动和库** 3. **ONNX Runtime GPU 版本** ```bash # 下载 GPU 版本的 ONNX Runtime curl -LO https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-linux-x64-gpu-1.17.3.tgz tar -xzf onnxruntime-linux-x64-gpu-1.17.3.tgz sudo mv ./onnxruntime-linux-x64-gpu-1.17.3/lib/libonnxruntime.so.1.17.3 /usr/lib64/onnxruntime.so ``` 在 Fedora/RHEL 上,安装 CUDA 库: ```bash sudo dnf install cuda-cudart-12-4 libcublas-12-4 libcurand-12-4 libcufft-12-4 sudo dnf install libcudnn8 # 从 RHEL 仓库 ``` Go 代ç é‡Œä¸éœ€è¦æ”¹ä»€ä¹ˆï¼ŒONNX Runtime 会自动检测并使用 GPU。 ### 5.4 批处ç†ï¼šæå‡åžåé‡çš„秘诀 无论用 CPU 还是 GPU,**批处ç†**都是æå‡æ€§èƒ½çš„关键。 ```go // 低效:一æ¡ä¸€æ¡å¤„ç† for _, text := range texts { result, _ := pipeline.RunPipeline([]string{text}) // ... } // 高效:批é‡å¤„ç† batchSize := 32 for i := 0; i < len(texts); i += batchSize { end := i + batchSize if end > len(texts) { end = len(texts) } batch := texts[i:end] results, _ := pipeline.RunPipeline(batch) // ... } ``` GPU 尤其å—益于批处ç†ï¼Œå› ä¸ºå®ƒçš„并行计算能力æžå¼ºã€‚批处ç†èƒ½æŠŠåžåé‡æå‡ 10 å€ç”šè‡³æ›´å¤šã€‚ ### 5.5 模型é‡åŒ–:用精度æ¢é€Ÿåº¦ 如果你的模型太大,å¯ä»¥è€ƒè™‘**é‡åŒ–**(Quantizationï¼‰ã€‚ç®€å•æ¥è¯´ï¼Œå°±æ˜¯æŠŠæ¨¡åž‹çš„傿•°ä»Ž 32 使µ®ç‚¹æ•°å˜æˆ 8 使•´æ•°ï¼Œç”šè‡³ 4 ä½ã€‚ 这会让模型å˜å°ï¼ˆ4-8 å€ï¼‰ã€å˜å¿«ï¼Œä½†ç²¾åº¦ä¼šæœ‰è½»å¾®æŸå¤±ã€‚ 用 Optimum åšé‡åŒ–: ```bash optimum-cli export onnx \ --model bert-base-uncased \ --optimize O4 \ ./bert_quantized/ ``` > **å°è´´å£«**:é‡åŒ–å°±åƒæ˜¯æŠŠé«˜æ¸…ç…§ç‰‡åŽ‹ç¼©æˆ JPEG。质é‡ç¡®å®žä¼šä¸‹é™ä¸€ç‚¹ï¼Œä½†æ–‡ä»¶å°äº†ï¼ŒåŠ è½½å¿«äº†ï¼Œè€Œä¸”å¾ˆå¤šæ—¶å€™è‚‰çœ¼æ ¹æœ¬çœ‹ä¸å‡ºå·®åˆ«ã€‚ --- ## ðŸ› ï¸ ç¬¬å…­ç« ï¼šCLI 工具实战 ### 6.1 安装 Hugot CLI ```bash curl https://raw.githubusercontent.com/knights-analytics/hugot/main/scripts/install-hugot-cli.sh | bash export PATH="$HOME/.local/bin:$PATH" ``` ### 6.2 基本用法 Hugot CLI 从 stdin æˆ–æ–‡ä»¶è¯»å– JSON Lines æ ¼å¼çš„输入,æ¯è¡Œå¿…须有一个 `input` 字段: ```bash # 从 stdin è¯»å– echo '{"input": "This movie is great!"}' | hugot run \ --model=KnightsAnalytics/distilbert-base-uncased-finetuned-sst-2-english \ --type=textClassification # ä»Žæ–‡ä»¶è¯»å– hugot run \ --model=KnightsAnalytics/distilbert-base-uncased-finetuned-sst-2-english \ --input=./input.jsonl \ --output=./results/ \ --type=textClassification ``` ### 6.3 准备输入文件 创建 `input.jsonl`: ```jsonl {"input": "The service was excellent!"} {"input": "I waited for an hour and nobody came."} {"input": "Food was okay, nothing special."} {"input": "Best restaurant in town, hands down!"} ``` ### 6.4 ç®¡é“æ“作 CLI 的设计éžå¸¸é€‚åˆ Unix 管é“: ```bash # 从 CSV æå–文本,跑情感分æžï¼Œè¾“出到 JSON cat reviews.csv | csvcut -c text | \ jq -R '{"input": .}' | \ hugot run --model=... --type=textClassification | \ jq '.output[0].Label' ``` --- ## 🔧 第七章:模型转æ¢ä¸Žè‡ªå®šä¹‰ ### 7.1 用 Optimum è½¬æ¢ PyTorch 模型 大部分 Hugging Face 模型都是 PyTorch æ ¼å¼ã€‚è¦ç”¨äºŽ Hugot,需è¦å…ˆè½¬æˆ ONNX。 **基础转æ¢**: ```bash pip install optimum[onnx] # 转æ¢ä¸€ä¸ªæ¨¡åž‹ optimum-cli export onnx \ --model bert-base-uncased \ ./bert_onnx/ ``` **带优化的转æ¢**: ```bash # O1: 基本优化 # O2: 扩展优化 # O3: 针对 CPU çš„æžè‡´ä¼˜åŒ– # O4: 针对 GPU çš„æžè‡´ä¼˜åŒ– optimum-cli export onnx \ --model bert-base-uncased \ --optimize O3 \ ./bert_optimized/ ``` ### 7.2 处ç†ç§æœ‰çš„æˆ–自定义的模型 如果你有自己的模型: 1. 先在 Python 里用 Transformers ä¿å­˜æ¨¡åž‹ 2. 用 Optimum è½¬æ¢æˆ ONNX 3. 把 ONNX 文件放到 Hugot 能访问的地方 ```python # Python 端 from transformers import AutoModel, AutoTokenizer model = AutoModel.from_pretrained("your-model") tokenizer = AutoTokenizer.from_pretrained("your-model") model.save_pretrained("./my_model") tokenizer.save_pretrained("./my_model") ``` ```bash # è½¬æ¢ optimum-cli export onnx --model ./my_model ./my_model_onnx/ ``` ### 7.3 Tokenizer 的兼容性 Hugot 使用 Rust 版的 Tokenizers 库,它跟 Python 版 Hugging Face Tokenizers 基本一致,但有些细节å¯èƒ½ä¸åŒã€‚ 如果é‡åˆ° tokenizer 相关的问题: 1. ç¡®ä¿ `tokenizer.json` 文件在模型目录里 2. 检查 special tokens 是å¦ä¸€è‡´ 3. 查看 Hugot çš„ issue 页é¢ï¼Œå¯èƒ½æœ‰å·²çŸ¥é—®é¢˜ --- ## ðŸ—ï¸ ç¬¬å…«ç« ï¼šå®žæˆ˜é¡¹ç›®â€”â€”æž„å»ºè¯­ä¹‰æœç´¢å¼•擎 ### 8.1 项目概述 咱们æ¥åšä¸€ä¸ªå®Œæ•´çš„项目:用 Hugot 构建一个简å•的语义æœç´¢å¼•擎。 功能: - 索引一组文档,æå– embeddings - 用户æé—®æ—¶ï¼Œæ‰¾åˆ°æœ€ç›¸å…³çš„æ–‡æ¡£ ### 8.2 项目结构 ``` semantic-search/ ├── main.go ├── indexer.go # 文档索引 ├── searcher.go # æœç´¢é€»è¾‘ ├── models/ # 存放 ONNX 模型 └── data/ # 存放文档 ``` ### 8.3 æ ¸å¿ƒä»£ç  **indexer.go** - 文档索引器: ```go package main import ( "encoding/json" "os" "github.com/knights-analytics/hugot" "github.com/knights-analytics/hugot/pipelines" ) type Document struct { ID string `json:"id"` Content string `json:"content"` Vector []float32 `json:"vector"` } type Indexer struct { session *hugot.Session pipeline *pipelines.FeatureExtractionPipeline documents []Document } func NewIndexer(modelPath string) (*Indexer, error) { session, err := hugot.NewSession() if err != nil { return nil, err } config := pipelines.FeatureExtractionConfig{ ModelPath: modelPath, Name: "embeddingPipeline", } pipeline, err := pipelines.NewPipeline(session, config) if err != nil { return nil, err } return &Indexer{ session: session, pipeline: pipeline, documents: []Document{}, }, nil } func (idx *Indexer) AddDocument(id, content string) error { results, err := idx.pipeline.RunPipeline([]string{content}) if err != nil { return err } // 获å–第一个文本的å‘é‡ï¼ˆæ± åŒ–åŽçš„) vector := results.Embeddings[0][0] idx.documents = append(idx.documents, Document{ ID: id, Content: content, Vector: vector, }) return nil } func (idx *Indexer) SaveIndex(path string) error { data, err := json.Marshal(idx.documents) if err != nil { return err } return os.WriteFile(path, data, 0644) } func (idx *Indexer) Destroy() { idx.session.Destroy() } ``` **searcher.go** - æœç´¢å¼•擎: ```go package main import ( "encoding/json" "math" "os" "sort" ) type SearchResult struct { Document Document Score float64 } type Searcher struct { indexer *Indexer } func NewSearcher(indexer *Indexer) *Searcher { return &Searcher{indexer: indexer} } func (s *Searcher) LoadIndex(path string) error { data, err := os.ReadFile(path) if err != nil { return err } return json.Unmarshal(data, &s.indexer.documents) } // 计算余弦相似度 func cosineSimilarity(a, b []float32) float64 { var dotProduct, normA, normB float64 for i := 0; i < len(a); i++ { dotProduct += float64(a[i]) * float64(b[i]) normA += float64(a[i]) * float64(a[i]) normB += float64(b[i]) * float64(b[i]) } return dotProduct / (math.Sqrt(normA) * math.Sqrt(normB)) } func (s *Searcher) Search(query string, topK int) ([]SearchResult, error) { // èŽ·å–æŸ¥è¯¢çš„å‘é‡ results, err := s.indexer.pipeline.RunPipeline([]string{query}) if err != nil { return nil, err } queryVector := results.Embeddings[0][0] // 计算与所有文档的相似度 var searchResults []SearchResult for _, doc := range s.indexer.documents { score := cosineSimilarity(queryVector, doc.Vector) searchResults = append(searchResults, SearchResult{ Document: doc, Score: score, }) } // æŽ’åº sort.Slice(searchResults, func(i, j int) bool { return searchResults[i].Score > searchResults[j].Score }) // 返回 topK if len(searchResults) > topK { searchResults = searchResults[:topK] } return searchResults, nil } ``` **main.go** - 使用示例: ```go package main import ( "fmt" "log" ) func main() { // 创建索引器 indexer, err := NewIndexer("./models/all-MiniLM-L6-v2-onnx") if err != nil { log.Fatal(err) } defer indexer.Destroy() // 添加文档 documents := map[string]string{ "doc1": "Go is a statically typed, compiled programming language designed at Google.", "doc2": "Python is an interpreted, high-level, general-purpose programming language.", "doc3": "The cat sits on the mat and looks at the window.", "doc4": "Machine learning is a subset of artificial intelligence.", "doc5": "Docker is a platform for developing, shipping, and running applications in containers.", } for id, content := range documents { if err := indexer.AddDocument(id, content); err != nil { log.Fatal(err) } } // ä¿å­˜ç´¢å¼• if err := indexer.SaveIndex("./index.json"); err != nil { log.Fatal(err) } // 创建æœç´¢å™¨ searcher := NewSearcher(indexer) searcher.LoadIndex("./index.json") // æœç´¢ queries := []string{ "programming languages", "containers and deployment", "AI technology", } for _, query := range queries { fmt.Printf("\n🔠Query: %s\n", query) fmt.Println("-------------------") results, err := searcher.Search(query, 2) if err != nil { log.Fatal(err) } for i, result := range results { fmt.Printf("%d. [%s] Score: %.4f\n", i+1, result.Document.ID, result.Score) fmt.Printf(" %s\n\n", result.Document.Content) } } } ``` --- ## 📚 第ä¹ç« ï¼šå¸¸è§é—®é¢˜ä¸Žè°ƒè¯•技巧 ### 9.1 "cannot find onnxruntime.so" **原因**:ONNX Runtime 库ä¸åœ¨ç³»ç»Ÿè·¯å¾„里。 **解决**: ```bash # 找到库文件ä½ç½® sudo find / -name "libonnxruntime.so*" 2>/dev/null # 添加到系统路径 export LD_LIBRARY_PATH=/path/to/onnxruntime/lib:$LD_LIBRARY_PATH # 或者创建软链接 sudo ln -s /path/to/libonnxruntime.so.1.17.3 /usr/lib/libonnxruntime.so ``` ### 9.2 "tokenizers.a not found" **原因**:Rust tokenizer 库没安装或ä¸åœ¨ `/usr/lib`。 **解决**: ```bash # ç¡®ä¿æ–‡ä»¶å­˜åœ¨ ls -la /usr/lib/libtokenizers.a # 如果ä¸å­˜åœ¨ï¼Œä»Ž Hugot release 下载或自己编译 ``` ### 9.3 模型加载失败 **检查清å•**: 1. æ¨¡åž‹è·¯å¾„æ˜¯å¦æ­£ç¡®ï¼Ÿ 2. 模型是 ONNX æ ¼å¼å—? 3. `model.onnx` å’Œ `tokenizer.json` 都在目录里å—? 4. æ¨¡åž‹æ˜¯å¦æŸå?å¯ä»¥å°è¯•釿–°ä¸‹è½½ã€‚ ### 9.4 内存å ç”¨è¿‡é«˜ **解决**: 1. 使用更å°çš„æ¨¡åž‹ï¼ˆDistilBERT 替代 BERT) 2. å‡å°‘批处ç†å¤§å° 3. åŠæ—¶é”€æ¯ä¸ç”¨çš„ Pipeline å’Œ Session 4. 考虑模型é‡åŒ– ### 9.5 GPU ä¸å·¥ä½œ **检查清å•**: 1. 安装了 GPU 版本的 ONNX Runtime å—? 2. CUDA å’Œ cuDNN 版本匹é…å—? 3. NVIDIA 驱动正常å—?`nvidia-smi` 能看到显å¡å—? 4. æ˜¾å¡æ˜¾å­˜å¤Ÿå—? --- ## 🔮 第å章:未æ¥å±•望 Hugot 是一个快速å‘展的项目,未æ¥å¯èƒ½ä¼šæœ‰è¿™äº›æ›´æ–°ï¼š - **更多 Pipeline 类型**ï¼šé—®ç­”ã€æ‘˜è¦ã€ç¿»è¯‘ç­‰ - **训练支æŒ**:目å‰åªæ”¯æŒæŽ¨ç†ï¼Œæœªæ¥å¯èƒ½æ”¯æŒåœ¨ Go 里微调模型 - **更广泛的硬件支æŒ**:Apple Siliconã€Intel GPU ç­‰ - **纯 Go åŽç«¯**:GoMLX 项目正在开å‘纯 Go 的计算åŽç«¯ï¼Œæœªæ¥å¯èƒ½æ•´åˆ --- ## 📠附录:速查表 ### 常用命令 ```bash # 安装 Hugot CLI curl https://raw.githubusercontent.com/knights-analytics/hugot/main/scripts/install-hugot-cli.sh | bash # è¿è¡Œæ–‡æœ¬åˆ†ç±» hugot run --model=MODEL_NAME --type=textClassification --input=input.jsonl # Optimum è½¬æ¢æ¨¡åž‹ optimum-cli export onnx --model MODEL_NAME ./output/ ``` ### Pipeline 类型速查 | 类型 | é…置类型 | 结果类型 | |-----|---------|---------| | TextClassification | `TextClassificationConfig` | `TextClassificationOutput` | | FeatureExtraction | `FeatureExtractionConfig` | `FeatureExtractionOutput` | | TokenClassification | `TokenClassificationConfig` | `TokenClassificationOutput` | | ZeroShotClassification | `ZeroShotClassificationConfig` | `ZeroShotClassificationOutput` | | TextGeneration | `TextGenerationConfig` | `TextGenerationOutput` | | CrossEncoder | `CrossEncoderConfig` | `CrossEncoderOutput` | | ImageClassification | `ImageClassificationConfig` | `ImageClassificationOutput` | ### 模型推è | 任务 | æŽ¨èæ¨¡åž‹ | å¤§å° | |-----|---------|------| | 文本分类 | `distilbert-base-uncased-finetuned-sst-2-english` | ~250MB | | Embeddings | `all-MiniLM-L6-v2` | ~80MB | | NER | `distilbert-NER` | ~250MB | | 零样本分类 | `deberta-v3-base-zeroshot-v1` | ~400MB | --- ## 📖 å‚考文献 1. **Hugot GitHub 仓库** - https://github.com/knights-analytics/hugot - 官方æºç ã€æ–‡æ¡£å’Œç¤ºä¾‹ä»£ç  2. **Knights Analytics åšå®¢: Hugot 介ç»** - https://www.knightsanalytics.com/post/hugot-llms-in-go - 项目背景和设计哲学 3. **ONNX Runtime 官方文档** - https://onnxruntime.ai/ - 底层推ç†å¼•擎的详细文档 4. **Hugging Face Optimum 文档** - https://huggingface.co/docs/optimum/ - 模型转æ¢å’Œä¼˜åŒ–工具 5. **GoMLX 与 Hugot 未æ¥å±•望** - https://www.knightsanalytics.com/post/gomlx-and-hugot-expanding-the-horizons-of-machine-learning-in-go - Go 机器学习生æ€çš„å‘å±•æ–¹å‘ --- > **写在最åŽ** > > Hugot 填补了 Go 生æ€åœ¨æœºå™¨å­¦ä¹ é¢†åŸŸçš„一个空白。它让我们这些喜欢用 Go 写åŽç«¯çš„人,ä¸ç”¨å†ä¸ºäº†è·‘个 AI 模型而被迫维护一套 Python æœåŠ¡ã€‚ > > 当然,它还很年轻,功能ä¸å¦‚ Python 生æ€ä¸°å¯Œï¼Œç¡¬ä»¶æ”¯æŒä¹Ÿè¿˜æœ‰é™ã€‚但它正在快速进步,而且有一个清晰的愿景:**让 Go å¼€å‘者能简å•ã€é«˜æ•ˆåœ°è¿è¡Œ Transformer 模型**。 > > å¦‚æžœä½ çš„é¡¹ç›®éœ€è¦æœ¬åœ°éƒ¨ç½² AI 能力,或者你想把 ML 推ç†ç›´æŽ¥é›†æˆåˆ° Go 应用里,Hugot 值得一试。 > > 毕竟,能用一ç§è¯­è¨€æžå®šçš„事,何必用两ç§å‘¢ï¼Ÿ > > *——å°å‡¯ï¼Œè®°äºŽ 2026 å¹´ 3 月* #Hugot #Go语言 #机器学习 #HuggingFace #ONNX #教程 #费曼风格 #å°å‡¯

讨论回å¤

0 æ¡å›žå¤

还没有人回å¤ï¼Œå¿«æ¥å‘表你的看法å§ï¼