2023-03-25

讓 ChatGPT 能料事如神

首度使用 ChatGPT 的體驗如何?

會不會覺得:「不怎麼樣嗎?!它的表現,不像外傳,那般的神嘛!」

非 ChatGPT 股東;更不是它們家員工的我,對此有話要說,想提供另一種持平的觀點!

【註】:個人為 ChatGPT Plus 訂戶;所以我的使用感受,系基於這個前提開啟的。

個人喜歡用 Markdown 文檔寫「規格文件」、「備忘錄」。最近,遇有需求:「原 Markdown 文檔中的某些內容,想放上我的 Google Blog 」。所以,我想要透過我的 Neovim 0.8 + Lua Script 將 Markdown 文檔中的一個個純文字段落,轉換成帶有 <p> tag 的 HTML 文檔。

昨天我向 GPT-4 提需求,要求它提供程式碼。結果,第一次,他弄錯了意思,所以,首版的產出,根本就不能用。經過:文字補述,詳敘我的需求,以這樣的方式與 GPT-4「溝通」,終於在十幾回合的往返後,GPT-4 滿足了敞人的需求。

今天,我又向 GPT-4 提: Markdown 文檔中「重編號」的需求,這次僅一個來回,它就提供了我所需要的程式。

-- 將 reorder_ordered_list 函數的定義添加到 init.lua
function _G.reorder_ordered_list()
    -- 獲取選取的文字區域
    local line_start, line_end = unpack(vim.api.nvim_buf_get_mark(0, "<")), unpack(vim.api.nvim_buf_get_mark(0, ">"))

    -- 將選取的文字區域讀入到一個表格中
    local lines = vim.api.nvim_buf_get_lines(0, line_start - 1, line_end, false)

    -- 初始化變數,存放重新排序後的有序列表項目
    local reordered_lines = {}

    -- 初始化列表項目編號
    local item_number = 1

    -- 迭代選取的每一行文字
    for _, line in ipairs(lines) do
        -- 使用正則表達式匹配有序列表項目
        if string.match(line, "^%s*%d+%..+") then
            -- 替換列表項目編號
            local new_line = string.gsub(line, "^%s*%d+%.", tostring(item_number) .. ".")
            table.insert(reordered_lines, new_line)

            -- 更新列表項目編號
            item_number = item_number + 1
        else
            -- 將未匹配的行保持原樣添加到 reordered_lines 中
            table.insert(reordered_lines, line)
        end
    end

    -- 將重新排序後的有序列表項目替換原來的文字區域
    vim.api.nvim_buf_set_lines(0, line_start - 1, line_end, false, reordered_lines)
end

-- 在 init.lua 中定義命令:執行 reorder_ordered_list 函數
vim.cmd("command! Reorder :lua _G.reorder_ordered_list()")
  

【總結】:

別把 ChatGPT 當神,認為它能洞悉我們要的是什麼;但我們可以訓練它,一旦它知道 了我們的「習慣」後,其「料事如神」的本事,便會逐漸顯現。

【參考】

最後,為說明上面那段 Lua Script 是怎麼產生的,附上個實際應用案例。以下,將今天我跟 GPT-4 溝通需求的過程及方式。

Markdown 文檔,原有 Ordered Lists 項目如下:

1. First item
2. Second item
3. Third item
4. Fourth item

但在插入新行後,原有的編號順序會被打亂:

1. First item
2. Lorem ipsum dolor sit amet consectetur
3. Second item
4. Third item
5. Fourth item

請仿以下 Lua Script ,撰寫程式。令我可依如下操作,重調 Ordered Lists 編號。

1. 按 `V` 鍵;
2. 移動游標;
3. 按 `V` 鍵;(自此完成了,使用 V-LINE 選擇一個區段的文字)
4. 按 `:` 鍵,要求在 Command Line 輸入 Neovim 指令;
5. 輸入 `Reorder` ,按 Enter 鍵。

------------------------------------------------------------------------------
-- 將選取的文字區域轉換成帶有 

標籤的 HTML 內容 ------------------------------------------------------------------------------ -- 將 convert_to_html 函數的定義添加到 init.lua function _G.convert_to_html() -- 獲取選取的文字區域 local line_start, line_end = unpack(vim.api.nvim_buf_get_mark(0, "<")), unpack(vim.api.nvim_buf_get_mark(0, ">")) -- 將選取的文字區域讀入到一個表格中 local lines = vim.api.nvim_buf_get_lines(0, line_start - 1, line_end, false) -- 初始化變數,存放轉換後的 HTML 內容 local html_lines = {} -- 在開始之前添加

標籤 table.insert(html_lines, "

") -- 迭代選取的每一行文字 for i, line in ipairs(lines) do -- 判斷是否為空行 if line == "" then -- 如果上一行不為空,則添加

標籤 if i > 1 and lines[i - 1] ~= "" then table.insert(html_lines, "

") -- 在

標籤後添加空白行 table.insert(html_lines, "") end -- 如果下一行不為空,則添加

標籤 if i < #lines and lines[i + 1] ~= "" then table.insert(html_lines, "

") end else -- 將非空行添加到 html_lines 中 table.insert(html_lines, line) end end -- 在結束時添加

標籤 table.insert(html_lines, "

") table.insert(html_lines, "") -- 將轉換後的 HTML 內容替換原來的文字區域 vim.api.nvim_buf_set_lines(0, line_start - 1, line_end, false, html_lines) end -- 在 init.lua 中定義命令:執行 convert_to_html 函數 vim.cmd("command! ConvertToHTML :lua _G.convert_to_html()") 需求細節: 1. Code 說明使用繁體字; 2. 若需使用 Lua Global Function / Global Variable ,需於其前加 `_G.`(如:`_G.convert_to_html()` ),這是為了令 Lua Linter 不會認為程式碼撰寫不符合規範)

以上這段洛洛長的文字,怕您看了頭暈,甚而有不知所云之感,所以,我需要將文章做個結構性的解析。

第 1 至 22 行,用於向 GPT-4 說明,我需要它代為撰碼的「功能需求」。第 18 至 22 行,則是參考 UML Scenario 的概念,用於向 GPT-4 詳述,我所要的「功能」,其操作使用的步驟系如何進行。

第 24 至 68 行,透過範例碼(Example Code),向 GPT-4 說明個人對程式撰碼的風格,進行規範:例如:要求 GPT-4 對於 Global Function 的命名方式,一定要在前頭加上 _G. ,免得 Neovim 0.8 預設的 LSP ,其 Linter 功能又要抱怨我在 Global Function 的使用沒照规規來;儘可能為程式碼加上中文註釋。

第 70 至 73 行,「需求細節」則是用於特別指定 GPT-4 在「產出」時,務必遵循的執行要點。譬如 72 行的第一點,就是要 GPT-4 別又突然轉用簡體中文;第二點則是再次提醒它,若是程式碼中需要用到 Lua Global Function 時,務必在 Funcation Name 之前補上 `_G.` 。

2023-03-24

當那一天真的來臨

當習主席沿著登機梯,逐步邁向機門的過程,耳裡聽著由「軍儀隊(Airport Honor Guard Band)」送來的樂音《當那一天來臨》;心頭會是什麼樣的念想?!

【後記】:

成長的年代,《龍的傳人》這首歌伴著我自少年轉青年。

⋯⋯
百年前寧靜的一個夜,巨變前夕的深夜裡。
槍砲聲敲碎了寧靜的夜,四面楚歌是姑息的劍。
多少年砲聲仍隆隆,多少年又是多少年。
⋯⋯

這三句詞,看著就心酸,每每無法完整唱完。想我華夏族人,有著優秀的文明,在漢、唐時 代更是萬朝來貢,何其風光。奈何自清末的鴉片戰爭起,我們就變得如此憋屈?時時忍受著 列強諸國強加我們身上的百般屈辱?

華夏先聖、先賢,所推崇的:「王道文化」。在《論語》堯曰第二十篇,其中有言:「興滅 國,繼絕世」。北宋理學家張載更立說:「為天地立心,為生民立命,為往聖繼絕學,為萬 世開太平。」

今天的中國,有著強大的經際實力;更有堅實的軍事武力為其後盾。世界諸國遇有難解的紛 爭,開始習慣找中國當大哥,為產生矛盾的雙方兩照排解題。這個世界秩序的新變化,看在 眼裡,著實叫人感動莫名!

國家有了堅實的軍事實力當後盾,當然人家自不敢小視我們。但也期待如今的中國,別像俗 諺所說的一樣:「好了傷疤,忘了痛」。萬萬莫將將今日中國,變成昔日的西方列強,憑藉 拳頭大,到處欺負人。

當那一天真的來臨

在全世界已逐漸看不到以理服人,需要有國家出面為全人類主持正義,維持國際新秩序時; 當世界諸國自願要求中國排解紛爭的那一天來臨時,中國人能昂首挺胸說:「是的!我已做 了周全的準備了!」

2023-03-17

出門一笑大江横,這人間,老子來過了!

《念奴嬌·斷虹霽雨》

作者:黃庭堅(宋代)

八月十七日,同諸生步自永安城樓,過張寬夫園待月。 偶有名酒,因以金荷酌衆客。客有孫彥立,善吹笛。援筆作樂府長短句,文不加點。

斷虹霽雨,淨秋空,山染修眉新綠。桂影扶疏,誰便道,今夕清輝不足?萬里青天,姮娥何處,駕此一輪玉。寒光零亂,爲誰偏照醽醁?

年少從我追遊,晚涼幽徑,繞張園森木。共倒金荷,家萬里,難得尊前相屬。 老子平生,江南江北,最愛臨風笛。孫郎微笑,坐來聲噴霜竹。

「⋯⋯其實大多數的人生没那麼壯闊,不過是桃李春風下飲的一杯酒;江湖夜雨中留的一盞燈。甚至是墓碑上寥寥幾字的生卒年月。

人生無趣是當真無趣,有趣也是當真有趣⋯⋯!!」

影片中的一席話,本就叫人愁悵、鼻酸不已。待至將盡之時,那首《人間烟火》配樂響起時,淚,於眼框泛成江河!

2023-03-14

《座敷童子的搖籃曲》

《座敷童子的搖籃曲》-日本卡通電影《河童之夏》中的插曲,非常「亞沙系」,極為温柔的一首歌。

🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿
花開、風吹
雪飄飛
萬物消逝

但我在這裡
你也不知怎地在這裡

睡吧、睡吧
昔今將來,明天總是會來

神啊,請不要忘了我
安心睡吧,安心睡吧,安心地睡吧
🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿

人生的路上,處境總會有高低,心情不免會有起伏。

好時光、壞時光,都也是人生路上,理應出現不同的風光。

不順意、難捱的時刻,靜心內省並傾聽上蒼的聲音,耐心學習成長必經的課程。

晨曦的亮光在暗夜之後得見
彩虹的炫麗得雨後才會展現

總有路可以繼續走下去, 難過的關鍵時候,總有人會關懷著你!

《時代 (中島みゆき)》フル

悲和喜的眼淚你我都流過
聚和散的折磨有誰不怕痛

多少事看在眼中彷彿一場夢
多少事反覆從頭躲也躲不過

但世上的人啊 不過都是過客
何苦讓昨夜的風吹熄今天的火

歲月帶著你我跟著時代不停地走
它來來去去從不曾為誰改變停留

人生路總難免有一點傷有一點起落
所有的失去的夢依然能擁有

《なごり雪 (殘雪)》イルカ


陪著你等著火車到來,
一旁的我不時注意著時間,
不合時節的雪,此時正滿天飄舞著。

你傷感而喃喃說著:
這應是今年東京最後的一場雪吧?!

殘雪降落,在此紛紛擾嚷的季節
而今,春己將至,
你變得如此美麗,比去年更加美麗了。

火車已緩緩啟動,
臉頰緊貼在車窗上的你,
似乎正有話說;
看著你的唇形,似像說著「再見」,
我竟慌亂地低頭看著地面。

時光飛逝,
當時年幼的你,
似乎仍未察覺自己已長大了吧。

而今,春己將至,
你已變得如此美麗,
比去年更加美麗了。

留在月台上的我,
望著飄落地面,隨即融化的殘雪

而今,春己將至,
你已變得如此美麗,
比去年更加美麗了~
你變得比去年更加美麗,
更加美麗了~~~

《雨の物語》イルカ

在這不止歇的長雨,
我一人獨行
等待那人出現,
直到全身溼透。

不停地走著,即便沒傘也不在乎。

在這雨中,我是個傷心的人。
無人相伴,只有雨水與我同行。

無法斷絕的思念,
往昔有我、有他我的美好時光。

即使在這時候,
我仍然想起,
即使在這樣的天氣裡,
我仍然微笑著。

但那回憶,
漸漸變得模糊、依稀,
就像雨水遇到暖陽一般,
一點、一滴漸漸消失。

在這不止歇的長雨,
我一人獨行
等待那人出現,
直到全身溼透。

《好久不見》小柳琉璃子

好久不見啊,竟然還能再遇到你
從那時到今天,時間已過多少年

現在的我是否更成熟了些
而你是否已結美好的姻緣

本以為不過是喝個茶,閒聊幾句便我們道別
怎料此次的重逢,我們竟不覺時間飛逝而過
想到又要再次道別
內心倍感惶恐難受

珍重,再見了
我狀似平靜,轉身離去
內心卻在自言自語
直到今天我還是喜歡著你

希望再一次,再一次,我們再次重新來過
希望再一次,再一次,重逢於不久的將來

電話裡傳來你的聲音
在這夜深人靜時分,聽到你說:好久不見
你那奇特卻又認真的聲音
原本睡意正濃的我,剎那間竟然全消

你說若你還是單身
是否我倆可像電影情節般談戀愛
你說愛可以培養,可以慢慢積累;

我不置可否,用笑聲忽悠帶過
電話結束前,我們又再次互道珍重
掛上話筒,陣陣感傷湧上心頭
不知怎的,顆顆淚珠滴滴滑落

希望再一次,再一次,我們再次重新來過
希望再一次,再一次,重逢於不久的將來

2023-03-09

在 Neovim 使用 plantuml-previewer.vim 為專案繪製設計文件

如何在 Neovim 啟用 PlantUML 的教學影片

常言道:「文不如表,表不如圖;一圖勝過千言萬語」。可知圖像給予人們的感覺,比文字乃至表格,更為強而有力。

UML (Unified Modeling Language,中文譯名:「統一塑模語言」),這套透過圖形規範,針對「軟體」塑形造模的方法論,自推出以來,廣被當作:描述系統/軟體架構,乃至軟體設計的工具。

以個人而言,我相信:「在軟體專案導入UML 圖,可協助我檢驗軟體設計的合理化,乃至在檢驗的過程中,察覺思考上的錯誤,乃至系統埋下了潛在的問題。個人好用的UML 圖為:循序圖及類別圖。我好使用循序圖來表達「功能細部設計」;而類別圖則用於描述軟體的 Domain Model 。在繪圖的過程,經常會發現原先未考量之事,所以程式碼在尚未動手撰寫前,便已先行「重構」和優化,避免了事後的重工,乃至除錯工作。」

雖說使用 UML 圖,對於軟體的開發有著諸多的好處。但也不得不承認,手工繪圖是件細鎖的煩人事。UML圖能為軟體開發人員帶來效益,但製圖過程卻費力耗時的反作用力,反而使人寧可放棄的問題,似乎被某些天賦異稟的軟體天才所發現,於是乎,這世界有了:PlantUML 的發明。PlantUML 的迷人之處在於:可用「文字敘述」描繪製作 UML 圖。

在 Neovim 眾多的 Plugins 中,plantuml-previewer.vim可供使用者在 Neovim 中「描繪」及「預覽」繪圖的成果。

  -- PlantUML
  use({ "weirongxu/plantuml-previewer.vim" })
  -- PlantUML syntax highlighting
  use({ "aklt/plantuml-syntax" })
  -- provides support to mermaid syntax files (e.g. *.mmd, *.mermaid)
  use({ "mracos/mermaid.vim" })

以下是個展示範例:在使用 Django 開發「部落格(Blog)」 的專案中。欲使用「循序圖(Sequence Diagram)」描述的「閱讀某則貼文」的功能規格。

閱讀貼文(Post)的文字描述

「描繪」此功能的循序圖,其「描述」文字如下:

@startuml
autonumber "[00]"

actor    User
control	 Django.Router		as Router
control  Django.Template	as Template
boundary post_detail     	as View
boundary CommentForm     	as Form
entity   Post				as Model
entity   Comment			as Comment
database database			as DB

User -> Router : url: /blog/  (post_detail)
Router -> View : post_detail(request, year, month, day, post)
View -> Model : get_object_or_404(Post, slug=post, \n status='published', publish__year=year, \n publish__month=month, publish__day=day)
Model -> DB : sql_query()
DB --> Model : post
Model --> View : post
View -> Comment: post.comments.filter(active=True)
Comment --> View: comments
View -> Form: CommentForm()
Form --> View: form
View --> Template: render(request, \n uri_of_template, \n {post, comments, form})
Template --> User: /blog/post/list.html
@enduml

最後,在文章結束之前,提供以下一些參考資料。希望對想了解 PlantUML 多一點;或是「如何在 Neovim 導入 PlantUML 之人」,能有所助益!

閱讀貼文(Post)循序圖

根據以上「描述文字」,繪製而成的循序圖如下:

如何以 PlantUML 呈現 Domain Model 的教學影片

【參考文件】

2023-03-02

將 ChatGPT 的 AI 功能,導入 Neovim 中

 


上述影片中的展示,使用的 Neovim 擴充套件(Plugin)為:ChatGPT.nvim

這擴充套件的安裝及設定,極為簡單,但...需小心的是:套件的運作,需要透過【環境變數:$OPENAI_API_KEY】,取得 ChatGPT API Key ;及操作的電腦中需有 curl 軟體已完成安裝。

所以,在完成 ChatGPT.nvim 的安裝及設定後,於重啟 Neovim 前,需先完成以下所述二事:

(1)在「終端機(Shell)」中,檢查及確認 curl 已安裝;若無,須先完成;

(2)取得 ChatGPT API Key 值,並於 Shell 設定檔中,完成「環境變數」:OPENAI_API_KEY 的設定。 

【例如】:在 ~/.zshrc~/.bashrc 檔中,添加以下設定:


...
export OPENAI_API_KEY="《取得之ChatGPT API Key值》"

以下是兩個操作案例的晝面展示:

(1)先是用英文,詢問如何在家中的陽台種植蕃茄?接著要求 ChatGPT 將回覆,自英文翻譯成中文;並要求輸出的格式須是 Markdown ;

(2)因為聽說 HighlightJS 可以令 Google Blogger 的貼文,顯示美觀、易讀的程式碼。但因個人不愛其預設的配色,想改用個人偏好的〖Tokyo Night Dark〗樣式(Style),所以,我在 Neovim 中,透過 ChatGPT.nvim 請教大神:「使用 hightlightjs ,要如何挑選不同的樣式?」