File size: 2,885 Bytes
9aa8153
c6a7d30
9aa8153
 
 
c6a7d30
9aa8153
 
 
 
c6a7d30
9aa8153
 
c6a7d30
9aa8153
 
 
c6a7d30
9aa8153
 
c6a7d30
9aa8153
c6a7d30
9aa8153
 
c6a7d30
9aa8153
c6a7d30
9aa8153
 
c6a7d30
 
9aa8153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import os
import gradio as gr
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from openai import OpenAI

class CustomE5Embedding(HuggingFaceEmbeddings):
    def embed_documents(self, texts):
        texts = [f"passage: {t}" for t in texts]
        return super().embed_documents(texts)

    def embed_query(self, text):
        return super().embed_query(f"query: {text}")

embedding_model = CustomE5Embedding(model_name="intfloat/multilingual-e5-small")
db = FAISS.load_local("faiss_db", embedding_model, allow_dangerous_deserialization=True)
retriever = db.as_retriever(search_kwargs={"k": 20})

client = OpenAI()
model = "gpt-4o"

system_prompt = "你是清華大學校園資訊助理 AI,專門解答與課程、社團、場地與設施時段相關的問題。請根據資料內容,以台灣人熟悉的繁體中文提供清楚、簡潔且實用的回應。如無法在資料中找到答案,請誠實說明。"

prompt_template = """以下是關於國立清華大學課程、社團與校內設施的資料片段:
{retrieved_chunks}

使用者的提問是:{question}

請根據提供的內容回答問題,若提到課程請具體指出課程名稱、教師或時間地點;若提到社團或場地,也請回應具體活動內容或使用時段。
如查無相關資訊,請明確告知查無資料。
"""

def chat_with_rag(user_input):
    docs = retriever.get_relevant_documents(user_input)
    retrieved_chunks = "\n\n".join([doc.page_content for doc in docs])
    final_prompt = prompt_template.format(retrieved_chunks=retrieved_chunks, question=user_input)

    response = client.chat.completions.create(
        model=model,
        max_tokens=1000,
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "assistant", "content": f"以下是相關資料片段:\n\n{retrieved_chunks}"},
            {"role": "user", "content": f"問題:{user_input}\n\n請根據資料,詳細列出所有相關內容,包括課程名稱、授課教師、時間地點等,必要時請使用條列式說明。若查無資料,也請清楚說明。"}
        ]
    )
    return response.choices[0].message.content

with gr.Blocks() as demo:
    gr.Markdown("# 🎓 校園資訊查詢小幫手")
    gr.Markdown("請輸入你想詢問的清華大學的問題,包含資工系課程、校園設施、社團,我會根據資料幫你解答 💬")

    chatbot = gr.Chatbot(label="📚 問答紀錄", height=600)
    msg = gr.Textbox(placeholder="例如:大一有哪些必修課?", label="❓ 問題輸入")

    def respond(message, chat_history_local):
        response = chat_with_rag(message)
        chat_history_local.append((message, response))
        return "", chat_history_local

    msg.submit(respond, [msg, chatbot], [msg, chatbot])

demo.launch()