目录
1. data load & document process
任务:创建一个带有记忆和工具调用功能的医疗助手系统。由于原课程中使用到openai,我们绕开其中涉及的权限问题,使用替代方法和替代模型来实现这个 agent 系统。
1. data load & document process
data = load_dataset("keivalya/MedQuad-MedicalQnADataset", split='train')
data = data.to_pandas()
data = data[0:300]
df_loader = DataFrameLoader(data, page_content_column="Answer")
df_document = df_loader.load()
text_splitter = CharacterTextSplitter(
chunk_size=1000,
separator="\n",
chunk_overlap=150
)
texts = text_splitter.split_documents(df_document)
2. vector embedding
嵌入模型
embedding_model = HuggingFaceEmbeddings(
model_name="thenlper/gte-small",
model_kwargs={"device": "cuda"},
encode_kwargs={"normalize_embeddings": True}
)
CHROMA_DIR = "./chromadb"
chroma_db = Chroma.from_documents(
documents=texts,
embedding=embedding_model,
persist_directory=CHROMA_DIR
)
3. LLM
生成模型
model_name = "HuggingFaceH4/zephyr-7b-beta" # 通用对话模型
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16
)
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=256,
do_sample=True,
temperature=0.7,
top_p=0.95,
repetition_penalty=1.15
)
llm = HuggingFacePipeline(pipeline=pipe)
4. memory system
conversational_memory = ConversationBufferWindowMemory(
memory_key='chat_history', ## 在后续流程中通过此键名访问历史
k=4, ## 只保留最近的4轮对话(滑动窗口机制)
return_messages=True ## 以结构化消息格式(非纯文本)存储对话
)
对话记忆组件 (ConversationBufferWindowMemory) :
存储对话历史,使 Agent 能记住上下文
5. RAG system
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", ## 将全部检索结果直接注入LLM上下文
retriever=chroma_db.as_retriever()
)
创建了一个基于检索的问答(Retrieval Augmented Generation, RAG)系统。
通过向量数据库(ChromaDB)查询医疗知识,流程:接收问题 → 从ChromaDB中检索相关医学资料 → 使用 LLM 生成基于检索结果的答案。
6. agent system
(1)Tool:定义了一个工具列表
tools = [
Tool(
name='Medical Knowledge Base', ## 工具的名称
func=qa.run, ## 调用该工具时,将执行qa.run方法
description=( ## 描述该工具的用途,用于agent决定何时调用该工具
"""use this tool when answering medical knowledge queries to get
more information about the topic"""
)
)
]
(2) create_react_agent:创建agent
"hwchase17/react-chat" 模板是为对话场景优化的增强版本,虽然更适合 openai 的 chat 模型,但其适应性较强。
agent = create_react_agent(
tools=tools,
llm=llm,
prompt=hub.pull("hwchase17/react-chat")
)
另外地,我们还尝试自定义 prompt 模板:
custom_react_prompt = PromptTemplate(
input_variables=["input", "tool_names", "tools", "agent_scratchpad", "chat_history"],
template="""You are a medical assistant with access to specialized tools.
### Patient History
{chat_history}
### Available Tools
Tool Names: {tool_names}
Tool Descriptions: {tools}
### Current Patient Query
{input}
### Reasoning Process
{agent_scratchpad}
### Response Requirements
- MUST begin with "Final Answer:"
- Include key findings summary if tools were used
- Provide clear patient instructions
- Include medical disclaimer"""
)
agent = create_react_agent(
tools=tools,
llm=llm,
prompt=custom_react_prompt
)
input_variables:定义模板中需要填充的变量名称列表
变量 | 提供者 | 功能 |
input | 用户 | 当前用户的查询 |
tool_names | LangChain | 可用工具名称列表 |
tools | LangChain | 工具详细描述 |
agent_scratchpad | Agent | agent 思考过程记录 |
chat_history | Memory | 对话历史上下文 |
(3)AgentExecutor:包装 agent,负责实际执行 agent 的每一步
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, ## 开启详细日志,便于调试和观察执行过程
memory=conversational_memory, ## 传入之前创建的对话,保留记忆
max_iterations=30, ## 最多执行30步(包括思考、调用工具等)
max_execution_time=600, ## 设置最大执行时间为600秒
handle_parsing_errors=True ## 当解析代理输出(如解析工具调用参数)出错时,允许处理错误,而不是直接抛出异常终止。
)
(4)全流程:
7. test & results
query1 = {"input": """I have a patient that can have Botulism, how can I confirm the diagnosis?"""}
response1 = agent_executor.invoke(query1)
print(f"response1: {response1['output']}")
query2 = {"input": "Is this an important illness?"}
response2 = agent_executor.invoke(query2)
print(f"response2: {response2['output']}")
输出:回答的结果看起来效果还是不错的ヾ(o◕∀◕)ノヾ
(1)prompt - hwchase17/react-chat
(2)prompt - 自定义