生成式AI - 輔助生成文字基礎圖表(Text-based diagram) I (弘文高中)
===
> [name=George YEH]
> [time=Sun, April 14, 2024 10:30 AM]
###### tags: `AI`, `GenAI`, `ChatGPT`, `Text-based diagram`, `Graphviz`, `Mermaid`
:::info
:bulb: 本課程將使用 生成式AI工具。可以先註冊[OpenAI ChatGPT](https://chat.openai.com/), 或 [Microsoft Copilot(建議使用Edge瀏覽器)](https://copilot.microsoft.com/)
另外,也將使用
* 文字基礎圖表(Text-based diagram)線上工具: https://dreampuf.github.io/GraphvizOnline
* 線上Python編譯器: https://www.onlinegdb.com/
:::
#### :small_blue_diamond: **地點:** 弘文高中
#### :small_blue_diamond: **日期:** 2024/04/19
#### :small_blue_diamond: **講師:** 靜宜大學 [葉介山資訊長](https://www1.pu.edu.tw/~jsyeh/DRYEH/)
#### :small_blue_diamond: [**簡報PPT**](https://puo365-my.sharepoint.com/:b:/g/personal/jsyeh_o365_pu_edu_tw/EXfDPYYQuEtBji0qWdPek_MB5d_a80wEu9MKdZsDh-76Bw?e=xbGk5S)(驗證碼:20240419)
## ℹ 生成式AI
### 1. 什麼是生成式AI(Generative AI, GenAI)?
* 由機器產生==複雜而有結構==的物件
### 2. AI生成內容(AI generated content)有哪幾類?
- ==Informative content (資訊性內容)==
* factual information, explanations, or specific topic analysis
* Based on clear rules and data, easier to process and generate
- ==Creative content (創意性內容)==
* Stories, poems, artwork, music, or design
* Requires higher levels of creativity and emotional expressions
### 3. 生成式AI能做什麼?
* Text generation 文本生成
* Image generation 影像生成
* Music generation 音樂生成
* Voice generation 語音生成
* Video generation 影片生成
* Design generation 設計生成
### 4. 生成式AI"還不能"做什麼?
* Common-sense reasoning 常識推理 (進化中)
* Understanding context deeply 深入理解上下文(進化中)
* Real-time adaptation and learning 即時適應與學習 (進化中)
* Ethical and moral reasoning 倫理和道德推理
* Creativity and originality 創造力和獨創性
* Emotional intelligence 情緒智商
* Self-awareness 自我覺察
* Cross-domain generalization 跨域泛化
* Long-term planning and goal setting 長期規劃與目標設定
* Genuine empathy and understanding 真正的同理心與理解
### 5. 熱門的AI文字生成工具?
* ==[OpenAI ChatGPT](https://chat.openai.com/)==
* [Android手機 (請至 Google Store下載)](https://play.google.com/store/apps/details?id=com.openai.chatgpt&hl=zh-TW)
* [iPhone手機(請至 App Store下載)](https://apps.apple.com/tw/app/chatgpt/id6448311069)
* ==[Microsoft Copilot(建議使用Edge瀏覽器)]
(https://copilot.microsoft.com/)==
* [Android手機 (請至 Google Store下載)](https://play.google.com/store/apps/details?id=com.microsoft.copilot&hl=zh-TW)
* [iPhone手機 (請至 App Store下載)](https://apps.apple.com/hk/app/microsoft-copilot/id6472538445) 
* [Google Gemini](https://gemini.google.com/app)
* [Anthropic Claude](https://claude.ai/)
### 6. 熱門的AI圖像生成工具?
* [OpenAI DALL·E](https://openai.com/dall-e-3)
* ==[Microsoft Bing Image Creator](https://www.bing.com/images/create)==
* [Midjourney](https://www.midjourney.com/)
* [Adobe Firefly](https://firefly.adobe.com/generate/images)
* ==[Moonshot](https://moonshot.today/)== (透過行動條碼加入LINE好友)
## ✍ 文字基礎圖表(Text-based diagram)
### 1. 什麼是==文字基礎圖表==?
* 一種使用文字和字符來表示和組織資訊的圖表。
* 不依賴於圖形或視覺元素,而是通過文字排列和符號來表達結構、流程、概念或系統。
* 在資料表示、程式設計、文件撰寫和學術研究中十分常見。
### 2. 文字基礎圖表的用途?
* **流程圖:** 表示步驟、決策和流程的文字描述。
* **組織架構圖:** 用於展示組織的層次結構和成員關係。
* **思維導圖:** 透過文字的層次和關聯來組織和展示思考。
* **代碼架構:** 展示軟體架構、類和方法的組織方式。
* **資料結構:** 用於表示資料的組織方式,如樹狀結構、圖等。
### 3. 文字基礎圖表有哪些格式?
* [PlantUML](https://www.plantuml.com/)
* 特點:簡單的文本語言來定義UML圖表,然後自動轉換成圖形表示。
* 用途:快速生成軟體設計文檔中的UML圖表。
* [Mermaid](https://mermaid.js.org/)
* 特點:文本語言描述圖表,然後自動生成流程圖、序列圖、甘特圖等。
* 用途:適用於Markdown文件中快速創建和共享複雜的圖表。
* 線上編輯工具 https://mermaid.live ☝️
* [Graphviz](https://graphviz.org/)
* 特點:使用DOT語言來描述圖表,然後生成圖形。
* 用途:用於自動化圖表生成,特別適合需要表示複雜網絡或結構的場合。
* 線上編輯工具
* https://dreampuf.github.io/GraphvizOnline/ ☝️
* https://www.devtoolsdaily.com/graphviz ☝️
* [D2](https://d2lang.com/)
* 特點:Declarative Diagramming
* 用途:適合需要表示複雜網絡或結構。
* 線上編輯工具
* https://play.d2lang.com/ ☝️
#### 範例: 輸入三個數字,判斷是否可以生成三角形
#### graphviz格式:
```graphviz!
digraph triangle_decision {
node [shape=rectangle, style=filled, fillcolor=lightblue, fontname=Arial];
start [label="開始",shape=ellipse, fillcolor="#00ff00"];
input [label="輸入三個數字"];
check1 [label="是否所有數字都大於零?", shape=diamond , style=filled, fillcolor=lightyellow];
check2 [label="是否任意兩個數字之和大於第三個數字?", shape=diamond, style=filled, fillcolor=lightcoral];
output_true [label="可以生成三角形"];
output_false [label="無法生成三角形"];
end [label="結束",shape=ellipse, fillcolor="#00ff00"];
start -> input;
input -> check1;
check1 -> check2 [label="是"];
check1 -> output_false [label="否"];
check2 -> output_true [label="是"];
check2 -> output_false [label="否"];
output_true -> end;
output_false -> end;
}
```
#### 呈現:
```graphviz
digraph triangle_decision {
node [shape=rectangle, style=filled, fillcolor=lightblue, fontname=Arial];
start [label="開始",shape=ellipse, fillcolor="#00ff00"];
input [label="輸入三個數字"];
check1 [label="是否所有數字都大於零?", shape=diamond , style=filled, fillcolor=lightyellow];
check2 [label="是否任意兩個數字之和大於第三個數字?", shape=diamond, style=filled, fillcolor=lightcoral];
output_true [label="可以生成三角形"];
output_false [label="無法生成三角形"];
end [label="結束",shape=ellipse, fillcolor="#00ff00"];
start -> input;
input -> check1;
check1 -> check2 [label="是"];
check1 -> output_false [label="否"];
check2 -> output_true [label="是"];
check2 -> output_false [label="否"];
output_true -> end;
output_false -> end;
}
```
#### graphviz格式:
```graphviz!
digraph _graph_name_ {
# 設定 (其實沒有順序,這整個文檔每行亂調輸出都一樣)
rankdir=LR; # 順序由左至右(上下是"TD")
graph [fontname="DFKai-SB"]; # 此三行是設定字型
node [fontname="DFKai-SB"]; # 中文務必指定
edge [fontname="DFKai-SB"]; # 不然可能會出現亂碼
# 這邊是 graph (圖面)
label="我是標題";
{rank=same A B C } # 同層(強迫上下)
{rank=same F G H } # 同層(強迫上下)
{rank=same D E } # 同層(強迫上下)
# 這邊是 node (節點)
A[label = "我是開始"]
B[label = "label\n是文字", shape=box]
C[label = "shape\n指定形狀\n(這是box)", shape=box]
D[shape=box] # 不給 label 就會直接用名稱
E[label = "diamond\n菱形", shape=diamond]
F[label = "\\n\n會換行", shape=box]
G[label = "$mathmode$\n要用LaTeX處理", shape=diamond]
H[label = "我是結束"]
# 這邊是 edge (邊)
A->B->C->D->E # 可以一直連
E->C [label="否"]
E->F [label="是"]
F->G
G->B [label="是"]
G->H [label="否"]
}
```
#### 呈現:
```graphviz
digraph _graph_name_ {
# 設定 (其實沒有順序,這整個文檔每行亂調輸出都一樣)
rankdir=LR; # 順序由左至右(上下是"TD")
graph [fontname="DFKai-SB"]; # 此三行是設定字型
node [fontname="DFKai-SB"]; # 中文務必指定
edge [fontname="DFKai-SB"]; # 不然可能會出現亂碼
# 這邊是 graph (圖面)
label="我是標題";
{rank=same A B C } # 同層(強迫上下)
{rank=same F G H } # 同層(強迫上下)
{rank=same D E } # 同層(強迫上下)
# 這邊是 node (節點)
A[label = "開始"]
B[label = "label\n是文字", shape=box]
C[label = "shape\n指定形狀\n(這是box)", shape=box]
D[shape=box] # 不給 label 就會直接用名稱
E[label = "diamond\n菱形", shape=diamond]
F[label = "\\n\n會換行", shape=box]
G[label = "$mathmode$\n要用LaTeX處理", shape=diamond]
H[label = "結束"]
# 這邊是 edge (邊)
A->B->C->D->E # 可以一直連
E->C [label="否"]
E->F [label="是"]
F->G
G->B [label="是"]
G->H [label="否"]
}
```
## ✍ 實作練習
### 1. 判斷閏年
A. 如何用簡單的方式介紹閏年?
B. 如何判斷閏年?
C. 產生一個判斷閏年的流程圖
D. 產生一個判斷閏年的python程式碼
### 2. 判斷星座
A. 如何判斷星座?
B. 請產生一個判斷生日星座的流程圖,以graphviz格式輸出
C. 請產生一個判斷生日星座的python程式碼
### 3. 判斷農曆生肖
A. 如何判斷農曆的生肖?
B. 請提供以西元年的生日為輸入,判斷農曆生肖的流程圖,以graphviz格式輸出
C. 請提供以西元年的生日為輸入,判斷農曆生肖的python程式碼。 需要包含日期格式是否正確的判斷,並輸出生肖的中英文名稱。
## :open_book: 解答
### 1. 判斷閏年 https://chat.openai.com/share/0ff90c0a-6394-44f7-813e-9b9d2f064667
#### A. 如何用簡單的方式介紹閏年?
```
定義:
閏年是指格里曆中一年中包含有一個额外的天數(閏日)的年份。
規則:
每四年有一個閏年。
除了能被 100 整除的年份,所有能被 4 整除的年份都是閏年。
但是,被 100 整除且不能被 400 整除的年份不是閏年。
目的:
修正了太陽年和曆年之間的差異,確保曆法與地球公轉的時間保持同步。
影響:
閏年對於確定復活節日期、會計年度等具有重要影響。
人們習慣於在閏年進行重要活動或慶祝。
範例:
例如,2020 年是閏年,有 366 天,2 月份有 29 天。
而 1900 年雖然能被 4 整除,但不能被 400 整除,因此不是閏年。
優缺點:
優點:
簡單易懂,適合初學者理解。
包含了基本的閏年計算規則。
缺點:
沒有涉及更深層次的歷史或文化背景。
缺少更複雜的詳細計算範例。
```
#### B. 如何判斷閏年?
```
判斷閏年的方法:
能被 4 整除的年份是閏年:
如果一個年份能夠被 4 整除,那麼它是閏年。
例外情況:
除了能被 100 整除的年份,所有能被 4 整除的年份都是閏年。
特殊情況:
能被 100 整除但不能被 400 整除的年份不是閏年。
示範:
2024 年是能被 4 整除的年份,因此是閏年。
1900 年能被 100 整除,但不能被 400 整除,因此不是閏年。
2000 年能被 400 整除,因此是閏年。
```
#### C. 產生一個判斷閏年的流程圖,以graphviz格式輸出
```graphviz!
digraph leap_year_decision {
node [shape=box, style=rounded];
Start [label="開始"];
Input [label="輸入年份"];
Divisible_by_4 [label="能否被 4 整除?"];
Divisible_by_100 [label="能否被 100 整除?"];
Divisible_by_400 [label="能否被 400 整除?"];
Leap_Year [label="是閏年"];
Not_Leap_Year [label="不是閏年"];
Start -> Input;
Input -> Divisible_by_4 [label="年份"];
Divisible_by_4 -> Leap_Year [label="是"];
Divisible_by_4 -> Divisible_by_100 [label="否"];
Divisible_by_100 -> Not_Leap_Year [label="是"];
Divisible_by_100 -> Divisible_by_400 [label="否"];
Divisible_by_400 -> Leap_Year [label="是"];
Divisible_by_400 -> Not_Leap_Year [label="否"];
}
```
```graphviz
digraph leap_year_decision {
node [shape=box, style=rounded];
Start [label="開始"];
Input [label="輸入年份"];
Divisible_by_4 [label="能否被 4 整除?"];
Divisible_by_100 [label="能否被 100 整除?"];
Divisible_by_400 [label="能否被 400 整除?"];
Leap_Year [label="是閏年"];
Not_Leap_Year [label="不是閏年"];
Start -> Input;
Input -> Divisible_by_4 [label="年份"];
Divisible_by_4 -> Leap_Year [label="是"];
Divisible_by_4 -> Divisible_by_100 [label="否"];
Divisible_by_100 -> Not_Leap_Year [label="是"];
Divisible_by_100 -> Divisible_by_400 [label="否"];
Divisible_by_400 -> Leap_Year [label="是"];
Divisible_by_400 -> Not_Leap_Year [label="否"];
}
```
可以在線上編譯工具 https://dreampuf.github.io/GraphvizOnline 測試
#### D. 產生一個判斷閏年的python程式碼
```python!
def is_leap_year(year):
"""
判斷一個年份是否為閏年。
參數:
year (int): 要判斷的年份。
返回值:
bool: 如果年份是閏年,則返回 True;否則返回 False。
"""
if year % 4 == 0:
if year % 100 == 0:
if year % 400 == 0:
return True
else:
return False
else:
return True
else:
return False
# 測試
year = int(input("請輸入年份:"))
if is_leap_year(year):
print(f"{year} 年是閏年")
else:
print(f"{year} 年不是閏年")
```
可以在線上python編譯器 https://www.onlinegdb.com/ 測試
### 2. 判斷星座 https://chat.openai.com/share/79193c9c-be28-4fc6-a6f0-20e2e79451a3
#### A. 如何判斷星座?
#### B. 請產生"輸入西元生日,輸出星座名稱"的流程圖,以graphviz格式輸出
```graphviz!
digraph G {
// Nodes
node [shape=box];
Start [label="開始"];
Input [label="輸入西元生日"];
CheckMonth [label="檢查月份"];
CheckDay [label="檢查日期"];
DetermineSign [label="確定星座"];
Output [label="輸出星座名稱"];
End [label="結束"];
// Edges
Start -> Input;
Input -> CheckMonth;
CheckMonth -> CheckDay [label="是3月至12月"];
CheckMonth -> DetermineSign [label="是1月或2月"];
CheckDay -> DetermineSign;
DetermineSign -> Output;
Output -> End;
}
```
```graphviz
digraph G {
// Nodes
node [shape=box];
Start [label="開始"];
Input [label="輸入西元生日"];
CheckMonth [label="檢查月份"];
CheckDay [label="檢查日期"];
DetermineSign [label="確定星座"];
Output [label="輸出星座名稱"];
End [label="結束"];
// Edges
Start -> Input;
Input -> CheckMonth;
CheckMonth -> CheckDay [label="是3月至12月"];
CheckMonth -> DetermineSign [label="是1月或2月"];
CheckDay -> DetermineSign;
DetermineSign -> Output;
Output -> End;
}
```
可以在線上編譯工具 https://dreampuf.github.io/GraphvizOnline 測試
#### C. 請產生一個判斷生日星座的python程式碼 。 參考以下的星座日期範圍:
* 白羊座(Aries):3月21日至4月19日
* 金牛座(Taurus):4月20日至5月20日
* 雙子座(Gemini):5月21日至6月20日
* 巨蟹座(Cancer):6月21日至7月22日
* 獅子座(Leo):7月23日至8月22日
* 處女座(Virgo):8月23日至9月22日
* 天秤座(Libra):9月23日至10月22日
* 天蠍座(Scorpio):10月23日至11月21日
* 射手座(Sagittarius):11月22日至12月21日
* 魔羯座(Capricorn):12月22日至1月19日
* 水瓶座(Aquarius):1月20日至2月18日
* 雙魚座(Pisces):2月19日至3月20日
```python
def determine_zodiac_sign(month, day):
if (month == 3 and day >= 21) or (month == 4 and day <= 19):
return "白羊座 (Aries)"
elif (month == 4 and day >= 20) or (month == 5 and day <= 20):
return "金牛座 (Taurus)"
elif (month == 5 and day >= 21) or (month == 6 and day <= 20):
return "雙子座 (Gemini)"
elif (month == 6 and day >= 21) or (month == 7 and day <= 22):
return "巨蟹座 (Cancer)"
elif (month == 7 and day >= 23) or (month == 8 and day <= 22):
return "獅子座 (Leo)"
elif (month == 8 and day >= 23) or (month == 9 and day <= 22):
return "處女座 (Virgo)"
elif (month == 9 and day >= 23) or (month == 10 and day <= 22):
return "天秤座 (Libra)"
elif (month == 10 and day >= 23) or (month == 11 and day <= 21):
return "天蠍座 (Scorpio)"
elif (month == 11 and day >= 22) or (month == 12 and day <= 21):
return "射手座 (Sagittarius)"
elif (month == 12 and day >= 22) or (month == 1 and day <= 19):
return "魔羯座 (Capricorn)"
elif (month == 1 and day >= 20) or (month == 2 and day <= 18):
return "水瓶座 (Aquarius)"
elif (month == 2 and day >= 19) or (month == 3 and day <= 20):
return "雙魚座 (Pisces)"
else:
return "日期不合法"
# 輸入生日
month = int(input("請輸入生日的月份(數字):"))
day = int(input("請輸入生日的日期(數字):"))
# 判斷星座
zodiac_sign = determine_zodiac_sign(month, day)
print("你的星座是:", zodiac_sign)
```
可以在線上python編譯器 https://www.onlinegdb.com/ 測試
#### D. 請增加判斷輸入西元日期是否為正確的程式
```python
def is_valid_date(year, month, day):
# 判斷年、月、日是否在合法範圍內
if year < 0:
return False
if month < 1 or month > 12:
return False
if day < 1:
return False
# 判斷每個月的天數是否合法
if month in [1, 3, 5, 7, 8, 10, 12]:
return day <= 31
elif month in [4, 6, 9, 11]:
return day <= 30
elif month == 2:
# 判斷閏年
if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
return day <= 29
else:
return day <= 28
else:
return False
def determine_zodiac_sign(year, month, day):
# 判斷輸入日期是否合法
if not is_valid_date(year, month, day):
return "日期不合法"
# 根據日期確定星座
if (month == 3 and day >= 21) or (month == 4 and day <= 19):
return "白羊座 (Aries)"
elif (month == 4 and day >= 20) or (month == 5 and day <= 20):
return "金牛座 (Taurus)"
elif (month == 5 and day >= 21) or (month == 6 and day <= 20):
return "雙子座 (Gemini)"
elif (month == 6 and day >= 21) or (month == 7 and day <= 22):
return "巨蟹座 (Cancer)"
elif (month == 7 and day >= 23) or (month == 8 and day <= 22):
return "獅子座 (Leo)"
elif (month == 8 and day >= 23) or (month == 9 and day <= 22):
return "處女座 (Virgo)"
elif (month == 9 and day >= 23) or (month == 10 and day <= 22):
return "天秤座 (Libra)"
elif (month == 10 and day >= 23) or (month == 11 and day <= 21):
return "天蠍座 (Scorpio)"
elif (month == 11 and day >= 22) or (month == 12 and day <= 21):
return "射手座 (Sagittarius)"
elif (month == 12 and day >= 22) or (month == 1 and day <= 19):
return "魔羯座 (Capricorn)"
elif (month == 1 and day >= 20) or (month == 2 and day <= 18):
return "水瓶座 (Aquarius)"
elif (month == 2 and day >= 19) or (month == 3 and day <= 20):
return "雙魚座 (Pisces)"
else:
return "日期不合法"
# 輸入生日
year = int(input("請輸入西元年份(數字):"))
month = int(input("請輸入生日的月份(數字):"))
day = int(input("請輸入生日的日期(數字):"))
# 判斷星座
zodiac_sign = determine_zodiac_sign(year, month, day)
print("你的星座是:", zodiac_sign)
```
### 3. 判斷農曆生肖 https://chat.openai.com/share/bc5682e9-1447-4b72-bd58-5374f301b707
#### A. 如何判斷農曆的生肖?
#### B. 請提供以西元年的生日為輸入,判斷農曆生肖的流程圖,以graphviz格式輸出
```graphviz!
digraph G {
node [shape=box, style=rounded, fontname="Arial"];
edge [fontname="Arial"];
Start [label="開始"];
Input [label="輸入西元年的生日", shape=diamond];
Determine [label="確定農曆年份"];
Lookup [label="查找生肖對應表"];
Output [label="輸出對應的生肖"];
End [label="結束"];
Start -> Input;
Input -> Determine [label="西元年轉換為農曆年"];
Determine -> Lookup;
Lookup -> Output;
Output -> End;
}
```
```graphviz
digraph G {
node [shape=box, style=rounded, fontname="Arial"];
edge [fontname="Arial"];
Start [label="開始"];
Input [label="輸入西元年的生日", shape=diamond];
Determine [label="確定農曆年份"];
Lookup [label="查找生肖對應表"];
Output [label="輸出對應的生肖"];
End [label="結束"];
Start -> Input;
Input -> Determine [label="西元年轉換為農曆年"];
Determine -> Lookup;
Lookup -> Output;
Output -> End;
}
```
可以在線上編譯工具 https://dreampuf.github.io/GraphvizOnline 測試
#### C. 請提供以西元年的生日為輸入,判斷農曆生肖的python程式碼。 需要包含日期格式是否正確的判斷,並輸出生肖的中英文名稱。
```python!
from datetime import datetime
# 定義生肖對應表
zodiac_map = {
0: ("鼠", "Rat"),
1: ("牛", "Ox"),
2: ("虎", "Tiger"),
3: ("兔", "Rabbit"),
4: ("龍", "Dragon"),
5: ("蛇", "Snake"),
6: ("馬", "Horse"),
7: ("羊", "Goat"),
8: ("猴", "Monkey"),
9: ("雞", "Rooster"),
10: ("狗", "Dog"),
11: ("豬", "Pig")
}
def determine_zodiac(birthday):
try:
# 轉換生日為datetime對象
birthday_date = datetime.strptime(birthday, "%Y-%m-%d")
# 確認生日是否在1900年到2099年之間
if 1900 <= birthday_date.year <= 2099:
# 計算生肖年份
year_diff = birthday_date.year - 1900
zodiac_index = (year_diff % 12)
# 根據生肖年份查找生肖
chinese_zodiac, english_zodiac = zodiac_map[zodiac_index]
return chinese_zodiac, english_zodiac
else:
return "生日年份不在1900年到2099年範圍內", "Birthday year is not within the range of 1900 to 2099"
except ValueError:
return "生日格式不正確,應為YYYY-MM-DD", "Incorrect birthday format, should be YYYY-MM-DD"
# 測試程式碼
birthday = input("請輸入您的西元生日(YYYY-MM-DD):")
chinese_zodiac, english_zodiac = determine_zodiac(birthday)
print("您的農曆生肖是:", chinese_zodiac, "(", english_zodiac, ")")
```
可以在線上python編譯器 https://www.onlinegdb.com/ 測試
### 參考資料
* 生成式AI資源庫, https://hackmd.io/xy0aXSm6SMCgDx3QvLbQng
* AI發展歷史, https://gitmind.com/app/docs/mohfye1p
* Generative AI (GAI) for teaching and learning, https://gitmind.com/app/docs/m7bnildt