寫作排版技巧:中英文文案的常見錯誤
我曾經看到一封 email ,內容寫得真爛,後來發現是我自己寫的,標點符號都亂標,XD 。最近又發現原來我寫中英文時,也很隨興,常事後看起來不對勁,但就是看不出所以然來。
後來我在脆上面,看到有人在推寫作時,應當要注意中、英文排版,建議參考「中文文案排版指北」,內容簡單,淺顯易懂,我也推薦大家發漏。
我曾經看到一封 email ,內容寫得真爛,後來發現是我自己寫的,標點符號都亂標,XD 。最近又發現原來我寫中英文時,也很隨興,常事後看起來不對勁,但就是看不出所以然來。
後來我在脆上面,看到有人在推寫作時,應當要注意中、英文排版,建議參考「中文文案排版指北」,內容簡單,淺顯易懂,我也推薦大家發漏。
原本我在公司寫好的 Spring Boot 3.1.5+OpenAPI 3.1+selenium 4.21 都很正常,直到 Spring AI 1.0 橫空出世,我想 Spring Boot 也應該升級到Spring boot 3.5.0 ,才能用上 Spring AI 1.0 MCP 功能,也才能接上未來的 n8n。
但很可惜還沒來得及加上 Spring AI 1.0 外掛,就出現執行階段錯誤
02:29:19,730 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4218d6a3 - ch.qos.logback.classic.util.DefaultJoranConfigurator.configure() call lasted 70 milliseconds. ExecutionStatus=DO_NOT_INVOKE_NEXT_IF_ANY
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
02:29:19,942 |-ERROR in ch.qos.logback.core.joran.spi.SaxEventInterpretationContext@663411de - No 'converterClass' attribute in <conversionRule>
Logging system failed to initialize using configuration from 'null'
java.lang.NoSuchMethodError: 'void ch.qos.logback.core.model.processor.ModelInterpretationContext.setConfiguratorSupplier(java.util.function.Supplier)'
at org.springframework.boot.logging.logback.SpringBootJoranConfigurator.buildModelInterpretationContext(SpringBootJoranConfigurator.java:117)
踩坑好久好久,後來才發現原本 selenium 使用 webdrivermanager.jar (5.8.0) 內建的 logback,與 spring-boot 3.5.0 內建的 logback 函式庫相衝突,需要升級到最新的 webdrivermanager 6.1.0 才可以匹配,且我有額外排除 webdrivermanager 6.1.0 內建的 logback。
我的設定檔案是 build.gradle,非 maven,重點如下
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.0'
id 'io.spring.dependency-management' version '1.1.7'
...
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:3.5.0")
implementation 'org.seleniumhq.selenium:selenium-java:4.33.0'
implementation("io.github.bonigarcia:webdrivermanager:6.1.0"){
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
...
}
當然 src/main/resources 目錄也要新增 logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-4level] %msg%n</pattern>
</encoder>
</appender>
<logger name="io.github.bonigarcia" level="DEBUG" />
<logger name="io" level="WARN" />
<logger name="org" level="WARN" />
<logger name="com" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
這樣就能成功從 Spring Boot 3.1.5 升級到 Spring Boot 3.5.0 了
json字串有些特殊字元,需要跳脫後才能正常使用。因此有必要在n8n加上code節點寫javascript 跳脫。
const chars = {
"\"": "\\\"",
"\\": "\\\\",
"\/": "\\/",
"\u0000": "\\u0000",
"\u0001": "\\u0001",
"\u0002": "\\u0002",
"\u0003": "\\u0003",
"\u0004": "\\u0004",
"\u0005": "\\u0005",
"\u0006": "\\u0006",
"\u0007": "\\u0007",
"\u0008": "\\u0008",
"\u0009": "\\u0009",
"\u000A": "\\u000A",
"\u000B": "\\u000B",
"\u000C": "\\u000C",
"\u000D": "\\u000D",
"\u000E": "\\u000E",
"\u000F": "\\u000F",
"\u0010": "\\u0010",
"\u0011": "\\u0011",
"\u0012": "\\u0012",
"\u0013": "\\u0013",
"\u0014": "\\u0014",
"\u0015": "\\u0015",
"\u0016": "\\u0016",
"\u0017": "\\u0017",
"\u0018": "\\u0018",
"\u0019": "\\u0019",
"\u001A": "\\u001A",
"\u001B": "\\u001B",
"\u001C": "\\u001C",
"\u001D": "\\u001D",
"\u001E": "\\u001E",
"\u001F": "\\u001F",
"\u007F": "\\u007F",
"\u0080": "\\u0080",
"\u0081": "\\u0081",
"\u0082": "\\u0082",
"\u0083": "\\u0083",
"\u0084": "\\u0084",
"\u0085": "\\u0085",
"\u0086": "\\u0086",
"\u0087": "\\u0087",
"\u0088": "\\u0088",
"\u0089": "\\u0089",
"\u008A": "\\u008A",
"\u008B": "\\u008B",
"\u008C": "\\u008C",
"\u008D": "\\u008D",
"\u008E": "\\u008E",
"\u008F": "\\u008F",
"\u0090": "\\u0090",
"\u0091": "\\u0091",
"\u0092": "\\u0092",
"\u0093": "\\u0093",
"\u0094": "\\u0094",
"\u0095": "\\u0095",
"\u0096": "\\u0096",
"\u0097": "\\u0097",
"\u0098": "\\u0098",
"\u0099": "\\u0099",
"\u009A": "\\u009A",
"\u009B": "\\u009B",
"\u009C": "\\u009C",
"\u009D": "\\u009D",
"\u009E": "\\u009E",
"\u009F": "\\u009F"
};
$json.output = $input.first().json.output.replace(/[\"\\\/\u0000-\u001F\u007F\u0080-\u009F]/g, match=>chars[match]);
return $input.all();
現在主流文件辨識,應該都交由vision功能的AI模型處裡,辨識度高;若不想花錢使用AI,可以用apache tika頂著用。
docker 安裝 apache tika
docker run -d -p 9998:9998 --name tika-server-ocr apache/tika:latest-full
# 目前是3.1.0
安裝完畢,進入容器,安裝中文語言套件
docker exec -u root -it tika-server-ocr bash
###
apt update
apt-get install tesseract-ocr-chi-sim tesseract-ocr-chi-tra
###
測試
# Linux
# 中文圖檔 test.png
curl -T test.png http://127.0.0.1:9998/tika --header "X-Tika-OCRLanguage: eng+chi_tra+chi_sim"
N8N(nodemation)設定
前一個節點要把檔案準備好,再新增以下節點,丟給tika處理,回傳設定為text
安裝環境:
參考官方文件:Guacamole Docker
⚠️ 注意事項:以下步驟請務必注意 IP、Port、以及容器名稱,請記得調整。
docker run --restart always --name guacd -d -p 4822:4822 guacamole/guacd:1.6.0-RC1
docker run -d --restart=always --name postgres-17 -p 5432:5432 \
-e POSTGRES_USER=root \
-e POSTGRES_PASSWORD=密碼 \
-v postgres-17-data:/var/lib/postgresql/data postgres:17.4-bookworm
進入容器:
docker exec -it postgres-17 bash
進入 PostgreSQL 服務器:
psql -U root -p 5432 -h localhost -W
建立資料庫:
create database guacamole;
docker run --rm guacamole/guacamole:1.6.0-RC1 /opt/guacamole/bin/initdb.sh --postgresql > initdb.sql
apt-get install -y postgresql-client
psql -U root -p 5432 -h <容器IP> -W -d guacamole < initdb.sql
docker run --restart always --name guacamole \
-e GUACD_HOSTNAME=<guacd ip> \
-e GUACD_PORT=4822 \
-e POSTGRESQL_HOSTNAME=<postgres ip> \
-e POSTGRESQL_PORT=5432 \
-e POSTGRESQL_DATABASE=guacamole \
-e POSTGRESQL_USERNAME=root \
-e POSTGRESQL_PASSWORD=密碼 \
-d -p 8080:8080 guacamole/guacamole:1.6.0-RC1
location /guacamole/ {
proxy_pass http://ip:8081;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
client_max_body_size 1g;
#proxy_cookie_path /guacamole/ /new-path/; 若位置不一樣
access_log off;
}
才剛安裝nginx 反向代理程式容器,沒多久就忘了密碼 XD,我安裝時不綁定外部資料庫,內建的是sqlite。
要救回來原理:先進容器將所有使用者設定刪除,重開容器後,系統會以為初始化,此時就可以用預設帳密登入,然後再進容器把刪除的狀態回原,這樣就可以重設原使用者的密碼囉。
步驟如下:
docker exec -it 容器名稱 bash
apt update && apt install sqlite3 -y
sqlite3 /data/database.sqlite
UPDATE user SET is_deleted=1;
然後重開容器,接下來就可以用預設的帳號登入
帳號:admin@example.com
密碼:changeme
接下來再進一次容器,將剛剛設定刪除的管理者還原
這樣用預設帳號登入重新查看,原本管理者的帳號就出現了,改掉其密碼,這樣就救回來了
公司大陸廠縮編但還剩20多人,原本的fortinet防火牆突然壞了,現主時那裏也沒寬頻上網分享器來替換防火牆;不過內部mail server因不透過防火牆,所以運行正常,server有兩片網卡,一個對外、一個對內,作業系統CentOS 6,算是老伺服器。
我必須在短時間內讓大家上網,也必須讓vpn server透過mail server,重新搞定site to site vpn,才能讓同事從大陸使用台北ERP等伺服器。
講這麼多,就是把NAT搞定,CentOS 6還在用老式的iptables,好險我有印象,google爬一爬,趕緊從台北遠端連到大陸任一台主機再,連到mail server進行設定並且測試。
# eth1網卡對外
# eth0網卡對內
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
iptables -P OUTPUT ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -A INPUT -i eth0 -j ACCEPT
iptables -A INPUT -j DROP
iptables -A FORWARD -i eth0 -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# 把原本的路由加回去
route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.1.1
我這種老派工程師,一直以來都用apache httpd 做反向代理,也沒用docker安裝,直到為了n8n能用mcp,果斷改用docker 安裝 nginx proxy manager。
nginx proxy manager 安裝方式請參考官方文件,安裝完畢反向對應到本地端的n8n(docker),此時需要額外設定,避開gzip壓縮問題,才能順利搭上n8n上的mcp server。
# disable gzip and proxy buffering for both /mcp/ and /mcp-test/
location ~* ^/(?:mcp|mcp-test)/ {
gzip off;
proxy_buffering off;
chunked_transfer_encoding off;
# prevent upstream compression
proxy_set_header Connection "";
proxy_set_header Accept-Encoding "";
# re‑declare NPM’s proxy headers using built‑in variables
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# send to your upstream based on NPM’s variables
proxy_pass $forward_scheme://$server:$port;
}
ollama Ubuntu 安裝
curl -fsSL https://ollama.com/install.sh | sh
ollama 好用模型以後盡量記錄在此,顯卡記憶體32GB
# 翻譯類
PetrosStav/gemma3-tools:27b
TeeZee/gemma-2-9b-it-abliterated
mistral-small3.1
# 工具類
PetrosStav/gemma3-tools:27b
mistral-small3.1
# 圖片辨識
mistral-small3.1
PVE 8 加上GPU Passthrough(顯卡通透),可能是PVE、5090、或主機板太新,一直卡關,因此我有必要紀錄一下如何攻克。
話說我前幾天終於說服公司購買好一點的顯示卡,因為先前提早研究,知道顯卡很吃PCI-E 16x,但那是什麼鬼我都不懂,於是快馬加鞭衝去原價屋,找專業店家買主機,服務人員聽說要買頂規的5090,很熱情地自動展開相關配置,這些專業建議不額外收費。
主機板:Z890 Aorus master
CPU:Intel Core ultra 9 285K
記憶體:256GB
M.2.: 1T
顯卡:ASUS ROG ASTRAL RTX 5090 32G 水冷
power:1300 瓦
原價屋組裝好,我收到貨之後,想說主機這麼好,應該要安裝pve多工使用。
爬文得知兩個重點:
首先我安裝pve 8.4.1,且照著官網建議的設定,但一直不成功,VM開不起來;後來想說是不是pve版本太新,因此改用8.3.1也不行,再改成8.2.2也不行。我總共參考以下文章,也測試了N輪,都快放棄了 XD
文章都說只要開通vfio-pci以及iommu就可以了,我照做也很順利。
執行 lspci -nnk,可以看出顯卡已開通 vfio-pci
執行 dmesg | grep -e DMAR -e IOMMU ,可看到IOMMU enabled
可惜無論如何努力,vm一直無法出現開機畫面,一看就知道通透失敗。
甚至我都扒出有些設定新版pve 8已棄用,也修改 /etc/default/grup ,加上新的設定 initcall_blacklist=sysfb_init,做完要執行 update-grub,但一樣GG,。
不死心,失敗了N次,我無意間在這裡發現新大陸,裡面提到一個設定disable_denylist=1要加到vfio.conf,雖然最後還是失敗XD
很神奇,當時突然如到電影盜夢空間(全面啟動)情節,彷彿有人偷偷修改我的記憶,不自覺自己無意識下了一個指令 modinfo -p vfio-pci,系統居然多嘴跟我說還有其他設定要加上企。
最後,我把系統建議的這些設定都加到 /etc/modprobe.d/vfio.conf 裡面( 加完記得要 update-initramfs -u -k all )。
disable_vga=1 disable_denylist=1 disable_idle_d3=1 enable_sriov=1
再重開vm就成功進入開機畫面了,太棒了!
vm 安裝ubuntu 24.04,還要加裝 nvidia 驅動。
vm如何安裝nvidia驅動,我參考了以下這兩篇
https://docs.nvidia.com/datacenter/tesla/driver-installation-guide/index.html#ubuntu-installation
安裝完畢,記得重開機,pve主機要重開,不能只重開vm。
等pve主機,與其vm重開後, 進 vm 執行 nvidia-smi,看到心愛的 5090 就安心了。
再下指令讓 Persistence-M 變成On
sudo nvidia-smi -pm 1
接下來安裝docker,我參考張騰元文章 。
docker安裝完畢,咱門還需要讓docker也能使用 nvidia ,請參考 https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html 。
最後啟動ollama docker
docker run -d –gpus=all -v ollama:/root/.ollama -p 11434:11434 –name ollama ollama/ollama
至此大功告成。
/etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt initcall_blacklist=sysfb_init"
修改完畢,記得套用 update-grub 生效。
/etc/modules
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
kvm
kvm_intel
kvmgt
xengt
vfio-mdev
i915.enable_gvt=1
/etc/modprobe.d/pve-blacklist.conf
blacklist nouveau
blacklist i2c_nvidia_gpu
blacklist snd_hda_intel
blacklist snd_hda_codec_hdmi
blacklist nvidia*
/etc/modprobe.d/vfio.conf
以下紅色部分,是顯卡的代號,請自己修改
nvidia有兩個video與audio硬體代號,可執行 lspci -nnk | grep -i nvidia 取得
softdep nouveau pre: vfio-pci
softdep nvidia pre: vfio-pci
softdep nvidiafb pre: vfio-pci
softdep nvidia_drm pre: vfio-pci
softdep drm pre: vfio-pci
options vfio-pci ids=10de:2b85,10de:22e8 disable_vga=1 disable_denylist=1 disable_idle_d3=1 enable_sriov=1
修改modprobe相關檔案,記得要執行 update-initramfs -u 套用更新。
VM的設定
重點在紅框的 host、PCI Device(hostpci0)、 與 q35