# 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)
```