import plotly.express as px import pandas as pd import gradio as gr import openai # 課程資料 course_dict = { "基礎必修": [ {"科目": "統計學", "學分": 3, "課程": ["統計學", "初級統計", "教育統計", "體育統計學", "生物統計學", "數理統計", "機率與統計"]}, {"科目": "資料庫系統", "學分": 3, "課程": ["資料庫系統", "資料庫管理系統", "資料庫"]}, {"科目": "資料探勘", "學分": 3, "課程": ["資料探勘", "人工智慧", "資料結構", "教育資料科學概論", "大數據分析", "深度學習", "機器學習", "演算法", "資料視覺化"]} ], "核心選修": [ {"科目": "研究方法", "學分": 3, "課程": ["研究方法", "教育研究法", "社會科學研究法", "科學教育研究法", "量化研究"]}, {"科目": "高等統計學", "學分": 3, "課程": ["高等教育統計", "高等體育統計學"]}, {"科目": "多變量分析", "學分": 3, "課程": ["多變量分析"]}, {"科目": "程式設計", "學分": 3, "課程": ["程式設計", "基礎程式設計", "計算機程式設計", "網路程式設計", "物件導向程式設計", "視窗程式設計", "行動程式設計", "網頁程式設計", "遊戲程式設計", "資料科學程式設計", "視覺化程式設計語言"]}, {"科目": "前端工程設計", "學分": 3, "課程": ["前端工程設計", "網頁設計與製作", "網頁設計", "網站建置與管理", "跨平台前端工程設計"]}, {"科目": "使用者經驗設計", "學分": 3, "課程": ["使用者經驗設計", "設計方法", "視覺傳達設計", "電腦多媒體理論與實務", "混合實境科技", "人機介面設計與製作"]}, {"科目": "專題研究", "學分": 2, "課程": ["智慧型科技專題", "資訊科技專題", "資料探勘專題研究", "人工智慧案例討論", "大數據分析案例討論"]} ] } # 將資料轉換為平坦的 DataFrame def create_dataframe(course_dict): data = [] for category, subjects in course_dict.items(): for subject in subjects: for course in subject["課程"]: data.append({ "類別": category, "科目": subject["科目"], "課程": course }) return pd.DataFrame(data) df = create_dataframe(course_dict) # 創建樹狀圖函數 def create_sunburst_chart(df): fig = px.sunburst( df, path=['類別', '科目', '課程'], title="課程結構互動圖", color='類別', color_discrete_sequence=px.colors.qualitative.Pastel ) # 自訂 hovertemplate,不顯示學分 fig.update_traces( hovertemplate="%{label}
" ) # 更新圖表佈局 fig.update_layout( margin=dict(t=50, l=25, r=25, b=25) ) return fig # 生成初始樹狀圖 initial_fig = create_sunburst_chart(df) # 課程推薦函數 def recommend_courses(learning_background, difficulty, preferred_course, question_type, possible_career_paths, api_key): openai.api_key = api_key try: # 使用 OpenAI API 生成建議,符合新版 API 介面 completion = openai.chat.completions.create( model="gpt-4o", messages=[ {"role": "system", "content": "你是一位資深的教育顧問,負責為學生提供個性化的學習建議,請以純文字格式回答,不要包含 Markdown 語法。"}, { "role": "user", "content": f"""請確保不要以Markdown語法回覆, 根據以下課程資料:{course_dict}, 學習背景為{learning_background}, 難度為{difficulty}, 最感興趣的課程名稱為{preferred_course}, 偏好教學方式為{question_type}, 未來可能從事的職業或研究方向為{possible_career_paths}, 請根據課程資料、學習背景、難度、最感興趣的課程、偏好教學方式、未來可能從事的職業或研究方向推薦所需修的科目, 請推薦至少9學分的基礎必修科目和至少8學分的核心選修科目, 並依照科目推薦對應的2-3個課程, 請確保至少9學分的基礎必修科目, 並確保至少8學分的核心選修科目與總科目學分不少於17學分, 並顯示目前所選科目的學分, 並顯示所選科目的學分的加總(包含詳細選擇課程學分的加總過程), 並依照推薦課程提供對應多個學習資源(如網站名稱,不要連結)建議。 請輸出推薦課程的學習路徑,範例:科目→科目→科目, 詳細分析此學習路徑原因, 請以純文字格式回答,不要包含 Markdown 語法。""" } ] ) recommendation = completion.choices[0].message.content # 返回推薦結果,不更新圖表 return recommendation except Exception as e: return f"錯誤發生:{str(e)}。請檢查 API Key 是否正確或稍後再試。" # Gradio 表單設計 with gr.Blocks() as demo: gr.Markdown("# 個人化課程學習建議") with gr.Row(): # 左側欄:課程結構與學分分佈樹狀圖 with gr.Column(scale=1): sunburst_output = gr.Plot(value=initial_fig, label="課程結構互動圖") # 中間欄:課程推薦表單 with gr.Column(scale=1): with gr.Row(): # 學習背景(複選) learning_background = gr.CheckboxGroup( choices=[ "無資訊技術背景", "相關資訊課經驗", "資訊本科生", "軟體開發經驗", "網頁設計經驗", "數據分析經驗" ], label="學習背景" ) with gr.Row(): # 難度區 difficulty = gr.Dropdown(["基礎", "進階", "專業"], label="偏好難度") # 偏好教學方式 question_type = gr.Dropdown( ["理論講解", "案例分析", "實作練習", "專題研究"], label="偏好教學方式" ) with gr.Row(): # 課程 preferred_course = gr.Dropdown( ["程式設計", "統計", "資料庫", "專題研究", "人機介面設計與製作", "網頁設計"], label="最感興趣的課程名稱" ) # 未來可能從事的職業或研究方向 possible_career_paths = gr.Dropdown( ["資料科學家", "機器學習工程師", "前端設計師", "後端軟體工程師"], label="可能從事的職業或研究方向" ) with gr.Row(): # API Key 輸入 api_key = gr.Textbox(label="生成金鑰(API Key)", type="password") # 提交按鈕 submit = gr.Button("提交") # 右側欄:課程推薦輸出 with gr.Column(scale=1): # 課程推薦輸出 output = gr.Textbox(label="課程推薦", lines=24) # 將提交按鈕與輸出連接 submit.click( recommend_courses, inputs=[learning_background, difficulty, preferred_course, question_type, possible_career_paths, api_key], outputs=output ) # 啟動 Gradio 的應用 demo.launch()