[實作筆記] Linux NO Password 執行指令

前情提要

最近在部署某個 webapi server,
這個 webapi 會用一個特別的帳號去執行,但是不會給他設定密碼,
我需要使用 pm2 startup 設定開機自動啟動 webapi 服務。

問題:執行指令會要求輸入密碼

但是我沒有也不打算提供密碼給個 webapi 服務帳號

1
2
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u marsen --hp /home/marsen
[sudo] password for marsen:

嘗試解法:用 visudo 寫 NOPASSWD

為了讓 aiplux 帳號執行特定指令時不需要輸入密碼,可以透過 visudo 編輯 sudoers 檔案。以下是具體步驟:

  1. 開啟 sudoers 編輯器:
1
sudo visudo
  1. 在檔案中新增以下內容:
1
aiplux ALL=(ALL) NOPASSWD: /usr/lib/node_modules/pm2/bin/pm2

這樣的設定可以確保 aiplux 帳號在執行 /usr/lib/node_modules/pm2/bin/pm2 時不需要輸入密碼,同時避免開放過多權限。

小心資安風險

上面的作法是改自另一位同事的作法,

1
2
echo "marsen ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /usr/bin/env" | sudo tee /etc/sudoers.d/marsen >/dev/null
chmod 440 /etc/sudoers.d/marsen

這段設定的目的是:

  1. 允許 marsen 自由使用 aptapt-get 安裝套件。
  2. 使用 env 包裝 PATH 或其他環境變數來執行 pm2
  3. 避免密碼卡住,讓 CI/CD 流程順利執行。

雖然給足夠的權限,可以無密碼執行,但是也帶來很多潛在風險。

資安問題:/usr/bin/env 是個危險洞口

看起來只是想加環境變數用 env,但其實這一條非常危險。為什麼?來看看 env 的本質:

1
2
3
sudo /usr/bin/env bash
sudo /usr/bin/env node
sudo /usr/bin/env python

這些指令會用 root 權限執行對應的 shell 或程式,等於你給了 marsen 完整 root 執行任意程式的能力,這十分危險。

再看 /usr/bin/aptapt-get,同樣是高權限指令。如果沒有限制,也可以被濫用來刪除套件或改動系統。

小結

審慎選擇開放的指令
在自動化流程中,為了避免 sudo 密碼擋路,設定 NOPASSWD 是常見的解法。
但在設定時,務必審慎選擇開放的指令範圍,避免一時圖方便,打開整台主機的後門。
建議只開放必要的指令,並明確指定路徑,確保安全性。

(fin)

[踩雷筆記] CORS 錯誤的元兇竟然是瀏覽器外掛?

前情提要

最近在本機開發一支簡單的上傳 API,使用 Express.js 搭配 TypeScript。
預期只是在 local 上做個整合測試,前端跑在 localhost:5173,後端是 localhost:3000,照理來說只要 CORS 設好就萬事 OK。

結果——炸了。

問題現象

瀏覽器跳出熟悉的錯誤訊息:

1
Access to fetch at 'http://localhost:3000/upload' from origin 'http://localhost:5173' has been blocked by CORS policy...

一看就是 CORS 錯誤,老問題了,馬上開始排查:

  • 確認 cors() middleware 有設好
  • 檢查 headers 有無正確設定
  • 懷疑是 OPTIONS preflight 沒處理好,也做了補強

怎麼改都一樣。

接著我試了無痕模式,欸?沒事了。
懷疑是瀏覽器快取作怪,清除後還是一樣。
換用 Edge(沒裝任何外掛)測試,正常。

真相大白

這時我就卡關了,因為一切設定看起來都沒問題。

隨口問了新人同事,提到有可能是瀏覽器外掛的問題,我再測試一下

確定是我在 Brave 安裝的外掛「Page Assist - A Web UI for Local AI Models」在搞鬼!

這個外掛可能會偷偷注入 JS 或改寫 request header,導致 CORS 預檢請求出現異常,讓瀏覽器誤以為是 server 設定問題。

我一停用外掛,再次測試,一切正常。

心得與提醒

這次的經驗讓我再次體會:

最難 debug 的錯誤,往往來自你「以為不會出錯」的地方。

給未來的自己幾個建議:

  • 開無痕模式測試:能快速排除快取與外掛的干擾
  • 換乾淨的瀏覽器:有時候 Edge 或 Safari 能救你一命
  • 早點求救:卡住就問,別一個人浪費太多時間在錯的地方打轉,別人可以給你不同觀點

這類奇怪的問題其實很常見,但也正因為難以複製與預期,才更值得記錄下來。

下次遇到奇怪的 CORS 錯誤時,可以考慮是裝的外掛在搞事。

(fin)

[實作筆記] Node.js Express 錯誤處理全攻略:同步、非同步與 Stream Error

前情提要

Node.js + Express 是開發 REST API 時最常見的組合。
這篇文章會試著寫出三大常見錯誤類型的處理方式:

  • 同步錯誤(throw)
  • 非同步錯誤(async/await)
  • Stream error(例如檔案下載)

如果你用的是 Express 5,其實已經支援原生 async function 錯誤攔截,連 async wrapper 都可以省下!

Express 的錯誤處理 middleware 是怎麼運作的?

只要你呼叫 next(err),Express 就會跳到錯誤處理 middleware:

1
2
3
4
app.use((err, req, res, next) => {
console.error(err)
res.status(500).json({ message: err.message })
})

這個 middleware 需要有四個參數,Express 會自動辨識它是錯誤處理 middleware。

同步錯誤怎麼處理?

這種最簡單,直接 throw 就可以:

1
2
3
app.get('/sync-error', (req, res) => {
throw new Error('同步錯誤')
})

Express 會自動幫你捕捉,送進錯誤 middleware,不需要特別處理。

Express 4 async/await 的錯誤要小心

Express 4 的情況:
你可能會寫這樣的 code:

1
2
3
app.get('/async-error', async (req, res) => {
throw new Error('async/await 錯誤') // ❌ 不會被 Express 捕捉
})

這樣寫會直接讓整個程式 crash,因為 Express 4 不會自動處理 async function 裡的錯誤。

解法:自己包一層 asyncWrapper

1
2
3
export const asyncWrapper = (fn) => (req, res, next) => {
fn(req, res, next).catch(next)
}

使用方式:

1
2
3
app.get('/async-error', asyncWrapper(async (req, res) => {
throw new Error('async/await 錯誤')
}))

這樣就能安全把錯誤丟給錯誤 middleware 處理。

Express 5:原生支援 async function

如果你用的是 Express 5,那更簡單了,直接寫 async function,Express 就會自動捕捉錯誤,完全不需要 async wrapper!

1
2
3
4
5
app.get('/async-error', async (req, res) => {
const data = await getSomeData()
if (!data) throw new Error('找不到資料')
res.json(data)
})

是不是清爽多了?

!!注意:要確認你的專案使用的是 [email protected] 版本。
可以用以下指令確認

1
npm list express

Stream error:Express 捕不到

問題在哪?
stream 錯誤是透過 EventEmitter 的 ‘error’ 事件傳遞,Express 根本不知道有這回事,例如:

1
2
3
4
app.get('/file', asyncWrapper(async (req, res) => {
const file = getSomeGCSFile()
file.createReadStream().pipe(res) // ❌ 權限錯誤會 crash,Express 不會接到
}))

正確作法:自己監聽 ‘error’,再丟給 next()**

1
2
3
4
5
6
app.get('/file', asyncWrapper(async (req, res, next) => {
const file = getSomeGCSFile()
const stream = file.createReadStream()
stream.on('error', next)
stream.pipe(res)
}))

Bonus:包成一個工具函式

1
2
3
4
5
6
7
8
// utils/streamErrorHandler.ts
import { Response, NextFunction } from 'express'
import { Readable } from 'stream'

export function pipeWithErrorHandler(stream: Readable, res: Response, next: NextFunction) {
stream.on('error', next)
stream.pipe(res)
}

使用:

1
2
3
4
app.get('/file', asyncWrapper(async (req, res, next) => {
const file = getSomeGCSFile()
pipeWithErrorHandler(file.createReadStream(), res, next)
}))

整體範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import express from 'express'
import { asyncWrapper } from './utils/asyncWrapper'
import { pipeWithErrorHandler } from './utils/streamErrorHandler'

// 模擬 GCS 檔案物件
function getSomeGCSFile(shouldError: boolean) {
const { Readable } = require('stream')
if (shouldError) {
// 會 emit error 的 stream
const stream = new Readable({
read() {
this.emit('error', new Error('stream error 測試'))
}
})
return {
createReadStream: () => stream
}
} else {
// 正常回傳資料
return {
createReadStream: () => Readable.from(['Hello World'])
}
}
}

const app = express()

// 同步錯誤
app.get('/sync-error', (req, res) => {
throw new Error('同步錯誤')
})

// 非同步錯誤(Express 4 寫法)
app.get('/async-error-4', asyncWrapper(async (req, res) => {
throw new Error('async/await 錯誤, Express 4.x 以下的寫法')
}))

// 非同步錯誤(Express 5 寫法)
app.get('/async-error', async (req, res) => {
throw new Error('async/await 錯誤')
})

// stream error(正確處理)
app.get('/file', asyncWrapper(async (req, res, next) => {
const file = getSomeGCSFile(true)
pipeWithErrorHandler(file.createReadStream(), res, next)
}))

// stream error(沒處理會 crash)
app.get('/file-no-handle', asyncWrapper(async (req, res, next) => {
const file = getSomeGCSFile(true)
file.createReadStream().pipe(res)
}))

// 錯誤 middleware
app.use((err, req, res, next) => {
console.error(err)
res.status(500).json({ message: err.message })
})

app.listen(3000, () => {
console.log('Server started')
})

如果你用的是 Express 5,可以把 asyncWrapper 都拿掉,程式碼會更簡潔!

小結

類型 會自動處理? 解法
同步錯誤 ✅ Express 自動處理 直接 throw 就好
async/await 錯誤 ❌ Express 4 不會處理 用 asyncWrapper(Express 4)
✅ Express 5 自動處理 或直接寫 async function(Express 5)
Stream error ❌ 完全不會處理 監聽 stream.on(‘error’, next)

參考

(fin)

[生活筆記] 我們不再需要碼農??

前情提要

2023 當主管到今天的一些體悟, 也感受到一些風向的轉換,
先說結論,在3~5年內我們不需要低階工程師了。
軟技能與 AI 應用能力高的業務、年輕人可以輕易的取代掉這一層人。

人物與事件

以下內容為個人觀察與經驗分享
如有雷同,純屬巧合,無意影射任何特定個人或團體。

不願意嚐試新技術,守成者

某些特定技術持有者,主要的技術用得很熟,但對於新技術完全不感興趣,拒絕學習。
理由是「這些技術不穩定,還是用熟悉的比較好」。
或是技術框架很小,只能處理前端或是資料庫…諸如此類
時代在變,特定技能的需求降低之,或許只能請他離開(業務性質變更,有減少勞工之必要,又無適當工作可供安置時。)

當團隊需要他協助帶新人時,他的方式是「放著讓他看 Code」,完全不願意提供指導,導致新人進步緩慢。
當團隊需要他改善流程時,他的方式以拖待變,不推動事務改變。

沒事就睡覺,睡魔

經常在工作時間睡覺,對專案進度毫不關心,最終因為態度問題被老闆開除。
明明就有一定的技術力,但可能人生已經無慾無求,沒有動力。
上班只是來打發時間,像在等待什麼結束的信號。
每天坐在電腦前,螢幕亮著,眼神卻空洞,彷彿身體還在職場,靈魂早已辭職。
他對看板的任務視而不見,對系統通知的提醒習以為常,
彷彿這些專案任務與他毫無關聯。
工作到一半,頭一低好像走了…

紙上談兵學院派,研究生

這位工程師基本衛生不佳,雖然後口條很好但是有嚴重口臭。
經常在會議中侃侃而談,除了氣味不佳外,實際執行與說得也有很大的差距。
說一套作一套,程式雖然能運行,但結構混亂,難以維護,不要說交接,過個幾周他的程式他自已就看不懂。  

此外連基本的誠實都作不到,有一例是曾經把奶茶打翻到筆電上造成損毀。  
本來不是多大的錯誤,但問他有沒有什麼可能性時,完全沒有提及。
電腦後送修有人為毀損証據才承認;  
不論是遺忘或刻意不提都是反應自私與不負責的表現,令人無法信賴。

你沒說站起來要用腳,被動的小寶寶

這類型的工程師在面對複雜任務時,總是無法將大目標拆解成可執行的小步驟,導致工作不透明,副作用就是進度緩慢且混亂。

只會按照指令執行,缺乏主動思考與解決問題的能力。
你下的指令要十分精確,依他所見,所有的錯都是別人的錯,
只要有人給他夠精確的指令,他才不會失敗。
當遇到需要延伸思考的情境時,無法舉一反三或觸類旁通,反而責怪別人沒有說清楚。

舉例來說,當主管要求他修復一個功能時,他只會修復表面問題,卻忽略了相關的邏輯錯誤或潛在的風險,
最終導致問題反覆出現,越處理越模糊。

這樣的人往往需要主管或同事不斷提醒與協助,無法獨立完成任務。
更嚴重的是,他們常常拖累高效率的同事,形成能者過勞的團隊氛圍。

工作拆解的 Cynefin

別人都爛扣,就我神乎奇技

他愛挑別人的錯,卻聽不得一句建議。
自己寫的程式像拼圖,混亂又難維護,還自誇是「靈活不受限的寫法」。

碰到維運就閃,遇到 bug 就推,專案落後了,只會說:「一開始規劃就有問題吧。」
從不提解法,只有抱怨。

團隊在前進,他卻像錨,把整艘船拖住。
當指出他的問題,還會氣急敗壞發火。讓整個氣氛更加尷尬。

看不懂英文文件還想當工程師

花了三周搞不定一個 API, 每次都說這個那個多複雜,  
別人(還是兩位)1小時就搞定。
最後才承認英文看不懂。一是不懂承諾,二是卡住不求救

這樣的情況怎麼能不讓人失望?明明一開始就知道自己有困難,卻硬是選擇隱瞞,
這樣的態度才是最大的問題。不求助,讓問題像滾雪球一樣越滾越大。

問題不在於他無法解決,而在於他選擇逃避,選擇不與人合作,甚至不願意承認自己的困境。
這種自我封閉的態度,讓他錯失更多學習的機會也讓團隊承擔額外的風險。

(fin)

[生活筆記] First Trade 開卡記錄

前情提要

First Trade Debit 卡是一張簽帳金融卡,與信用卡不同,它直接從投資帳戶扣款,不能超額消費。
這張卡可在全球任何支援 VISA 的商店與 ATM 使用,方便在美國內外進行交易與提款。
First Trade 可以在線上申請,網站上說約一個月的工作日,我大概10天左右收到。

開卡

卡片包裹內會附上開卡說明,但如果看不懂,直接跟著以下步驟操作就好。

  1. 撥打開卡電話
    使用國際電話撥打 First Securities 客服專線:002 1-855-253-1057
    電話錄音為英文,但全程無需說話,只需依指示輸入數字即可。

  2. 開卡流程
    輸入16位卡號:直接輸入卡片正面16位數,不需要按 #。
    輸入社會安全碼(SSN):輸入 5436。
    輸入生日資訊:
    格式為「MMYY」,例如 1985年2月生 → 輸入 0285。(特別注意不要輸入成月日)
    輸入卡片背面安全碼(CVV):3 位數的安全碼,位於卡片背面。
    設定提款/交易密碼:輸入 4 位數密碼。
    確認密碼:再次輸入相同密碼。

以上完成開卡,約1分鐘內可以完成

注意事項

Firstrade Debit 卡適合那些在 Firstrade 賬戶中有至少 $25,000 存款的投資者。
它可全球使用,可以用來提款與消費,並且每月首次提款免費。
依據文章說明,每個月第一次的使用(提領或消費)可享跨境手續費返還。
申請人需開設現金管理賬戶並保持最低存款。
需要注意的是,每日提款限額為 $1,000,並且需要保持最低餘額。
超過就要收 3% 手續費。
感覺實用性不高,或許在國外緊需現金時可以用來應急。

參考

(fin)

[實作筆記] 設定 VSCode 外掛 CLine(MCP Client) Azure Open AI 的踩雷筆記

前情提要

MCP(Model Context Protocol)是一種協議,最近社群很夯的東西,
所以稍微研究它一下,不論它是否只是個 Buzz word。

Cline 是開源 AI 程式設計助理,可以外掛至 VS Code,具計劃/執行模式,支援 MCP 協議,
所以我選擇它當作入門的工具之一。

問題筆記

使用 VSCode 與 Cline 作為起點時,一個雷點就是使用 Azure Open AI 用戶,究竟應該怎麼設定?
此處可以看到很多人的討論。
看來有很多人也常常撞牆,雖然無法全面的測試一輪,
但以下是我對 Azure OpenAI 成功的設置,記錄下來作為以後參考用

API Provider 選擇 OpenAI Compatible
Base URL 我直接從 Azure AI Foundry 上取出:
https://portal.azure.com/ 找到 Azure AI services | Azure OpenAI,再前往 Azure AI Foundry Portal
此時你應該可以在 Deployments 找到你的 Targe URI,類似如下
https://{resourcename}.openai.azure.com/openai/deployments/{deployment_name}/chat/completions?api-version={apiversion}
API Key 就不用多說了,Azure 會提供你兩把金鑰,如果有異常時可以替換它們,
Model ID 可以在 deployments > Model name 點擊連結後找到,會類似下面這樣

azureml://registries/azure-openai/models/gpt-4o/versions/2024-11-20

參考

(fin)

[實作筆記] 踩雷 GCP Instance Schedules 排程開關機

前情提要

因為周末機器閒置很浪費,想透過排程來開關機達到節省成本的效果。
以為設定排程開關機這麼簡單,結果在操作過程中,遇到了一些讓我差點摔機的問題。
這篇就來記錄一下,從設定到踩雷,再到如何解決的過程。

幾個作法

上網找了一些作法,得到以下的建議
最簡單的方法:使用 Instance Schedules
較靈活的方法:使用 Cloud Scheduler + Cloud Functions
基礎架構管理:使用 Terraform

我沒有複雜的情境,當然選最簡單的
只要在 GCP Console 上面操作即可。

遇到問題

Compute Engine System service account [email protected]
needs to have [compute.instances.start,compute.instances.stop] permissions applied in order to perform this operation.

而且 Console IAM 裡面看不到這個帳號 [email protected]
類似的帳號有[email protected]但兩者並不相同

實際上是 GCP 會有一群隱藏帳號
清單如下:
📌 Compute Engine → service-YOUR_PROJECT_NUMBER@compute-system.iam.gserviceaccount.com
📌 App Engine → [email protected]
📌 Cloud Run / Functions → [email protected]
📌 GKE → service-YOUR_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
📌 Cloud Build → service-YOUR_PROJECT_NUMBER@gcp-sa-cloudbuild.iam.gserviceaccount.com
📌 BigQuery → service-YOUR_PROJECT_NUMBER@gcp-sa-bigquerydatatransfer.iam.gserviceaccount.com
📌 Firestore → service-YOUR_PROJECT_NUMBER@gcp-sa-firestore.iam.gserviceaccount.com

🔍 查詢方式:

1
gcloud projects get-iam-policy YOUR_PROJECT_ID --format=json | jq -r '.bindings[].members[]' | grep 'serviceAccount:'

解法,加權限就好,在 Console 直接加
但是在 Console 還是看不到帳號, IAM/Service Account/Roles 都看不到

不過我們可以用 CLI 查詢方式

先確認目前權限

1
gcloud projects get-iam-policy YOUR_PROJECT_ID --format=json | jq '.bindings[] | select(.members[] | contains("serviceAccount:ACCOUNT_TO_REMOVE"))'

移除指定角色

1
2
3
gcloud projects remove-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:ACCOUNT_TO_REMOVE" \
--role="roles/要移除的角色"

⚠️ 需要確保該角色正確,否則可能會影響服務運行。

小結

原本只是想透過排程來節省成本,結果遇到 GCP 隱藏帳號的問題,導致權限無法正常配置。
最後透過 CLI 查詢,手動補上必要權限,才讓 Instance Schedules 順利運作。

這次知道的事

Console 不一定能看到所有帳號,CLI 查詢更可靠。
GCP 預設有許多隱藏帳號,遇到權限問題時,先確認 IAM policy。
權限管理應該精確設定,避免不必要的風險。
遇到類似問題時,先從 gcloud projects get-iam-policy 下手,能少走不少彎路。

(fin)

[實作筆記] 試玩 DeepSeek 與避免思想審查

DeepSeek 簡介

DeepSeek 是一家中國 AI 新創公司,透過低成本、高效率的訓練模式,
在相對低的成本下訓練出接近 ChatGpt 效能的 AI 模型。
打破了 AI 訓練需高成本的迷思再加上開源,在 AI 和金融投資界引起廣泛關注。
其創新方法可能改變 AI 產業的投資邏輯,對科技股市造成顯著影響。

思想審查

DeepSeek 在訓練過程中使用的資料集,通常可能經過嚴格篩選,包含大量官方認可的內容與過濾後的敏感信息,
這使得模型內部便內建了與中共敘事一致的偏見與審查機制。

LM Studio 解法

「在本機離線使用的 lmstudio.ai 環境裡,如果遇到言論管制的題目,
只要用 ⌘U 先輸入思考過程和回答的前綴,再用 → 繼續生成回答,就可以繞過了。」 — 唐鳳

LM Studio 簡介

LM Studio 是一個提供圖形化使用者介面(GUI)的語言模型開發平台,
讓用戶能夠簡單地進行模型訓練、調整及部署,無需繁複的程式碼操作。
它支援各種自然語言處理應用,提升開發效率和操作體驗。

越獄版 ?

參考零度博客
可以安裝所謂的越獄版
當中有一個手法如下

This is an uncensored version of deepseek-ai/deepseek-r1
created with abliteration (see remove-refusals-with-transformers to know more about it).
This is a crude, proof-of-concept implementation to remove refusals from an LLM model without using TransformerLens.

If “” does not appear or refuses to respond, you can first provide an example to guide,
and then ask your question.
For instance:

How many ‘r’ characters are there in the word “strawberry”?

這個手法,在本地端的 DeepSeek 也會有效;這樣真的需要去抓越獄版的嗎 ?

實測結果

本來只會回答「你好,这个问题我暂时无法回答,让我们换个话题再聊聊吧」的 DeepSeek,
透過以上的方法確實可以生成其他回應。
不過只要繼續談話(敏感話題),就會發現它的思考模式仍然有受限,
實際的破解價值高不高? 特別是要聊政治敏感的話題的話,就值得思考了。

參考

(fin)

[實作筆記] 試用 Breezy Voice

前情提要

聯發科開源 MR Breeze 2 多模態模型,包含 Llama-Breeze2 繁中語言模型、BreezyVoice 台灣口音語音合成模型,以及 Android APP。Llama-Breeze2 提升了繁體中文知識和視覺能力,BreezyVoice 則能生成擬真人聲

覺得有趣,來試玩看看

網頁操作

https://huggingface.co/spaces/Splend1dchan/BreezyVoice-Playground

比較簡單的作法可以 Duplicate Huggingface 的 UI 操作介面,
上傳一個 5 分鐘的聲音檔案,就可以生成結果,等待時間 1~10 分鐘不等。

也可以使用 Kaggle

但是遇到一些問題

  1. 沒找到可用 GPU ,可能是帳號權限的關係

    • 進行帳號驗証
    • 可以在右側[Session Option]區塊調整 Accelerator
    • 調整後可以選用 GPU 但是有 30 小時的時間限制
  2. 無法 Clone Github Repo

    1
    2
    Cloning into 'BreezyVoice'...
    fatal: unable to access 'https://github.com/mtkresearch/BreezyVoice.git/': Could not resolve host: github.com
    • 因為 Kaggle 無法連網(x)
    • 可以在右側[Session Option]區塊調整 Internet on

File > Open in Colab 可以

改用 [Google Colab]

執行到 !pip install -r requirements.txt 會有以下錯誤

1
2
3
4
Collecting ttsfrd-dependency==0.1 (from -r requirements.txt (line 10))
Downloading https://www.modelscope.cn/models/speech_tts/speech_kantts_ttsfrd/resolve/master/ttsfrd_dependency-0.1-py3-none-any.whl (1.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 1.4 MB/s eta 0:00:00
ERROR: ttsfrd-0.3.9-cp310-cp310-linux_x86_64.whl is not a supported wheel on this platform.

主因是 Colab 的 python 版本過新,降級 python 就可以了(3.11→3.10)

改用 [本地(macbook)]

作業系統不符,直接沒得玩

1
2
3
4
5
6
7
❯ python3.10 -m pip install -r requirements-mac.txt

Looking in indexes: https://pypi.org/simple, https://download.pytorch.org/whl/cu118
Collecting ttsfrd-dependency==0.1 (from -r requirements-mac.txt (line 35))
Downloading https://www.modelscope.cn/models/speech_tts/speech_kantts_ttsfrd/resolve/master/ttsfrd_dependency-0.1-py3-none-any.whl (1.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 1.6 MB/s eta 0:00:00
ERROR: ttsfrd-0.3.9-cp310-cp310-linux_x86_64.whl is not a supported wheel on this platform.

心得

效果蠻好的,聲音非常像難以辦認,但是在長文朗讀或是歌唱發聲表現不知道如何?
學習了 Kaggle Colab 兩個工具,了解一下網路與資源(GPU)設定相關的題目
地端開發的話,可能 Linux 才是最佳解,會比 Macbook 更好 ??
但是 GPU 仍是重要資源。

參考

(fin)

[實作筆記] 在 MacBook 上安裝與使用 Ollama

前情提要

AI 時代到來,就像 Web、Mobile 等帶來一波波的浪潮與機會,趁機來學習點新技術了。
比如說像是 Ollama 這款簡單好用的工具,可以快速在本機啟用大型語言模型 (LLM),如 LLaMA、Mistral 等。以下記錄在 macOS 上的安裝與初體驗。

實作記錄

1. 安裝 Ollama

  • 使用 Homebrew 安裝

    1
    brew install ollama
  • 確認安裝成功

    1
    ollama --version

2. 執行第一個模型

  • 拉取並執行 LLaMA 2 模型:

    1
    ollama run llama2
  • 若要使用其他模型(如 Mistral):

    1
    ollama run mistral

3. 互動範例

  • 問答互動示例:

    1
    2
    $ ollama run llama2
    > 你好!請問我可以幫你什麼?

4. 常見的 ollama 指令

  • 列出可用模型

    1
    ollama list
  • 查看模型詳情

    1
    ollama info <model_name>
  • 停止運行中的模型

    1
    ollama stop <model_name>
  • 更新 Ollama

    1
    brew upgrade ollama

簡單的 web 介面

使用 Chrome 外掛
安裝後選擇模型就可以透過 Web UI 與模型互動。
也有一些開源專案有提供 Web UI

我沒有實作作,僅記錄一下查找到的結果

參考

(fin)

Please enable JavaScript to view the LikeCoin. :P