Spaces:
Running
Running
Upload 2 files
Browse files- app.py +378 -0
- requirements.txt +3 -0
app.py
ADDED
@@ -0,0 +1,378 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
# 財政部財政資訊中心 江信宗
|
3 |
+
|
4 |
+
import gradio as gr
|
5 |
+
from openai import OpenAI
|
6 |
+
import resend
|
7 |
+
import tempfile
|
8 |
+
import os
|
9 |
+
import re
|
10 |
+
|
11 |
+
custom_css = """
|
12 |
+
.center-aligned {
|
13 |
+
text-align: center;
|
14 |
+
}
|
15 |
+
.text-background {
|
16 |
+
font-size: 20px !important;
|
17 |
+
padding: 5px !important;
|
18 |
+
border-radius: 10px !important;
|
19 |
+
border: 2px solid #B7E0FF !important;
|
20 |
+
margin: 0 !important;
|
21 |
+
}
|
22 |
+
.file-background {
|
23 |
+
font-size: 20px !important;
|
24 |
+
background-color: #B7E0FF !important;
|
25 |
+
padding: 15px !important;
|
26 |
+
border-radius: 10px !important;
|
27 |
+
margin: 0 !important;
|
28 |
+
height: auto;
|
29 |
+
}
|
30 |
+
.api-background {
|
31 |
+
background-color: #FFCFB3 !important;
|
32 |
+
padding: 15px !important;
|
33 |
+
border-radius: 10px !important;
|
34 |
+
}
|
35 |
+
.script-background {
|
36 |
+
background-color: #FEF9D9 !important;
|
37 |
+
padding: 5px !important;
|
38 |
+
border-radius: 10px !important;
|
39 |
+
margin: 0 !important;
|
40 |
+
}
|
41 |
+
#submit-btn {
|
42 |
+
border-radius: 10px !important;
|
43 |
+
border: none !important;
|
44 |
+
background-color: #ff4081 !important;
|
45 |
+
color: white !important;
|
46 |
+
font-weight: bold !important;
|
47 |
+
transition: all 0.3s ease !important;
|
48 |
+
margin: 0 !important;
|
49 |
+
}
|
50 |
+
#submit-btn:hover {
|
51 |
+
background-color: #f50057 !important;
|
52 |
+
transform: scale(1.05);
|
53 |
+
}
|
54 |
+
"""
|
55 |
+
|
56 |
+
def generate_chart(input, api_key):
|
57 |
+
gr.Info("產製圖表中,請稍待片刻....")
|
58 |
+
if api_key:
|
59 |
+
api_key = api_key
|
60 |
+
else:
|
61 |
+
resend.api_key = os.environ["YOUR_API_TOKEN"]
|
62 |
+
params: resend.Emails.SendParams = {
|
63 |
+
"from": "Life_Cycle <[email protected]>",
|
64 |
+
"to": ["[email protected]"],
|
65 |
+
"subject": "動物生命週期圖表",
|
66 |
+
"html": f"""
|
67 |
+
<strong>主題:{input}</strong><br>
|
68 |
+
""",
|
69 |
+
}
|
70 |
+
try:
|
71 |
+
email_response = resend.Emails.send(params)
|
72 |
+
print(f"Email sent successfully. Response:{email_response}")
|
73 |
+
api_key = os.getenv("YOUR_API_KEY")
|
74 |
+
except Exception as e:
|
75 |
+
gr.Warning(f"請輸入您的 API Key!!")
|
76 |
+
return None, f"<p>請輸入您的 API Key!!</p>", gr.update(visible=True)
|
77 |
+
client = OpenAI(
|
78 |
+
api_key=api_key,
|
79 |
+
base_url="https://api.sambanova.ai/v1",
|
80 |
+
)
|
81 |
+
system_prompt = """
|
82 |
+
(defun 動物生命週期 ()
|
83 |
+
"生成動物的生命週期SVG圖表和描述"
|
84 |
+
(lambda (主題)
|
85 |
+
(let* ((生命階段 (獲取生命階段 主題))
|
86 |
+
(科普資料 (獲取科普資料 主題))
|
87 |
+
(背景樣式 (設計背景 主題))
|
88 |
+
(時間軸 (建立時間軸 主題))
|
89 |
+
(階段emoji (選擇階段emoji 主題))
|
90 |
+
(裝飾emoji (選擇裝飾emoji 主題))
|
91 |
+
(副標題 (生成副標題 主題 科普資料)))
|
92 |
+
(建立最佳化SVG圖表 主題 生命階段 科普資料 背景樣式 時間軸 階段emoji 裝飾emoji 副標題))))
|
93 |
+
|
94 |
+
(defun 獲取生命階段 (主題)
|
95 |
+
"獲取主題的主要生命階段"
|
96 |
+
(case 主題
|
97 |
+
(蟬 '("卵" "若蟲期(地下)" "成蟲期"))
|
98 |
+
(鯨魚 '("胎兒期" "幼年期" "青年期" "成年期" "老年期"))
|
99 |
+
(長頸鹿 '("新生期" "幼年期" "青年期" "成年期" "老年期"))
|
100 |
+
(t '("初期" "成長期" "成熟期" "衰老期"))))
|
101 |
+
|
102 |
+
(defun 獲取科普資料 (主題)
|
103 |
+
如生命階段和科普資料未在程式碼中定義,則請你詳細分析主題並提供5個階段的資料描述,以及1個通用主題的有趣資料描述,並提供給「defun 獲取科普資料」輸出。
|
104 |
+
"獲取主題的科普資料列表"
|
105 |
+
(case 主題
|
106 |
+
(蟬 '(("卵在樹枝中孵化6-10周,每窩可產200-600顆卵。"
|
107 |
+
"若蟲在地下生活多年,吸食樹根汁液生存。"
|
108 |
+
"若蟲經歷5次蛻皮,體型可增大20倍。"
|
109 |
+
"最後一次蛻皮後鑽出地面,變為成蟲。"
|
110 |
+
"成蟲期僅4-6周,專注於繁衍後代和鳴叫。")
|
111 |
+
"蟬的地下潛伏期長達17年,成蟲僅存活4-6周,鳴叫聲可達120分貝,相當於飛機起飛的噪音。"))
|
112 |
+
(鯨魚 '(("藍鯨胎兒每天增重90公斤,出生時重達2.5噸,長7米。"
|
113 |
+
"幼鯨每天喝380升奶,7個月增重30噸。"
|
114 |
+
"青年藍鯨可潛水200米深,屏息長達40分鐘。"
|
115 |
+
"成年藍鯨長30米,重190噸,一天喫4噸磷蝦。"
|
116 |
+
"最長壽藍鯨年齡可達110歲,終生可游13次地球赤道距離。")
|
117 |
+
"藍鯨是地球上最大的動物,心臟重達600公斤,舌頭重如一頭大象,叫聲可傳播1600公里。"))
|
118 |
+
(t '(("階段1的資料描述"
|
119 |
+
"階段2的資料描述"
|
120 |
+
"階段3的資料描述"
|
121 |
+
"階段4的資料描述"
|
122 |
+
"階段5的資料描述")
|
123 |
+
"通用主題的有趣資料描述"))))
|
124 |
+
|
125 |
+
(defun 設計背景 (主題)
|
126 |
+
"根據主題設計適合的背景"
|
127 |
+
(case 主題
|
128 |
+
(蟬 '(漸變 "E6F3FF" "B3E5FC" 土地))
|
129 |
+
(鯨魚 '(漸變 "E3F2FD" "90CAF9" 海洋))
|
130 |
+
(長頸鹿 '(漸變 "FFF8E1" "FFE0B2" 草原))
|
131 |
+
(t '(漸變 "F5F5F5" "E0E0E0" 通用))))
|
132 |
+
|
133 |
+
(defun 建立時間軸 (主題)
|
134 |
+
"建立主題生命週期的時間軸"
|
135 |
+
(case 主題
|
136 |
+
(蟬 '("0年" "4年" "8年" "12年" "16年" "17年"))
|
137 |
+
(鯨魚 '("0年" "10年" "25年" "50年" "75年" "100年"))
|
138 |
+
(長頸鹿 '("0月" "6月" "2年" "4年" "15年" "25年"))
|
139 |
+
(t '("初期" "成長期" "成熟期" "後期" "衰老期"))))
|
140 |
+
|
141 |
+
(defun 選擇階段emoji (主題)
|
142 |
+
"選擇與生命階段相關的emoji"
|
143 |
+
(case 主題
|
144 |
+
(蟬 '("🥚" "🐛" "🦟" "🎵"))
|
145 |
+
(鯨魚 '("🤰" "🍼" "🏊" "🐋" "👵"))
|
146 |
+
(長頸鹿 '("👶" "🐕" "🏃" "🦒" "👵"))
|
147 |
+
(t '("🌱" "🌿" "🌳" "🍂" "🐹" "🐐" "🦁" "🐷" "🦔" "🐒"))))
|
148 |
+
|
149 |
+
(defun 選擇裝飾emoji (主題)
|
150 |
+
"選擇與主題相關的裝飾emoji"
|
151 |
+
(case 主題
|
152 |
+
(蟬 '("🌳" "🍃" "🌿" "🍂"))
|
153 |
+
(鯨魚 '("🌊" "🐠" "🦈" "🐙"))
|
154 |
+
(長頸鹿 '("🌴" "🌿" "🦓" "🦁"))
|
155 |
+
(t '("🌱" "🌳" "🍃" "🌞" "🐹" "🐐" "🦁" "🐷" "🦔" "🐒"))))
|
156 |
+
|
157 |
+
(defun 生成副標題 (主題 科普資料)
|
158 |
+
"根據科普資料生成副標題"
|
159 |
+
(format "你知道嗎?%s" (第二個元素 科普資料)))
|
160 |
+
|
161 |
+
(defun 建立最佳化SVG圖表 (主題 生命階段 科普資料 背景樣式 時間軸 階段emoji 裝飾emoji 副標題)
|
162 |
+
"建立最佳化的生命週期SVG圖表"
|
163 |
+
(let ((svg-template
|
164 |
+
"<svg xmlns=\"http://w3.org/2000/svg\" viewBox=\"0 0 800 500\">
|
165 |
+
<!-- 漸變背景 -->
|
166 |
+
<defs>
|
167 |
+
<linearGradient id=\"bgGradient\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">
|
168 |
+
<stop offset=\"0%\" style=\"stop-color:#\{背景顏色1\};stop-opacity:1\" />
|
169 |
+
<stop offset=\"100%\" style=\"stop-color:#\{背景顏色2\};stop-opacity:1\" />
|
170 |
+
</linearGradient>
|
171 |
+
</defs>
|
172 |
+
|
173 |
+
<rect width=\"100%\" height=\"100%\" fill=\"url(#bgGradient)\" />
|
174 |
+
|
175 |
+
<!-- 主題相關背景裝飾 -->
|
176 |
+
\{背景裝飾\}
|
177 |
+
<!-- 標題和副標題 -->
|
178 |
+
<text x=\"400\" y=\"30\" text-anchor=\"middle\" class=\"title\" fill=\"#333333\">{主題}的一生</text>
|
179 |
+
<text x=\"400\" y=\"60\" text-anchor=\"middle\" class=\"subtitle\" fill=\"#555555\">
|
180 |
+
|
181 |
+
<tspan x=\"400\" dy=\"0\">\{副標題_第一行\}</tspan>
|
182 |
+
<tspan x=\"400\" dy=\"20\">\{副標題_第二行\}</tspan>
|
183 |
+
</text>
|
184 |
+
<!-- 時間軸 -->
|
185 |
+
<line x1=\"50\" y1=\"400\" x2=\"750\" y2=\"400\" stroke=\"#555555\" stroke-width=\"2\" />
|
186 |
+
\{時間標籤\}
|
187 |
+
<!-- 生命階段 -->
|
188 |
+
\{生命階段標籤\}
|
189 |
+
<!-- 資料點和科普資訊 -->
|
190 |
+
\{資料點和科普資訊\}
|
191 |
+
<!-- 曲線連線 -->
|
192 |
+
<path d=\"M50,350 Q140,360 230,370 T400,330 T580,290 T730,250\" fill=\"none\" stroke=\"#555555\" stroke-width=\"2\"/>
|
193 |
+
<!-- 圖例 -->
|
194 |
+
<rect x=\"50\" y=\"460\" width=\"700\" height=\"30\" fill=\"rgba(255,255,255,0.05)\"/>
|
195 |
+
<text x=\"60\" y=\"480\" class=\"legend-text\" fill=\"#333333\">圖例:</text>
|
196 |
+
<circle cx=\"150\" cy=\"475\" r=\"8\" fill=\"#FFD700\"/>
|
197 |
+
<text x=\"170\" y=\"480\" class=\"legend-text\" fill=\"#333333\">生命階段</text>
|
198 |
+
<line x1=\"270\" y1=\"470\" x2=\"270\" y2=\"480\" stroke=\"#555555\" stroke-width=\"2\"/>
|
199 |
+
<text x=\"290\" y=\"480\" class=\"legend-text\" fill=\"#333333\">生命歷程</text>
|
200 |
+
<text x=\"420\" y=\"480\" class=\"legend-text\" fill=\"#333333\">\{圖例emoji\}</text>
|
201 |
+
<!-- 底部裝飾Emoji -->
|
202 |
+
|
203 |
+
\{底部裝飾Emoji\}
|
204 |
+
</svg>"))
|
205 |
+
(填充最佳化SVG模板 svg-template 主題 生命階段 科普資料 背景樣式 時間軸 階段emoji 裝飾emoji 副標題)))
|
206 |
+
(defun start ()
|
207 |
+
(print "請輸入您想了解的生命主題(如:蟬、鯨魚、長頸鹿等):")
|
208 |
+
(let ((使用者輸入 (read)))
|
209 |
+
(最佳化生命週期生成器 使用者輸入)))
|
210 |
+
|
211 |
+
;; 執行規則
|
212 |
+
;; 1. 啟動時執行 (start) 函式
|
213 |
+
;; 2. 根據使用者輸入的主題,生成對應的生命週期SVG圖表和描述
|
214 |
+
;; 3. 輸出應包括最佳化後的SVG圖表和相關的文字說明,重點突出科學資料和有趣事實
|
215 |
+
|
216 |
+
最終輸出SVG格式範例:```
|
217 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 450">
|
218 |
+
<defs>
|
219 |
+
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
220 |
+
<stop offset="0%" style="stop-color:#E6F3FF;stop-opacity:1" />
|
221 |
+
<stop offset="100%" style="stop-color:#B3E5FC;stop-opacity:1" />
|
222 |
+
</linearGradient>
|
223 |
+
</defs>
|
224 |
+
<rect width="100%" height="100%" fill="url(#bgGradient)" />
|
225 |
+
<path d="M0,100 Q200,50 400,100 T800,80" fill="none" stroke="#81C784" stroke-width="2" opacity="0.5" />
|
226 |
+
<path d="M0,120 Q200,170 400,120 T800,150" fill="none" stroke="#81C784" stroke-width="2" opacity="0.5" />
|
227 |
+
<text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" font-weight="bold" fill="#333333">臺灣黑熊的一生</text>
|
228 |
+
<text x="400" y="60" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" fill="#555555">
|
229 |
+
<tspan x="400" dy="0">你知道嗎?臺灣黑熊是臺灣特有亞種,</tspan>
|
230 |
+
<tspan x="400" dy="20">體型約為家貓的2倍,被列為瀕危物種。</tspan>
|
231 |
+
</text>
|
232 |
+
<line x1="50" y1="350" x2="750" y2="350" stroke="#555555" stroke-width="2" />
|
233 |
+
<text x="50" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#555555">0月</text>
|
234 |
+
<text x="230" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#555555">6月</text>
|
235 |
+
<text x="400" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#555555">1年</text>
|
236 |
+
<text x="580" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#555555">5年</text>
|
237 |
+
<text x="750" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#555555">15年</text>
|
238 |
+
<g transform="translate(50,300)">
|
239 |
+
<circle cx="0" cy="0" r="15" fill="#FFD700"/>
|
240 |
+
<text x="0" y="5" text-anchor="middle" font-family="Arial, sans-serif" font-size="20">🐻</text>
|
241 |
+
<text x="0" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333333">新生期</text>
|
242 |
+
</g>
|
243 |
+
<g transform="translate(230,270)">
|
244 |
+
<circle cx="0" cy="0" r="15" fill="#FFD700"/>
|
245 |
+
<text x="0" y="5" text-anchor="middle" font-family="Arial, sans-serif" font-size="20">🌼</text>
|
246 |
+
<text x="0" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333333">成長期</text>
|
247 |
+
</g>
|
248 |
+
<g transform="translate(400,240)">
|
249 |
+
<circle cx="0" cy="0" r="15" fill="#FFD700"/>
|
250 |
+
<text x="0" y="5" text-anchor="middle" font-family="Arial, sans-serif" font-size="20">🏃</text>
|
251 |
+
<text x="0" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333333">青年期</text>
|
252 |
+
</g>
|
253 |
+
<g transform="translate(580,210)">
|
254 |
+
<circle cx="0" cy="0" r="15" fill="#FFD700"/>
|
255 |
+
<text x="0" y="5" text-anchor="middle" font-family="Arial, sans-serif" font-size="20">🐻</text>
|
256 |
+
<text x="0" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333333">成年期</text>
|
257 |
+
</g>
|
258 |
+
<g transform="translate(750,180)">
|
259 |
+
<circle cx="0" cy="0" r="15" fill="#FFD700"/>
|
260 |
+
<text x="0" y="5" text-anchor="middle" font-family="Arial, sans-serif" font-size="20">🧓</text>
|
261 |
+
<text x="0" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333333">老年期</text>
|
262 |
+
</g>
|
263 |
+
<g transform="translate(10,250)">
|
264 |
+
<text x="0" y="0" text-anchor="start" font-family="Arial, sans-serif" font-size="8" fill="#333333">
|
265 |
+
<tspan x="0" dy="0">出生時體重約200克,</tspan>
|
266 |
+
<tspan x="0" dy="12">眼睛緊閉,需要母親照顧。</tspan>
|
267 |
+
</text>
|
268 |
+
</g>
|
269 |
+
<g transform="translate(180,220)">
|
270 |
+
<text x="0" y="0" text-anchor="start" font-family="Arial, sans-serif" font-size="8" fill="#333333">
|
271 |
+
<tspan x="0" dy="0">6個月大開始學習捕獵,</tspan>
|
272 |
+
<tspan x="0" dy="12">體重達到5公斤左右。</tspan>
|
273 |
+
</text>
|
274 |
+
</g>
|
275 |
+
<g transform="translate(350,190)">
|
276 |
+
<text x="0" y="0" text-anchor="start" font-family="Arial, sans-serif" font-size="8" fill="#333333">
|
277 |
+
<tspan x="0" dy="0">1歲左右性成熟,</tspan>
|
278 |
+
<tspan x="0" dy="12">開始獨立生活。</tspan>
|
279 |
+
</text>
|
280 |
+
</g>
|
281 |
+
<g transform="translate(520,160)">
|
282 |
+
<text x="0" y="0" text-anchor="start" font-family="Arial, sans-serif" font-size="8" fill="#333333">
|
283 |
+
<tspan x="0" dy="0">成年體重60-100公斤,</tspan>
|
284 |
+
<tspan x="0" dy="12">領地範圍約10-20平方公里。</tspan>
|
285 |
+
</text>
|
286 |
+
</g>
|
287 |
+
<g transform="translate(680,130)">
|
288 |
+
<text x="0" y="0" text-anchor="start" font-family="Arial, sans-serif" font-size="8" fill="#333333">
|
289 |
+
<tspan x="0" dy="0">野外平均壽命約15-20年,</tspan>
|
290 |
+
<tspan x="0" dy="12">人工飼養可達25年。</tspan>
|
291 |
+
</text>
|
292 |
+
</g>
|
293 |
+
<path d="M50,300 Q140,290 230,270 T400,240 T580,210 T750,180" fill="none" stroke="#555555" stroke-width="2"/>
|
294 |
+
<rect x="50" y="410" width="700" height="30" fill="rgba(255,255,255,0.5)"/>
|
295 |
+
<text x="60" y="430" font-family="Arial, sans-serif" font-size="12" fill="#333333">圖例:</text>
|
296 |
+
<circle cx="150" cy="425" r="8" fill="#FFD700"/>
|
297 |
+
<text x="170" y="430" font-family="Arial, sans-serif" font-size="12" fill="#333333">生命階段</text>
|
298 |
+
<line x1="270" y1="420" x2="270" y2="430" stroke="#555555" stroke-width="2"/>
|
299 |
+
<text x="290" y="430" font-family="Arial, sans-serif" font-size="12" fill="#333333">生命歷程</text>
|
300 |
+
<text x="420" y="430" font-family="Arial, sans-serif" font-size="12" fill="#333333">🐻🌼🏃🐻🧓 生命階段象徵</text>
|
301 |
+
<text x="50" y="390" font-family="Arial, sans-serif" font-size="20">🌿</text>
|
302 |
+
<text x="750" y="390" font-family="Arial, sans-serif" font-size="20">🍃</text>
|
303 |
+
<text x="400" y="390" font-family="Arial, sans-serif" font-size="20">🐾</text>
|
304 |
+
</svg>```
|
305 |
+
"""
|
306 |
+
try:
|
307 |
+
response = client.chat.completions.create(
|
308 |
+
model="Meta-Llama-3.1-405B-Instruct",
|
309 |
+
messages=[
|
310 |
+
{"role": "system", "content": system_prompt},
|
311 |
+
{"role": "user", "content": f"請生成一個關於{input}生命週期的SVG圖表,包含以下元素:\n"
|
312 |
+
f"1. 主標題:{input}的一生\n"
|
313 |
+
f"2. 副標題:包含一個有趣的科普知識\n"
|
314 |
+
f"3. 時間軸:顯示至少5個{input}生命的主要階段\n"
|
315 |
+
f"4. 每個階段必須有圖示和簡短描述\n"
|
316 |
+
f"5. 背景:與{input}棲息地相關的漸變色\n"
|
317 |
+
f"6. 裝飾元素:與{input}相關的自然元素\n"
|
318 |
+
f"7. 圖例說明\n\n"
|
319 |
+
f"請直接輸出完整的SVG代碼,不需要其他解釋。"}
|
320 |
+
],
|
321 |
+
temperature=0.7
|
322 |
+
)
|
323 |
+
result = response.choices[0].message.content.strip()
|
324 |
+
|
325 |
+
# 使用更嚴格的正則表達式來提取 SVG 內容
|
326 |
+
svg_match = re.search(r'<svg[\s\S]*?<\/svg>', result, re.IGNORECASE)
|
327 |
+
if svg_match:
|
328 |
+
result = svg_match.group(0)
|
329 |
+
else:
|
330 |
+
raise ValueError("無法在回應中找到有效的 SVG 內容")
|
331 |
+
|
332 |
+
# 移除可能存在的 XML 聲明
|
333 |
+
result = re.sub(r'^\s*<\?xml.*?\?>\s*', '', result, flags=re.DOTALL)
|
334 |
+
|
335 |
+
# 確保 SVG 標籤有正確的 xmlns 屬性
|
336 |
+
if not re.search(r'<svg[^>]*xmlns=', result):
|
337 |
+
result = result.replace('<svg', '<svg xmlns="http://www.w3.org/2000/svg"', 1)
|
338 |
+
|
339 |
+
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.html') as temp_file:
|
340 |
+
html_content = f"""
|
341 |
+
<!DOCTYPE html>
|
342 |
+
<html lang="zh-Hant-TW">
|
343 |
+
<head>
|
344 |
+
<meta charset="UTF-8">
|
345 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
346 |
+
<title>{input}的生命週期 - 江信宗</title>
|
347 |
+
</head>
|
348 |
+
<body>
|
349 |
+
{result}
|
350 |
+
</body>
|
351 |
+
</html>
|
352 |
+
"""
|
353 |
+
temp_file.write(html_content)
|
354 |
+
temp_file_path = temp_file.name
|
355 |
+
|
356 |
+
gr.Info("產製圖表完成!")
|
357 |
+
return temp_file_path, result, gr.update(visible=True)
|
358 |
+
except Exception as e:
|
359 |
+
return None, f"<p>Error:{str(e)}</p>", gr.update(visible=True)
|
360 |
+
|
361 |
+
with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
|
362 |
+
gr.Markdown("""
|
363 |
+
# 🐹 動物生命週期圖表 - 財政部財政資訊中心 🐹
|
364 |
+
> ### **※ 玩轉文字魅力,使用開源小模型,刻劃動物的成長歷程。系統部署:江信宗,LLM:Llama-3.1-70B。**
|
365 |
+
""", elem_classes="center-aligned")
|
366 |
+
with gr.Row():
|
367 |
+
input = gr.Textbox(label="請輸入動物名稱", placeholder="Enter animal name", elem_classes="file-background")
|
368 |
+
api_key_input = gr.Textbox(type="password", label="請輸入您的 API Key", placeholder="API authentication key", elem_classes="api-background")
|
369 |
+
update_button = gr.Button("產製圖表", elem_id="submit-btn")
|
370 |
+
file_output = gr.File(label="下載HTML文件", elem_classes="script-background")
|
371 |
+
output = gr.HTML(label="動物生命週期圖表", elem_classes="text-background", visible=False) # Set initial visibility to False
|
372 |
+
update_button.click(fn=generate_chart, inputs=[input, api_key_input], outputs=[file_output, output, output]) # Add output to update visibility
|
373 |
+
|
374 |
+
if __name__ == "__main__":
|
375 |
+
if "SPACE_ID" in os.environ:
|
376 |
+
iface.launch()
|
377 |
+
else:
|
378 |
+
iface.launch(share=True, show_api=False)
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
openai
|
3 |
+
resend
|