▍程式碼
<!-- history_analysis.html -->
<!-- 題目詳情 -->
<div>
...
<div class="modal-body">
<!-- AI 助教輔助按鈕 -->
<div>
<button type="button" id="llm-explain-btn">
呼叫 AI 助教解釋此題
</button>
</div>
...
<!-- AI 助教回答 -->
<div id="explanation">
<pid="explanation-text">AI 助教正在思考...</p>
</div>
...
</div>
<script>
# 呼叫 AI 助教
$('#explain-btn').on('click', async function() {
const btn = $(this);
const questionText = btn.attr('data-question-text');
const userNotes = $('#modal-user-notes').val();
const explanationDiv = $('#explanation');
const explanationText = $('#explanation-text');
if (!questionText) {
explanationText.text('錯誤:無法獲取題目內容。');
explanationDiv.removeClass('d-none').addClass('bg-danger text-white');
return;
}
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> AI 正在分析...');
explanationText.text('AI 助教正在分析題目與數據,請稍候...');
explanationDiv.removeClass('d-none bg-danger text-white').addClass('bg-info text-dark');
explanationDiv.css('border-left-color', '#007bff');
const payload = {
question_text: questionText,
user_notes: userNotes // 傳筆記給後端
};
try {
console.log(`[DEBUG] 呼叫 Mistral API: ${mistralApiUrl}`);
// 用 ajax 呼叫後端
const response = await $.ajax({
url: '/api/mistral_explain',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(payload)
});
const text = response.explanation;
if (text) {
explanationText.html(text.replace(/\n/g, '<br>'));
explanationDiv.removeClass('bg-info text-dark').addClass('bg-light text-dark').css('border-left-color', '#198754');
} else {
explanationText.text('AI 助教無法生成解釋,後端回傳內容為空。');
explanationDiv.removeClass('bg-info text-dark').addClass('bg-danger text-white').css('border-left-color', '#dc3545');
}
} catch (jqXHR) {
const errorMsg = jqXHR.responseJSON ? (jqXHR.responseJSON.error || JSON.stringify(jqXHR.responseJSON)) : '未知錯誤';
console.error('Mistral API 呼叫失敗:', errorMsg);
explanationText.text('AI 助教服務連線失敗:' + errorMsg);
explanationDiv.removeClass('bg-info text-dark').addClass('bg-danger text-white').css('border-left-color', '#dc3545');
} finally {
btn.prop('disabled', false).html('✨ 呼叫 AI 助教解釋此題');
}
});
</script>
# views.py
# 初始化 Mistral client
try:
MISTRAL_CLIENT = Mistral(api_key=" your api key here")
MISTRAL_MODEL = "mistral-large-latest"
print("Mistral Client initialized successfully.")
except Exception as e:
print(f"Mistral client initialization failed: {e}")
MISTRAL_CLIENT = None
@app.route('/api/mistral_explain', methods=['POST'])
def mistral_explain():
"""使用 Mistral LLM 針對指定題目和筆記內容進行解釋或擴展。"""
if not MISTRAL_CLIENT:
return jsonify({'error': 'Mistral 客戶端未初始化。請檢查 API Key 配置。'}), 500
try:
data = request.get_json()
question_text = data.get('question_text', '')
user_notes = data.get('user_notes', '')
if not question_text:
return jsonify({'error': '缺少題目內容。'}), 400
system_prompt = "你是一位專精於醫學資訊管理學的教學助理。請以清晰、專業且易懂的方式,針對用戶提供的題目或筆記內容進行分析、解釋或知識擴展。"
user_query = f"請詳細解釋以下醫學資訊管理學題目所涉及的知識、原理:\n\n題目: {question_text}"
if user_notes:
user_query += f"\n\n請考慮用戶的以下筆記,並提供進一步的補充或糾正。用戶筆記: {user_notes}"
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query}
]
# 呼叫 Mistral API
response = MISTRAL_CLIENT.chat(
model=MISTRAL_MODEL,
messages=messages,
)
explanation_text = response.choices[0].message.content
return jsonify({'explanation': explanation_text})
except Exception as e:
print(f"Mistral API 呼叫失敗: {e}")
return jsonify({'error': f'Mistral API 呼叫失敗: {e}'}), 500