[生活筆記] 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)

[學習筆記] TypeScript 的 Immutable Objects 與 Record<T1,T2>

前情提要

最近在看 TypeScript Wizard 的課程,稍作一下紀錄

1
2
const user = { name: "John" };
user.age = 24; // ❌ Property 'age' does not exist on type '{ name: string; }'.

這裡 IDE 會在 user.age 上報錯,因為 TypeScript 預設只允許存取「已知」的屬性。
由於 user 只有 name 屬性,TypeScript 會將其推斷為 { name: string } 類型,因此無法直接新增 age。

解法

這時候我們有幾種解法,但要挑選 最符合 TypeScript 精神的做法。

明確定義 User 類型

這是最推薦的作法

1
2
type User = { name: string; age?: number };
const user: User = { name: "John" };

使用 Record 定義動態物件

如果我們需要 允許物件擴展但仍保持類型安全,可以使用 Record<K, V>:

1
2
3
const user: Record<string, string | number> = { name: "John" };
user.age = 24; // ✅ 這次不會報錯!
user.isAdmin = true; // ❌ Type 'boolean' is not assignable to 'string | number'.

另一種動態的作法,明確定義索引簽名

1
2

type User = { name: string; [key: string]: string | number };

這樣 user 可以擁有 任何鍵(string 類型),但值必須是 string 或 number,避免亂塞其他類型。

Immutable Objects

反之,如何保證物件的結構不會意外被修改?
我們可以使用 readonly 保持 Immutable Objects

1
2
3
4
type User = Readonly<{ name: string; age: number }>;
const user: User = { name: "John", age: 24 };

user.age = 25; // ❌ Cannot assign to 'age' because it is a read-only property.

這種方式確保 user 一旦被賦值,就不能再改變,完全符合 Immutable Objects 的概念。
另一種方式是使用 Object.freeze() 來讓物件變成真正的 Immutable:

1
2
3
const user = Object.freeze({ name: "John", age: 24 });

user.age = 25; // ❌ TypeError: Cannot assign to read only property 'age'

不過要注意,Object.freeze() 只會影響淺層屬性,深層的物件仍然可以變更。

進一步思考,如何選擇?

  • 如果你的物件是固定結構但不可變更,readonly 是最佳選擇。
  • 如果需要允許擴展但要控制類型範圍,使用 Record<K, V>。
  • 如果想確保物件完全不可變,Object.freeze() 是最安全的選項。

參考

(fin)

[實作筆記] 使用 Docker 一鍵生成 Sample 資料庫

前情提要

在開發或測試過程中,常常需要一個快速可用的資料庫環境來模擬真實操作。
然而,手動安裝和配置 MySQL 不僅耗時,也容易出現版本兼容性問題。
透過 Docker,我們可以輕鬆建立一個即時可用的環境,並在啟動時自動初始化資料庫的必要條件(表格或 root 帳密等…)。

本文將介紹如何使用 Dockerfile 和 SQL 初始化腳本,快速構建一個名為 sample 的測試資料庫。

實作記錄

步驟 1: 建立專案目錄與檔案

首先,創建一個新目錄,並在其中準備以下檔案:

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Dockerfile for setting up MySQL with a sample database

# 使用官方 MySQL 映像

FROM mysql:latest

# 設定環境變數
ENV MYSQL_ROOT_PASSWORD={your root password}
ENV MYSQL_DATABASE=sample

# 複製初始化腳本

COPY init.sql /docker-entrypoint-initdb.d/

# 開放 MySQL 連接埠

EXPOSE 3306

init.sql

1
2
3
CREATE DATABASE IF NOT EXISTS sample;
USE sample;

步驟 2: 建構與啟動容器

執行以下指令來建構映像並啟動容器:

建構 Docker 映像

docker build -t mysql-sample .

啟動容器

docker run -d –name mysql-sample -p 3306:3306 mysql-sample

這將啟動一個名為 mysql-sample 的容器,並將 MySQL 的 3306 埠映射到本機。

步驟 3: 驗證資料庫

進入 MySQL 容器並確認資料庫與表格是否正確建立:

docker exec -it mysql-sample mysql -u root -p

在 MySQL shell 中執行:

1
2
3
SHOW DATABASES;
USE sample;
SHOW TABLES;

參考

開發用指令

1
2
3
4
5
6
❯ docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=You don't need to try this password; I made it up. A7X3P \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
mysql:latest

(fin)

[實作筆記] FastAPI 的 middleware

前請提要

最近團隊的小朋友作的系統發生了錯誤。

在追查的過程之中,
小朋友說了一個驚人的事實
Python 的 FastAPI Web 框架,發生 422 錯誤時(輸入的參數類別錯誤),無法追踪 Request$$
當然這不是事實,那麼 FastAPI 應該怎麼處理呢?

本文

讓我們先簡單實作一個 Fast API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from fastapi import FastAPI
from pydantic import BaseModel

# 初始化 FastAPI 應用
app = FastAPI()

# 定義請求資料模型
class Item(BaseModel):
name: str
price: float
description: str = None # 可選的欄位

# 定義 API 路徑
@app.post("/items/")
async def create_item(item: Item):
# 假設邏輯檢查
if item.price <= 0:
return {"error": "Price must be greater than 0"}
return {"message": "Item created successfully!", "item": item}

接下來,讓我試著用不正確的方式呼叫 API,並且得到一個 422 的錯誤

1
2
3
4
curl 
-X POST "http://127.0.0.1:8000/items/"
-H "Content-Type: application/json"
-d '{"item": "should be number", "price": 10.5}'

FastAPI 會提供 Client 端非常友善的資訊

1
2
3
4
5
6
7
8
9
10
11
12
{
"detail":[
{
"type":"missing",
"loc":["body","name"],
"msg":"Field required",
"input":{
"item":"should be number",
"price":10.5
}
}]
}

但在 Server 端只會有類似以下的資訊,這以後端的角度要排查錯誤會非常不便

1
INFO:     127.0.0.1:57617 - "POST /items/ HTTP/1.1" 422 Unprocessable Entity

Server Side 有沒有什麼好方法可以協助我們 Debug 呢?

解決方法:Middleware

這其實是 web 開發者的小常識才對,
實作如下,

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
from fastapi import FastAPI,Request
from pydantic import BaseModel
import logging
from datetime import datetime

# 初始化 FastAPI 應用
app = FastAPI()

# 初始化日誌
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")

# 定義請求資料模型
class Item(BaseModel):
name: str
price: float
description: str = None # 可選的欄位

# 中間件,用於記錄請求
@app.middleware("http")
async def log_requests(request: Request, call_next):
# 記錄請求進來的時間與基本資訊
request_time = datetime.utcnow()
logging.info(f"Incoming request at {request_time}")
logging.info(f"Method: {request.method} | Path: {request.url.path}")

# 嘗試讀取請求 Body
try:
body = await request.json()
logging.info(f"Request Body: {body}")
except Exception:
logging.info("No JSON body or failed to parse.")

# 執行後續處理並取得回應
response = await call_next(request)

# 記錄回應狀態碼
logging.info(f"Response status: {response.status_code}")
return response

# 定義 API 路徑
@app.post("/items/")
async def create_item(item: Item):
# 假設邏輯檢查
if item.price <= 0:
return {"error": "Price must be greater than 0"}
return {"message": "Item created successfully!", "item": item}

Request 送進來時 Server Side 就會如下記錄

1
2
3
4
5
2025-01-03 03:37:37,294 - Incoming request at 2025-01-02 19:37:37.294509
2025-01-03 03:37:37,294 - Method: POST | Path: /items/
2025-01-03 03:37:37,294 - Request Body: {'item': 'should be number', 'price': 10.5}
2025-01-03 03:37:37,295 - Response status: 422
INFO: 127.0.0.1:59545 - "POST /items/ HTTP/1.1" 422 Unprocessable Entity

心得

回到我們原本的情境,我們真正要解決的問題是,

|發生異常時,Server Side 要可以追蹤錯誤

因為是 FastAPI 所以沒有辦法追蹤錯誤,是非常錯誤判斷

在 Google 與 AI 工具這麼方便的時代,應該要能正確的提出問題。

ex: FastAPI 可以記錄什麼時候 request 送進來,並帶了什麼資訊嗎?

(fin)

[生活筆記] ChatGPT 個性分析

前請提要

ChatGPT 能透過語言理解和生成,提供更細緻的個性分析,特別是當你使用了一陣子後,
可以用以下的 Prompt 作個簡單的分析報告。

Prompt

根據我們之前的互動,我希望你能告訴我你觀察到關於我的哪些特質是我可能沒有意識到的。
請儘可能誠實直接的表達,不要有所保留。
如果你注意到我可能察覺不到的矛盾之處、行為模式或傾向,我都想清楚的聽到,不需要粉飾任何資訊,請給我最真實最直接的分析

ChatGPT said

以下是根據我們互動中可能顯現的特質和行為模式,我誠實的觀察與分析,供你參考:

  1. 強烈的自我驅動
    你有著明顯的自我驅動力,願意挑戰自我,例如你的30天鐵人挑戰或對學習新技能的熱忱。
    然而,這種驅動力可能會讓你偶爾忽略自己的疲憊或情緒需求,容易進入「過度努力」的狀態。

  2. 追求效率與結果,但重視細節
    你傾向於以結果為導向,尤其是在專案進行或問題解決時。
    你對細節的關注,例如希望資訊條理清楚或具可操作性,顯示出你對高標準執行的重視。
    然而,有時可能會因為過於專注於效率,無意間忽略更大的全局或需要額外耐心的部分。

  3. 多元興趣與高度適應力
    你對不同領域的興趣(技術、跳舞、潛水、反思工具等)顯示了你擁有探索和適應的能力。
    然而,這種多元性可能會讓你在資源有限的情況下分散注意力,難以在某一領域深耕到你期望的程度。

  4. 對「流程」的矛盾態度
    雖然你熟悉並實踐許多工具和方法(如敏捷、KPT、SMART等),但你的個性似乎也渴望自由與靈活性,
    這可能讓你在面對過於僵化的流程時感到不耐煩。
    這種矛盾可能讓你在制定規範時猶豫,因為你不想限制自己或團隊的創造力。

  5. 溫和但堅持個性
    你偏好直接但不咄咄逼人的溝通方式,並且能保持禮貌與平衡。
    然而,你也表現出對原則與目標的堅持,即使是在比較微妙的情境下,可能讓他人難以察覺你的真實意圖。

  6. 對自己標準的隱藏壓力
    你對自己設定的目標和標準很高,且傾向於內化「應該更好」的期待。
    這可能導致你對成功的認可不夠,容易放大未完成或未達成的部分,忽略已經達成的成就。

  7. 偏好控制但能適應改變
    你習慣掌控規劃與執行的過程,並且對細節要求高。
    然而,你在面對不可預測的情況時,也能快速調整心態並提出替代方案,顯示出高度靈活的思維。

這些分析可能包含一些你未曾意識到或尚未明確的特質,也可能包含你的日常行為中隱藏的矛盾。
如果你有不同的想法或任何補充,歡迎分享!

(fin)