# RAG CRUD & ER Model Design ## 每個實體(教材、考古題、詳解)可以作為一個集合,在Milvus中創建。例如,對於教材: ``` fields = [ {"name": "question_vector", "type": DataType.FLOAT_VECTOR, "params": {"dim": 768}}, {"name": "question_id", "type": DataType.INT64}, {"name": "textbook_id", "type": DataType.INT64} # 關聯到教材的ID ] client.create_collection("ExamQuestion", fields) # 假設每個考古題已轉換為向量 exam_question_vectors = [vector1, vector2] # 這些是問題的向量表示 exam_question_ids = [1, 2] related_textbook_ids = [1, 2] # 每個問題相關的教材ID exam_entities = [ {"name": "question_vector", "values": exam_question_vectors, "type": DataType.FLOAT_VECTOR}, {"name": "question_id", "values": exam_question_ids, "type": DataType.INT64}, {"name": "textbook_id", "values": related_textbook_ids, "type": DataType.INT64} ] client.insert("ExamQuestion", exam_entities) client.flush(["ExamQuestion"]) ``` ## 利用Milvus的搜索功能和metadata,使用考古題的問題ID或文本來查詢相關的教材ID,然後再去教材集合中檢索相應的教材內容: ``` # 假設你已經有一個問題的向量 search_vector = [0.1, 0.2, 0.3] # 這是一個查詢向量 # 在考古題集合中搜索相應的向量 search_params = {"metric_type": "L2", "params": {"nprobe": 10}} results = client.search("ExamQuestion", [search_vector], {"bool": {"must": [{"vector": {"question_vector": {"topk": 1, "query": [search_vector], "metric_type": "L2", "params": {"nprobe": 10}}}}]}}, search_params) # 假設results返回了相關的教材ID related_textbook_id = results[0].id # 取得第一個結果的教材ID # 再次查詢教材集合以獲取詳細信息 textbook_info = client.query("Textbook", ["title", "content"], {"term": {"text_id": related_textbook_id}}) ``` ## 資料結構與關聯設計 我們需要設計一個資料結構,使得教材內容、考古題和詳解之間的關聯性明確,並在檢索和生成答案的過程中有效利用這些關聯。 ### 資料準備 首先,我們需要收集和整理護理醫療教科書的教材內容以及考古題詳解。這些資料可以分為以下幾類: 1. 教科書內容(教材) 2. 考古題問題 3. 考古題詳解 ### 資料結構 ``` 教材 (Textbook) ID: 教材唯一標識符 標題: 教材標題 內容: 教材內容 考古題 (ExamQuestion) ID: 考古題唯一標識符 問題: 考古題問題文本 答案: 考古題答案文本 教材ID: 關聯的教材ID(可選) 詳解 (Explanation) ID: 詳解唯一標識符 考古題ID: 所屬考古題的ID 詳解內容: 詳解的文本內容 ``` 這樣設計的資料結構,使得每個考古題和其詳解可以關聯到相應的教材。 ### 資料欄位描述 教材 (Textbook) ``` [ { "ID": "1", "標題": "護理學概論", "內容": "這是護理學概論的教材內容。" }, { "ID": "2", "標題": "內科護理學", "內容": "這是內科護理學的教材內容。" } // 更多教材資料... ] ``` 考古題 (ExamQuestion) ``` [ { "ID": "1", "問題": "何者不是護理過程的步驟?", "選項": ["評估", "診斷", "計劃", "執行", "制定護理計劃"], "答案": "制定護理計劃", "教材ID": "1" }, { "ID": "2", "問題": "內科護理的主要內容是什麼?", "選項": ["心臟護理", "肺部護理", "腎臟護理", "所有上述"], "答案": "所有上述", "教材ID": "2" } // 更多考古題資料... ] ``` 詳解 (Explanation) ``` [ { "ID": "1", "考古題ID": "1", "詳解內容": "護理過程的步驟包括:評估、診斷、計劃、執行和評值。" }, { "ID": "2", "考古題ID": "2", "詳解內容": "內科護理涉及心臟、肺部和腎臟等多方面的護理。" } // 更多詳解資料... ] ``` ### 資料預處理與向量化 我們需要將這些資料進行預處理,並將其向量化,以便在向量資料庫中儲存和檢索。 ``` from sentence_transformers import SentenceTransformer import pinecone # 初始化向量模型和向量資料庫 model = SentenceTransformer('model_name') pinecone.init(api_key='your_api_key') index = pinecone.Index('your_index') # 假設我們有一些教材資料 textbooks = [ {"ID": "1", "標題": "護理學概論", "內容": "這是護理學概論的教材內容。"}, # 更多教材資料... ] exam_questions = [ {"ID": "1", "問題": "何者不是護理過程的步驟?", "答案": "制定護理計劃", "教材ID": "1"}, # 更多考古題資料... ] explanations = [ {"ID": "1", "考古題ID": "1", "詳解內容": "護理過程的步驟包括:評估、診斷、計劃、執行和評值。"}, # 更多詳解資料... ] # 向量化並儲存教材內容 for textbook in textbooks: embedding = model.encode(textbook['內容']) index.upsert([(textbook['ID'], embedding, textbook)]) # 向量化並儲存考古題問題 for question in exam_questions: embedding = model.encode(question['問題']) index.upsert([(question['ID'], embedding, question)]) # 向量化並儲存詳解內容 for explanation in explanations: embedding = model.encode(explanation['詳解內容']) index.upsert([(explanation['ID'], embedding, explanation)]) ``` ### 檢索與生成答案 在檢索和生成答案的過程中,我們需要利用資料之間的關聯性,來提供更準確的回答。 ``` # 定義檢索和生成答案的函數 def retrieve_and_generate_answer(query): # 向量化查詢 query_embedding = model.encode([query]) # 檢索最相關的考古題和詳解 result = index.query(query_embedding, top_k=5) # 提取檢索結果的內容 context = "" related_textbooks = set() for match in result['matches']: if '考古題ID' in match['metadata']: question = match['metadata']['問題'] explanation = match['metadata']['詳解內容'] context += f"考古題: {question}\n詳解: {explanation}\n" related_textbooks.add(match['metadata']['教材ID']) elif '內容' in match['metadata']: context += match['metadata']['內容'] + "\n" # 提取相關教材內容 for textbook_id in related_textbooks: textbook_result = index.query(model.encode([textbook_id]), top_k=1) context += "相關教材: " + textbook_result['matches'][0]['metadata']['內容'] + "\n" # 生成答案 generated_answer = generate_answer(query, context) return generated_answer # 示例查詢 query = "護理過程的步驟有哪些?" answer = retrieve_and_generate_answer(query) print(answer) ``` ### 模擬考試與行為推論 為了讓 Agent 能夠進行模擬考試並進行行為推論,我們需要進一步細化和模擬考試環境。這包括: 1. 構建考試題庫:將考古題和新增題目進行整理,構建完整的題庫。 ``` exam_questions = [ { "ID": "1", "問題": "何者不是護理過程的步驟?", "選項": ["評估", "診斷", "計劃", "執行", "制定護理計劃"], "正確答案": "制定護理計劃", "詳解": "護理過程的步驟包括:評估、診斷、計劃、執行和評值。" }, # 更多考古題資料... ] ``` 2. 模擬考試過程:設計模擬考試系統,讓 Agent 能夠回答問題並評估其答案。 ``` import random def simulate_exam(agent, exam_questions): score = 0 total_questions = len(exam_questions) for question in exam_questions: print("問題:", question['問題']) if '選項' in question: for i, option in enumerate(question['選項']): print(f"{i+1}. {option}") # 假設 Agent 可以生成答案 answer = agent.answer_question(question['問題']) print("Agent 的回答:", answer) if answer == question['正確答案']: print("回答正確!") score += 1 else: print("回答錯誤。正確答案是:", question['正確答案']) print("詳解:", question['詳解']) print("-" * 50) print(f"模擬考試結束,總分: {score}/{total_questions}") # 假設我們有一個簡單的 Agent 類 class SimpleAgent: def answer_question(self, question): # 這裡用隨機回答來模擬 Agent 的行為 return random.choice(["評估", "診斷", "計劃", "執行", "制定護理計劃"]) agent = SimpleAgent() simulate_exam(agent, exam_questions) ``` 3. 反饋機制:提供反饋機制,讓 Agent 能夠根據答案評價進行學習和改進。 ``` class LearningAgent(SimpleAgent): def __init__(self): self.knowledge_base = {} def learn(self, question_id, correct_answer, explanation): self.knowledge_base[question_id] = { 'correct_answer': correct_answer, 'explanation': explanation } def answer_question(self, question): # 這裡用簡單的知識庫查詢來模擬 Agent 的學習行為 for q_id, knowledge in self.knowledge_base.items(): if knowledge['correct_answer'] in question: return knowledge['correct_answer'] return random.choice(["評估", "診斷", "計劃", "執行", "制定護理計劃"]) def simulate_exam_with_learning(agent, exam_questions): score = 0 total_questions = len(exam_questions) for question in exam_questions: print("問題:", question['問題']) if '選項' in question: for i, option in enumerate(question['選項']): print(f"{i+1}. {option}") answer = agent.answer_question(question['問題']) print("Agent 的回答:", answer) if answer == question['正確答案']: print("回答正確!") score += 1 else: print("回答錯誤。正確答案是:", question['正確答案']) print("詳解:", question['詳解']) print("-" * 50) # Agent 學習反饋 agent.learn(question['ID'], question['正確答案'], question['詳解']) print(f"模擬考試結束,總分: {score}/{total_questions}") learning_agent = LearningAgent() simulate_exam_with_learning(learning_agent, exam_questions) ```