### [AI / ML領域相關學習筆記入口頁面](https://hackmd.io/@YungHuiHsu/BySsb5dfp)
#### [Deeplearning.ai GenAI/LLM系列課程筆記](https://learn.deeplearning.ai/)
##### GenAI
- [Large Language Models with Semantic Search。大型語言模型與語義搜索 ](https://hackmd.io/@YungHuiHsu/rku-vjhZT)
- [LangChain for LLM Application Development。使用LangChain進行LLM應用開發](https://hackmd.io/1r4pzdfFRwOIRrhtF9iFKQ)
- [Finetuning Large Language Models。微調大型語言模型](https://hackmd.io/@YungHuiHsu/HJ6AT8XG6)
##### RAG
- [Preprocessing Unstructured Data for LLM Applications。大型語言模型(LLM)應用的非結構化資料前處理](https://hackmd.io/@YungHuiHsu/BJDAbgpgR)
- [Building and Evaluating Advanced RAG。建立與評估進階RAG](https://hackmd.io/@YungHuiHsu/rkqGpCDca)
- [[GenAI][RAG] Multi-Modal Retrieval-Augmented Generation and Evaluaion。多模態的RAG與評估
](https://hackmd.io/@YungHuiHsu/B1LJcOlfA)
##### AI Agents
原理可參考這篇綜論: [How Agents for LLM Perform Task Planning。大型語言模型的代理如何進行任務規劃](https://hackmd.io/@YungHuiHsu/rkK52BkQp)
- 相關framework選擇
- [AI Agents in LangGraph](https://hackmd.io/@YungHuiHsu/BJTKpkEHC)
- [Building Agentic RAG with LlamaIndex](https://learn.deeplearning.ai/courses/building-agentic-rag-with-llamaindex/lesson/1/introduction)
- [Multi AI Agent Systems with crewAI](https://learn.deeplearning.ai/courses/multi-ai-agent-systems-with-crewai/lesson/1/introduction)
- [Functions, Tools and Agents with LangChain](https://learn.deeplearning.ai/courses/functions-tools-agents-langchain/lesson/1/introduction)
- Agent相關
- [Long-Term Agentic Memory With LangGraph](https://hackmd.io/@YungHuiHsu/S1f1cyOnke)
---
---
# [Long-Term Agentic Memory With LangGraph](https://learn.deeplearning.ai/courses/long-term-agentic-memory-with-langgraph/lesson/ovv0p/introduction?courseName=long-term-agentic-memory-with-langgraph)
* [Introduction to Agent Memory](https://hackmd.io/@YungHuiHsu/S1f1cyOnke)
* [Baseline Email Assistant、Email Assistant with Semantic Memory](https://hackmd.io/@YungHuiHsu/ryOkald2kl)
* [Email Assistant with Semantic + Episodic Memory](https://hackmd.io/@YungHuiHsu/r15H8kQTkx)
* [Email Assistant with Semantic + Episodic + Procedural Memory](https://hackmd.io/@YungHuiHsu/ByDawymp1e)
---
## [LangGraph官網對Semantic Memory的介紹](https://langchain-ai.github.io/langgraph/concepts/memory/?ref=blog.langchain.dev#semantic-memory)
:::info
🧠 語意記憶(Semantic Memory)
**語意記憶**,在人類與 AI agent 中,指的是對特定事實與概念的長期記憶。
在人類身上,這可能包括在學校學到的知識、概念間的關聯等。而對於 AI agent 而言,語意記憶常用於**個人化應用**,例如記住使用者過去提供的事實或偏好,以便產生更相關的回應。
> 🔸 **注意**:不要把語意記憶(semantic memory)與「語意搜尋(semantic search)」混淆。
> - 語意記憶是心理學術語,指儲存知識與事實。
> - 語意搜尋則是一種透過「語意(意義)」找出相似內容的技術,常基於嵌入向量(embeddings)。
:::
- 語意記憶(Semantic Memory)建議的資料儲存結構
| 模式 | 👤 Profile 模式 | 📄 Collection 模式 |
|------|------------------|----------------------|
| 圖示 |  |  |
| 概念 | 一份持續更新的 JSON 文件,描述使用者或實體的屬性 | 多份小型文件,每筆文件代表一個具體記憶片段 |
| 儲存格式 | 單一 Profile(如 JSON)<br>```{"name": "Alex", "language_preference": "Traditional Chinese"}``` | 多個記憶文件,獨立產生與擴充 |
| 優點 | - 結構完整<br>- 易於掌握全貌 | - 易於更新<br>- 範圍小,產生簡單<br>- 對於新知識 的「召回率(recall)較高 |
| 更新方式 | - 傳入舊 profile<br>- 模型輸出新 profile 或 JSON Patch | - 模型新增、刪除、更新文件 |
| 挑戰 | - Profile 越大越難維護<br>- 結構易錯<br>- 需 schema 驗證 | - 需處理去重/合併問題<br>- 記憶查找成本高<br>- 缺乏整體脈絡 |
| 適用工具 | JSON schema validation | Trustcall、LangSmith |
---
## 範例: Baseline Email Assistant
先建立基本的 Email Assistant架構,紅、綠、藍色的字體代表Memory的額外設計。


```python!
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
from typing import Literal
from IPython.display import Image, display
email_agent = StateGraph(State)
email_agent = email_agent.add_node(triage_router)
email_agent = email_agent.add_node("response_agent", agent)
email_agent = email_agent.add_edge(START, "triage_router")
email_agent = email_agent.compile()
```
```mermaid
graph TD
A[Start] --> B[Triage_Router Agent]
B -->|IGNORE| E[End]
B -->|NOTIFY| E
B -->|RESPOND| C[Response Agent]
%% Triage Router Prompt Integration
K((Triage Prompt)) --> B
M[triage_system_prompt] --> K
N[triage_user_prompt] --> K
subgraph Response_Agent
C --> D[Agent Tools]
D --> F[Write Email]
D --> G[Schedule Meeting]
D --> H[Check Calendar]
end
C --> E[End]
%% Prompt 說明
B:::agent
C:::agent
K:::prompt
%% Style Definitions
classDef agent fill:#FFD700,stroke:#333,stroke-width:2px
classDef prompt fill: #e6e6e6,stroke:#333,stroke-width:2px
classDef tool fill:#87CEEB,stroke:#333,stroke-width:2px
%% Apply Classes
B:::agent
C:::agent
K:::prompt
M:::prompt
N:::prompt
%% Apply subgraph styles
style Response_Agent fill:transparent,stroke:#333,stroke-width:2px
```
### Define the first part of the agent - triage.
根據 `Lesson 2_Baseline Email Assistant.ipynb` 中的段落 `## Define the first part of the agent - triage.`,以下是詳細的執行流程和參數的 mermaid 流程圖:
#### `triage_router`
```python
def triage_router(state: State) -> Command[
Literal["response_agent", "__end__"]
]:
author = state['email_input']['author']
to = state['email_input']['to']
subject = state['email_input']['subject']
email_thread = state['email_input']['email_thread']
system_prompt = triage_system_prompt.format(
full_name=profile["full_name"],
name=profile["name"],
user_profile_background=profile["user_profile_background"],
triage_no=prompt_instructions["triage_rules"]["ignore"],
triage_notify=prompt_instructions["triage_rules"]["notify"],
triage_email=prompt_instructions["triage_rules"]["respond"],
examples=None
)
user_prompt = triage_user_prompt.format(
author=author,
to=to,
subject=subject,
email_thread=email_thread
)
result = llm_router.invoke(
[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
]
)
if result.classification == "respond":
print("📧 Classification: RESPOND - This email requires a response")
goto = "response_agent"
update = {
"messages": [
{
"role": "user",
"content": f"Respond to the email {state['email_input']}",
}
]
}
elif result.classification == "ignore":
print("🚫 Classification: IGNORE - This email can be safely ignored")
update = None
goto = END
elif result.classification == "notify":
# If real life, this would do something else
print("🔔 Classification: NOTIFY - This email contains important information")
update = None
goto = END
else:
raise ValueError(f"Invalid classification: {result.classification}")
return Command(goto=goto, update=update)
```
- `triage_router` 的詳細工作流程:
1. **Start**: 開始處理電子郵件。
2. **Extract Email Details**: 提取電子郵件的詳細信息,包括作者、收件人、主題和郵件內容。
3. **Format System Prompt**: 格式化系統提示,填充用戶的詳細信息和分類規則。
4. **Format User Prompt**: 格式化用戶提示,填充郵件的詳細信息。
5. **Invoke LLM Router**: 調用 LLM 路由器,傳遞系統提示和用戶提示。
6. **Classification Result**: 根據 LLM 路由器的結果進行分類。
- **Respond**: 如果分類為回應,則生成回應內容,更新消息並轉到回應代理。
- **Ignore**: 如果分類為忽略,忽略消息並結束流程。
- **Notify**: 如果分類為通知,通知消息並結束流程。
7. **End**: 結束流程。
### Main agent, define tools
根據程式碼段落 `## Main agent, define tools`,以下是詳細的執行流程和參數的 mermaid 流程圖:
```python
@tool
def write_email(to: str, subject: str, content: str) -> str:
"""Write and send an email."""
# 實際應用中會真的發送郵件
return f"Email sent to {to} with subject '{subject}'"
@tool
def schedule_meeting(attendees: list[str], subject: str, duration_minutes: int, preferred_day: str) -> str:
"""Schedule a calendar meeting."""
# 實際應用中會確認行事曆並安排會議
return f"Meeting '{subject}' scheduled for {preferred_day} with {len(attendees)} attendees"
@tool
def check_calendar_availability(day: str) -> str:
"""Check calendar availability for a given day."""
# 實際應用中會檢查真實的行事曆
return f"Available times on {day}: 9:00 AM, 2:00 PM, 4:00 PM"
```
mermaid 流程圖:
````mermaid
graph TD
A[Define Tools] --> B[Define write_email]
B --> C[Input: to, subject, content]
C --> D[Output: Email sent confirmation]
A --> E[Define schedule_meeting]
E --> F[Input: attendees, subject, duration_minutes, preferred_day]
F --> G[Output: Meeting scheduled confirmation]
A --> H[Define check_calendar_availability]
H --> I[Input: day]
I --> J[Output: Available times]
classDef startEnd fill:#f9f,stroke:#333,stroke-width:2px;
classDef process fill:#bbf,stroke:#333,stroke-width:2px;
class A startEnd;
class B,E,H process;
class C,F,I process;
class D,G,J process;
````
#### Main agent, define tools` 的詳細執行流程和參數:
1. **Define Tools**: 定義工具。
2. **Define write_email**: 定義 `write_email` 工具。
- **Input**: 接受 `to`(收件人)、`subject`(主題)和 `content`(內容)作為輸入參數。
- **Output**: 返回郵件發送確認信息。
3. **Define schedule_meeting**: 定義 `schedule_meeting` 工具。
- **Input**: 接受 `attendees`(參加者列表)、`subject`(主題)、`duration_minutes`(持續時間)和 `preferred_day`(首選日期)作為輸入參數。
- **Output**: 返回會議安排確認信息。
4. **Define check_calendar_availability**: 定義 `check_calendar_availability` 工具。
- **Input**: 接受 `day`(日期)作為輸入參數。
- **Output**: 返回可用時間信息。
### prompts
| Prompt 名稱 | 差異 | 輸入 | 輸出 |
|-------------|------|------|------|
| `agent_system_prompt` | 基本代理提示,包含基本工具 | `{full_name}`, `{name}`, `{instructions}` | 格式化的系統提示 ||
| `triage_system_prompt` | 分類郵件的提示,包含分類規則 | `{full_name}`, `{name}`, `{user_profile_background}`, `{triage_no}`, `{triage_notify}`, `{triage_email}`, `{examples}` | 格式化的系統提示,包含分類規則和示例 |
| `triage_user_prompt` | 用戶提示,用於分類郵件 | `{author}`, `{to}`, `{subject}`, `{email_thread}` | 格式化的用戶提示,包含郵件詳細信息 |
---
## Email Assistant with Semantic Memory課程範例
:::success
Semantic Memory實作:在Response
Agent內加入事實/語意記憶的管理與查找功能(as tool),可以將使用者輪廓資料作為Prompt的一部分
:::
在Response_Agent中加入`manage_memory_tool` 與`create_manage_memory_tool`
```PYTHON!
tools= [
write_email,
schedule_meeting,
check_calendar_availability,
manage_memory_tool, # 新增記憶管理工具
search_memory_tool # 新增記憶搜尋工具
]
```
```mermaid
graph TD
A[Start] --> B[Triage_Router Agent]
B -->|IGNORE| E[End]
B -->|NOTIFY| E
B -->|RESPOND| C[Response Agent]
%% Triage Router Memory and Prompt Integration
K((Triage Prompt)) --> B
M[triage_system_prompt] --> K
N[triage_user_prompt] --> K
subgraph Response_Agent
C --> D[Agent Tools]
D --> F[Origin Tools]:::tool
subgraph Semantic_Memory_as_Tools[Semantic Memory_as_Tools ]
I[manage_memory]:::tool
J[search_memory]:::tool
end
D --> Semantic_Memory_as_Tools
end
%% Style Definitions
classDef agent fill:#FFD700,stroke:#333,stroke-width:2px
classDef prompt fill: #e6e6e6,stroke:#333,stroke-width:2px
classDef tool fill:#87CEEB,stroke:#333,stroke-width:2px
classDef storage fill:#FFFFFF,stroke:#333,stroke-width:2px
classDef memory fill:#FFEFD5,stroke:#333,stroke-width:2px
classDef semantic color:#000080,stroke:#333,stroke-width:2px
classDef episodic color:#006400,stroke:#333,stroke-width:2px
classDef subgraphStyle fill:#E8F5E9,stroke:#333,stroke-width:2px
%% Apply Classes
B:::agent
C:::agent
K:::prompt
M:::prompt
N:::prompt
%% Apply subgraph styles
style Semantic_Memory_as_Tools fill:#E8F5E9,stroke:#333,stroke-width:2px
style Response_Agent fill:transparent,stroke:#333,stroke-width:2px
```
### `langmem`的`create_manage_memory_tool()` 與 `create_search_memory_tool()`
#### 🔹 **`manage_memory_tool()`**
- 🔧 功能
此工具的目的是**將使用者的行為、互動、指示等資訊儲存在記憶系統中**,使 Email Assistant 在未來的互動中可以參考這些記憶來提供更個人化的回應。
```python
from langmem import create_manage_memory_tool, \
create_search_memory_tool
manage_memory_tool = create_manage_memory_tool(
namespace=(
"email_assistant",
"{langgraph_user_id}",
"collection"
)
)
```
---
#### 🔹 **`create_search_memory_tool()`**
- 🔧 功能
此工具的目的是**在記憶系統中搜尋與過往互動、郵件或行為相關的資料**,幫助 Email Assistant 根據過去的資訊提供更智慧的回應。
```python=
search_memory_tool = create_search_memory_tool(
namespace=(
"email_assistant",
"{langgraph_user_id}",
"collection"
)
)
```
| 功能/特性 | `manage_memory_tool()` | `search_memory_tool()` |
|---------------------------|----------------------------------|----------------------------------|
| **目的** | 儲存使用者資訊、行為或指示 | 搜尋使用者過去的資訊 |
| **輸入參數 (Parameters)** | `memory_type`, `user`, `data_type`, `content` | `memory_type`, `user`, `data_type`, `query` |
| **輸出 (Output)** | 儲存成功訊息或錯誤提示 | 搜尋結果或「無結果」提示 |
| **應用場景 (Use Case)** | 儲存指示、行為偏好、個人化資訊 | 檢索過往郵件、過往指示或互動記錄 |
#### 在`response_agent`中加入memory tool
- 要注意的是`memory_tool`還是需要透過`InMemoryStore` 將儲存的記憶pass給agent
```python=
from langgraph.store.memory import InMemoryStore
store = InMemoryStore(
index={"embed": "openai:text-embedding-3-small"}
)
tools= [
write_email,
schedule_meeting,
check_calendar_availability,
manage_memory_tool,
search_memory_tool
]
response_agent = create_react_agent(
"anthropic:claude-3-5-sonnet-latest",
tools=tools,
prompt=create_prompt,
# Use this to ensure the store is passed to the agent
store=store
)
```
---
### `agent_system_prompt` 與 `agent_system_prompt_memory` 的差異
```PYTHON=
# Agent prompt baseline
agent_system_prompt = """
< Role >
You are {full_name}'s executive assistant. You are a top-notch executive assistant who cares about {name} performing as well as possible.
</ Role >
< Instructions >
{instructions}
</ Instructions >
"""
# Agent prompt semantic memory
agent_system_prompt_memory = """
...
< Tools >
...
4. manage_memory("email_assistant", user, "collection") - Store any relevant information about contacts, actions, discussion, etc. in memory for future reference
5. manage_memory("email_assistant", user, "user_profile") - Store any relevant information about the recipient, {name}, in the user profile for future reference the current user profile is shown below
6. search_memory("email_assistant", user, "collection") - Search memory for detail from previous emails
7. manage_memory("email_assistant", user, "instructions") - Update the instructions for agent tool usage based upon the user feedback
</ Tools >
...
```
| 特點/功能 | `agent_system_prompt` | `agent_system_prompt_memory` |
|----------------------------------------|----------------------------------------------|--------------------------------------------------|
| **額外工具 (Memory Tools)** | ❌ 無額外的記憶管理工具。 | ✅ 4 個額外工具:<br>4. `manage_memory("collection")`<br>5. `manage_memory("user_profile")`<br>6. `search_memory("collection")`<br>7. `manage_memory("instructions")` |
| **使用者檔案 (User Profile)** | ❌ 未包含 `profile` (用戶偏好、背景等個人化資訊)。 | ✅ 包含 `profile`,用於儲存使用者的背景、喜好與行為資訊。 |
---