paigent 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ # `.pai` Binary Format Specification v1
2
+
3
+ **PAI(Proactive AI)打包容器格式** — 類比 `.gguf` 之於模型權重,`.pai` 把一個完整的主動式 AI agent 打包成單一可發布、可校驗的二進位檔案。
4
+
5
+ ## 設計目標
6
+
7
+ 1. **單檔發布**:agent 的 manifest、治理政策、觸發器、規則、動作、記憶快照、(選用)嵌入模型權重,全部在一個檔案內。
8
+ 2. **mmap 友善**:所有資料段 64-byte 對齊,大型權重段不壓縮,可直接記憶體映射讀取(與 GGUF 同理)。
9
+ 3. **完整性校驗**:每段附 SHA-256,防損毀與竄改。
10
+ 4. **向前相容**:版本欄位 + 具名段表,新版本可加段而不破壞舊讀取器。
11
+
12
+ ## 二進位佈局(全部 little-endian)
13
+
14
+ ```
15
+ ┌───────────────────────────────────────────────┐
16
+ │ Header (32 bytes) │
17
+ │ magic 4B = "PAI\x01" │
18
+ │ version u32 = 1 │
19
+ │ n_sections u32 │
20
+ │ flags u32 (bit0: 全檔預設 zlib 壓縮) │
21
+ │ created_at u64 (unix epoch 秒) │
22
+ │ reserved 8B │
23
+ ├───────────────────────────────────────────────┤
24
+ │ Section Table (n_sections 筆) │
25
+ │ name_len u16 │
26
+ │ name UTF-8 bytes │
27
+ │ stype u32 (0=json 1=bin 2=sqlite │
28
+ │ 3=text 4=gguf) │
29
+ │ compressed u8 (0/1,每段獨立) │
30
+ │ offset u64 (檔案絕對位移,64B 對齊) │
31
+ │ size u64 (儲存大小=壓縮後) │
32
+ │ raw_size u64 (解壓後大小) │
33
+ │ sha256 32B (解壓後內容雜湊) │
34
+ ├───────────────────────────────────────────────┤
35
+ │ Data Area │
36
+ │ 各段資料,起點 64-byte 對齊,\x00 padding │
37
+ └───────────────────────────────────────────────┘
38
+ ```
39
+
40
+ ## 標準段(section)
41
+
42
+ | 段名 | 必要 | 內容 |
43
+ |---|---|---|
44
+ | `manifest.json` | ✅ | agent 名稱、版本、作者、說明、相容框架版本 |
45
+ | `policy.json` | ✅ | ProactivityPolicy 參數(信心門檻、等級上限、安靜時段、干擾公式參數) |
46
+ | `triggers.json` | ✅ | 觸發器宣告:`[{"type": "threshold", "params": {...}}]` |
47
+ | `rules.json` | ✅ | 宣告式規則:事件條件 → 意圖(action/confidence/urgency/level) |
48
+ | `actions.json` | ✅ | 動作宣告:`{"notify": {"type": "webhook", "url": ...}}` |
49
+ | `brain.json` | 選用 | 決策腦設定(rule/llm、模型名、system prompt、fallback) |
50
+ | `memory.db` | 選用 | SQLite 記憶快照(出廠記憶/個人化狀態隨包攜帶) |
51
+ | `weights.gguf` | 選用 | 嵌入的本地模型權重(不壓縮,可 mmap) |
52
+
53
+ ## 與相關格式的關係
54
+
55
+ | 格式 | 角色 |
56
+ |---|---|
57
+ | `.gguf` | 打包「模型權重」 |
58
+ | `.pai` | 打包「整個主動式 agent」(行為+治理+記憶,可內嵌 .gguf) |
59
+ | `.pai.json` | 單筆 PAI Protocol 行為紀錄(執行期事件,文字 JSON) |
60
+
61
+ ## API
62
+
63
+ ```python
64
+ from pai import pack_agent, load_agent, PaiReader
65
+
66
+ # 打包
67
+ pack_agent("my-agent.pai",
68
+ manifest={"name": "ops-guardian", "version": "1.0.0", "author": "vito1317"},
69
+ policy={...}, triggers=[...], rules=[...], actions={...},
70
+ memory_db="pai_memory.db", # 選用
71
+ weights_path="qwen3-4b-q4.gguf", # 選用
72
+ )
73
+
74
+ # 載入
75
+ agent_def = load_agent("my-agent.pai")
76
+ r = PaiReader("my-agent.pai")
77
+ print(r.info()) # 段表、大小
78
+ data = r.read_bytes("weights.gguf") # 自動 SHA-256 校驗
79
+ ```
80
+
81
+ ---
82
+ Author: vito1317 <service@vito1317.com>
paigent-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vito1317 <service@vito1317.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md FORMAT.md SELF_FINETUNING.md LICENSE
2
+ recursive-include pai *.py py.typed
paigent-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: paigent
3
+ Version: 0.1.0
4
+ Summary: Proactive AI Framework — event-driven, governed proactive agents with a GGUF-like .pai container format and self-finetuning
5
+ Author-email: vito1317 <service@vito1317.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/vito1317/pai-framework
8
+ Project-URL: Repository, https://github.com/vito1317/pai-framework
9
+ Project-URL: Gemma-4 model, https://huggingface.co/vito95311/gemma-guardian-pai
10
+ Project-URL: MiniCPM-o model, https://huggingface.co/vito95311/minicpm-o-guardian-pai
11
+ Keywords: proactive-ai,agent,llm,gguf,pai,self-finetuning,omni,full-duplex
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: local
24
+ Requires-Dist: llama-cpp-python>=0.3.0; extra == "local"
25
+ Provides-Extra: omni
26
+ Requires-Dist: transformers==4.51.0; extra == "omni"
27
+ Requires-Dist: accelerate; extra == "omni"
28
+ Requires-Dist: torch>=2.3.0; extra == "omni"
29
+ Requires-Dist: torchaudio; extra == "omni"
30
+ Provides-Extra: finetune
31
+ Requires-Dist: llamafactory; extra == "finetune"
32
+ Provides-Extra: dev
33
+ Requires-Dist: build; extra == "dev"
34
+ Requires-Dist: twine; extra == "dev"
35
+ Requires-Dist: pytest; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # PAI — Proactive AI Framework(主動式 AI 框架)
39
+
40
+ 一個通用、零依賴(純 Python 標準庫)、可直接運行的主動式 AI 框架原型,並內建 **PAI Protocol v1.1** 標準資料格式。
41
+
42
+ 核心理念:從「被動式 AI(你下指令它才做事)」轉為「事件驅動 + 持續感知 + 受治理的主動行為」。
43
+
44
+ ## 預打包的 .pai agent(Hugging Face)
45
+
46
+ | 模型頁 | 決策腦 | 說明 |
47
+ |---|---|---|
48
+ | [vito95311/gemma-guardian-pai](https://huggingface.co/vito95311/gemma-guardian-pai) | Gemma 4 26B-A4B(QAT q4_0,內嵌 14.4GB GGUF) | 離線 guardian:CPU 監控→清理、新檔案→自動歸檔 |
49
+ | [vito95311/minicpm-o-guardian-pai](https://huggingface.co/vito95311/minicpm-o-guardian-pai) | MiniCPM-o 4.5(全雙工 omni,不內嵌權重) | 即時看+聽、原生主動互動、語音回應 |
50
+
51
+ ## 架構
52
+
53
+ ```
54
+ ┌─ 感知層 Triggers ─────────────────────────────┐
55
+ │ IntervalTrigger / ScheduleTrigger │
56
+ │ FileWatchTrigger / ThresholdTrigger │ → Event(標準事件格式)
57
+ └───────────────────────────────────────────────┘
58
+
59
+ ┌─ 決策層 Brain ────────────────────────────────┐
60
+ │ RuleBrain(規則,離線、零成本、前線哨兵) │
61
+ │ LLMBrain(LLM 判斷,僅在需要時喚醒,失敗退回規則)│ → Intent(action/confidence/urgency/rationale)
62
+ └───────────────────────────────────────────────┘
63
+
64
+ ┌─ 治理層 ProactivityPolicy ────────────────────┐
65
+ │ 1. 信心門檻 2. 動作風險上限 3. 回饋自動降級 │
66
+ │ 4. 安靜時段 5. 干擾度公式 6. 每小時打擾上限 │ → 授予的自主等級
67
+ └───────────────────────────────────────────────┘
68
+
69
+ ┌─ 行動層 Actions ──────────────────────────────┐
70
+ │ OBSERVE 只記錄 │ SUGGEST 通知 │ ASK 確認 │ ACT 自動執行 │
71
+ └───────────────────────────────────────────────┘
72
+
73
+ ┌─ 記憶層 Memory(SQLite)──────────────────────┐
74
+ │ 事件 / 意圖 / 結果 / 回饋 / PAI Protocol 紀錄 │ → 回饋迴圈調節未來主動性
75
+ └───────────────────────────────────────────────┘
76
+ ```
77
+
78
+ ## PAI 干擾度公式
79
+
80
+ ```
81
+ urgency × confidence > interruption_cost 才允許打擾使用者
82
+ ```
83
+
84
+ `interruption_cost_fn` 可依使用者當下狀態(專注模式、開會、深夜)動態回傳 0~1。
85
+
86
+ ## 自主等級 × 交付模式
87
+
88
+ | AutonomyLevel | 行為 | 交付模式 |
89
+ |---|---|---|
90
+ | OBSERVE (0) | 只記錄,不打擾 | level_0_silent |
91
+ | SUGGEST (1) | 主動通知/建議 | level_1_soft_nudge |
92
+ | ASK (2) | 草稿+請求人類授權 | level_2_approval |
93
+ | ACT (3) | 高信心低風險時自動執行 | level_0_silent(事後可查) |
94
+
95
+ 風險高的動作用 `action_max_levels` 鎖死上限(例:寄信最多 ASK,永不自動寄出)。
96
+
97
+ ## PAI Protocol v1.1(標準資料格式)
98
+
99
+ 每次主動行為產生一份 6 層 JSON 紀錄(存入 SQLite,可直接對外交換):
100
+
101
+ ```json
102
+ {
103
+ "pai_protocol_version": "1.1",
104
+ "record_id": "pai_20260611_a1b2c3",
105
+ "timestamp": "2026-06-11T15:39:50Z",
106
+ "1_perception": { "trigger_source": "...", "event_type": "...", "raw_data_summary": {} },
107
+ "2_context": { "user_current_state": "...", "relevant_memory": [], "action_history": [] },
108
+ "3_anticipation": { "predicted_intent": "...", "urgency_score": 0.95, "confidence_score": 0.88,
109
+ "interruption_cost": 0.9, "requested_level": 2, "granted_level": 2 },
110
+ "4_execution": { "actions_taken": [{ "tool": "...", "status": "ok" }], "status": "executed" },
111
+ "5_delivery": { "delivery_mode": "level_2_approval", "requires_human_approval": true },
112
+ "6_adaptation": { "user_feedback": "pending", "learning_adjustment": null }
113
+ }
114
+ ```
115
+
116
+ ## `.pai` 打包格式(類 GGUF 的二進位容器)
117
+
118
+ 整個 agent 可打包成單一 `.pai` 檔案發布(規格見 [FORMAT.md](FORMAT.md)):
119
+ magic `PAI\x01` + 段表(64-byte 對齊、每段 SHA-256 校驗、zlib 壓縮)+ 資料區,
120
+ 可內嵌 `manifest / policy / triggers / rules / actions / brain / memory.db / weights.gguf`。
121
+
122
+ ```python
123
+ from pai import pack_agent, load_agent
124
+ pack_agent("my-agent.pai", manifest={...}, policy={...},
125
+ triggers=[...], rules=[...], actions={...},
126
+ weights_path="model-q4.gguf") # 選用:內嵌本地模型
127
+ agent_def = load_agent("my-agent.pai")
128
+ ```
129
+
130
+ 執行期的單筆行為紀錄則是文字 JSON,附檔名 `.pai.json`。
131
+
132
+ ## 快速開始
133
+
134
+ ```bash
135
+ python3 demo.py # 主動行為迴圈示範(零依賴)
136
+ python3 pack_demo.py # .pai 打包/載入/防竄改示範
137
+ ```
138
+
139
+ demo 模擬三種主動行為:
140
+ 1. CPU 飆高(ThresholdTrigger)→ 高緊急 → **ASK**(確認後清理)
141
+ 2. 待辦堆積(IntervalTrigger)→ 中緊急 → **SUGGEST**(只通知)
142
+ 3. 新檔案出現(FileWatchTrigger)→ 低風險 → **ACT**(自動歸檔)
143
+
144
+ ## 一鍵執行 .pai
145
+
146
+ ```bash
147
+ python3 -m pai info ops-guardian.pai # 查看打包內容
148
+ python3 -m pai run ops-guardian.pai # 載入並運行(未注入的 handler 以 stub 示意)
149
+ ```
150
+
151
+ 程式內載入(注入真實 handler / metric):
152
+
153
+ ```python
154
+ from pai import load_runtime
155
+ agent = load_runtime("ops-guardian.pai",
156
+ handlers={"ops.cleanup": my_cleanup_fn},
157
+ metrics={"cpu": read_cpu_percent})
158
+ agent.run()
159
+ ```
160
+
161
+ ## 底層模型(模型無關,可插拔決策腦)
162
+
163
+ | 決策腦 | 底層模型 | 用途 |
164
+ |---|---|---|
165
+ | `RuleBrain` | 無(純規則) | 前線哨兵、離線運行、LLM 的安全 fallback |
166
+ | `LLMBrain` | 雲端 API(預設 `claude-sonnet-4-6`,可換任何模型) | 開放式判斷 |
167
+ | `LocalLLMBrain` | `.pai` 內嵌 GGUF,經 `llama-cpp-python` | 完全離線、資料不出機 |
168
+ | `LlamaServerBrain` | `.pai` 內嵌 GGUF,經 llama.cpp `llama-server`(支援 `--lora` 熱載入) | 離線、新架構支援最快、常駐免重載 |
169
+ | `MiniCPMoBrain` | **openbmb/MiniCPM-o-4_5**(全雙工 omni:影像+音訊輸入、文字+語音輸出) | 即時看+聽現場、原生主動互動、語音回應 |
170
+
171
+ `brain.json` 的 `engine` 決定用哪個(`llama-server` / `llama-cpp-python` / `minicpm-o`);
172
+ 載入失敗一律自動退回 `RuleBrain`。
173
+
174
+ ### 全雙工語音 / Omni 版本(MiniCPM-o 4.5)
175
+
176
+ MiniCPM-o 4.5(9B,SigLip2 + Whisper + CosyVoice2 + Qwen3-8B)能同時看、聽、說,
177
+ 且**原生支援主動互動**——天然契合 PAI。打包:
178
+
179
+ ```bash
180
+ python3 pack_minicpm_o.py # 預設不內嵌權重,transformers 從 HF 載入
181
+ ```
182
+
183
+ `DuplexOmniLoop` 把模型的全雙工串流(`streaming_prefill`/`streaming_generate`)包成
184
+ 「持續感知 trigger」:模型自己決定何時主動發話,PAI 治理層仍負責是否放行、用什麼等級打擾。
185
+ 微調走 `LlamaFactoryBackend`(包 LLaMA-Factory 做 LoRA),其餘 self-finetuning 編排(EvalGate /
186
+ promote / rollback / 稽核)完全沿用。詳見 `pack_minicpm_o.py` 與 `pai/omni_brain.py`。
187
+
188
+ ## 接上 LLM
189
+
190
+ ```python
191
+ from pai import LLMBrain, RuleBrain
192
+
193
+ brain = LLMBrain(
194
+ available_actions=["cleanup", "archive_file", "__notify__"],
195
+ model="claude-sonnet-4-6", # 需設 ANTHROPIC_API_KEY
196
+ fallback=RuleBrain([...]), # LLM 失敗時退回規則
197
+ user_profile="工程師,上班時間 9-18,討厭被打擾",
198
+ )
199
+ ```
200
+
201
+ 成本控制採「雙層觸發」:RuleBrain 當前線哨兵過濾大多數事件,只有規則判定值得深入時才喚醒 LLM。
202
+
203
+ ## 落地建議
204
+
205
+ 1. **預設 Human-in-the-loop**:初期把所有有副作用的動作上限設為 ASK,跑出信任後再逐步開放 ACT。
206
+ 2. **可撤銷性**:所有自動化動作應提供 Undo(demo 的歸檔動作即可逆)。
207
+ 3. **回饋驅動**:使用者連續拒絕同類建議時,policy 會自動降級該動作(內建)。
208
+
209
+ ---
210
+ Author: vito1317 <service@vito1317.com>
@@ -0,0 +1,173 @@
1
+ # PAI — Proactive AI Framework(主動式 AI 框架)
2
+
3
+ 一個通用、零依賴(純 Python 標準庫)、可直接運行的主動式 AI 框架原型,並內建 **PAI Protocol v1.1** 標準資料格式。
4
+
5
+ 核心理念:從「被動式 AI(你下指令它才做事)」轉為「事件驅動 + 持續感知 + 受治理的主動行為」。
6
+
7
+ ## 預打包的 .pai agent(Hugging Face)
8
+
9
+ | 模型頁 | 決策腦 | 說明 |
10
+ |---|---|---|
11
+ | [vito95311/gemma-guardian-pai](https://huggingface.co/vito95311/gemma-guardian-pai) | Gemma 4 26B-A4B(QAT q4_0,內嵌 14.4GB GGUF) | 離線 guardian:CPU 監控→清理、新檔案→自動歸檔 |
12
+ | [vito95311/minicpm-o-guardian-pai](https://huggingface.co/vito95311/minicpm-o-guardian-pai) | MiniCPM-o 4.5(全雙工 omni,不內嵌權重) | 即時看+聽、原生主動互動、語音回應 |
13
+
14
+ ## 架構
15
+
16
+ ```
17
+ ┌─ 感知層 Triggers ─────────────────────────────┐
18
+ │ IntervalTrigger / ScheduleTrigger │
19
+ │ FileWatchTrigger / ThresholdTrigger │ → Event(標準事件格式)
20
+ └───────────────────────────────────────────────┘
21
+
22
+ ┌─ 決策層 Brain ────────────────────────────────┐
23
+ │ RuleBrain(規則,離線、零成本、前線哨兵) │
24
+ │ LLMBrain(LLM 判斷,僅在需要時喚醒,失敗退回規則)│ → Intent(action/confidence/urgency/rationale)
25
+ └───────────────────────────────────────────────┘
26
+
27
+ ┌─ 治理層 ProactivityPolicy ────────────────────┐
28
+ │ 1. 信心門檻 2. 動作風險上限 3. 回饋自動降級 │
29
+ │ 4. 安靜時段 5. 干擾度公式 6. 每小時打擾上限 │ → 授予的自主等級
30
+ └───────────────────────────────────────────────┘
31
+
32
+ ┌─ 行動層 Actions ──────────────────────────────┐
33
+ │ OBSERVE 只記錄 │ SUGGEST 通知 │ ASK 確認 │ ACT 自動執行 │
34
+ └───────────────────────────────────────────────┘
35
+
36
+ ┌─ 記憶層 Memory(SQLite)──────────────────────┐
37
+ │ 事件 / 意圖 / 結果 / 回饋 / PAI Protocol 紀錄 │ → 回饋迴圈調節未來主動性
38
+ └───────────────────────────────────────────────┘
39
+ ```
40
+
41
+ ## PAI 干擾度公式
42
+
43
+ ```
44
+ urgency × confidence > interruption_cost 才允許打擾使用者
45
+ ```
46
+
47
+ `interruption_cost_fn` 可依使用者當下狀態(專注模式、開會、深夜)動態回傳 0~1。
48
+
49
+ ## 自主等級 × 交付模式
50
+
51
+ | AutonomyLevel | 行為 | 交付模式 |
52
+ |---|---|---|
53
+ | OBSERVE (0) | 只記錄,不打擾 | level_0_silent |
54
+ | SUGGEST (1) | 主動通知/建議 | level_1_soft_nudge |
55
+ | ASK (2) | 草稿+請求人類授權 | level_2_approval |
56
+ | ACT (3) | 高信心低風險時自動執行 | level_0_silent(事後可查) |
57
+
58
+ 風險高的動作用 `action_max_levels` 鎖死上限(例:寄信最多 ASK,永不自動寄出)。
59
+
60
+ ## PAI Protocol v1.1(標準資料格式)
61
+
62
+ 每次主動行為產生一份 6 層 JSON 紀錄(存入 SQLite,可直接對外交換):
63
+
64
+ ```json
65
+ {
66
+ "pai_protocol_version": "1.1",
67
+ "record_id": "pai_20260611_a1b2c3",
68
+ "timestamp": "2026-06-11T15:39:50Z",
69
+ "1_perception": { "trigger_source": "...", "event_type": "...", "raw_data_summary": {} },
70
+ "2_context": { "user_current_state": "...", "relevant_memory": [], "action_history": [] },
71
+ "3_anticipation": { "predicted_intent": "...", "urgency_score": 0.95, "confidence_score": 0.88,
72
+ "interruption_cost": 0.9, "requested_level": 2, "granted_level": 2 },
73
+ "4_execution": { "actions_taken": [{ "tool": "...", "status": "ok" }], "status": "executed" },
74
+ "5_delivery": { "delivery_mode": "level_2_approval", "requires_human_approval": true },
75
+ "6_adaptation": { "user_feedback": "pending", "learning_adjustment": null }
76
+ }
77
+ ```
78
+
79
+ ## `.pai` 打包格式(類 GGUF 的二進位容器)
80
+
81
+ 整個 agent 可打包成單一 `.pai` 檔案發布(規格見 [FORMAT.md](FORMAT.md)):
82
+ magic `PAI\x01` + 段表(64-byte 對齊、每段 SHA-256 校驗、zlib 壓縮)+ 資料區,
83
+ 可內嵌 `manifest / policy / triggers / rules / actions / brain / memory.db / weights.gguf`。
84
+
85
+ ```python
86
+ from pai import pack_agent, load_agent
87
+ pack_agent("my-agent.pai", manifest={...}, policy={...},
88
+ triggers=[...], rules=[...], actions={...},
89
+ weights_path="model-q4.gguf") # 選用:內嵌本地模型
90
+ agent_def = load_agent("my-agent.pai")
91
+ ```
92
+
93
+ 執行期的單筆行為紀錄則是文字 JSON,附檔名 `.pai.json`。
94
+
95
+ ## 快速開始
96
+
97
+ ```bash
98
+ python3 demo.py # 主動行為迴圈示範(零依賴)
99
+ python3 pack_demo.py # .pai 打包/載入/防竄改示範
100
+ ```
101
+
102
+ demo 模擬三種主動行為:
103
+ 1. CPU 飆高(ThresholdTrigger)→ 高緊急 → **ASK**(確認後清理)
104
+ 2. 待辦堆積(IntervalTrigger)→ 中緊急 → **SUGGEST**(只通知)
105
+ 3. 新檔案出現(FileWatchTrigger)→ 低風險 → **ACT**(自動歸檔)
106
+
107
+ ## 一鍵執行 .pai
108
+
109
+ ```bash
110
+ python3 -m pai info ops-guardian.pai # 查看打包內容
111
+ python3 -m pai run ops-guardian.pai # 載入並運行(未注入的 handler 以 stub 示意)
112
+ ```
113
+
114
+ 程式內載入(注入真實 handler / metric):
115
+
116
+ ```python
117
+ from pai import load_runtime
118
+ agent = load_runtime("ops-guardian.pai",
119
+ handlers={"ops.cleanup": my_cleanup_fn},
120
+ metrics={"cpu": read_cpu_percent})
121
+ agent.run()
122
+ ```
123
+
124
+ ## 底層模型(模型無關,可插拔決策腦)
125
+
126
+ | 決策腦 | 底層模型 | 用途 |
127
+ |---|---|---|
128
+ | `RuleBrain` | 無(純規則) | 前線哨兵、離線運行、LLM 的安全 fallback |
129
+ | `LLMBrain` | 雲端 API(預設 `claude-sonnet-4-6`,可換任何模型) | 開放式判斷 |
130
+ | `LocalLLMBrain` | `.pai` 內嵌 GGUF,經 `llama-cpp-python` | 完全離線、資料不出機 |
131
+ | `LlamaServerBrain` | `.pai` 內嵌 GGUF,經 llama.cpp `llama-server`(支援 `--lora` 熱載入) | 離線、新架構支援最快、常駐免重載 |
132
+ | `MiniCPMoBrain` | **openbmb/MiniCPM-o-4_5**(全雙工 omni:影像+音訊輸入、文字+語音輸出) | 即時看+聽現場、原生主動互動、語音回應 |
133
+
134
+ `brain.json` 的 `engine` 決定用哪個(`llama-server` / `llama-cpp-python` / `minicpm-o`);
135
+ 載入失敗一律自動退回 `RuleBrain`。
136
+
137
+ ### 全雙工語音 / Omni 版本(MiniCPM-o 4.5)
138
+
139
+ MiniCPM-o 4.5(9B,SigLip2 + Whisper + CosyVoice2 + Qwen3-8B)能同時看、聽、說,
140
+ 且**原生支援主動互動**——天然契合 PAI。打包:
141
+
142
+ ```bash
143
+ python3 pack_minicpm_o.py # 預設不內嵌權重,transformers 從 HF 載入
144
+ ```
145
+
146
+ `DuplexOmniLoop` 把模型的全雙工串流(`streaming_prefill`/`streaming_generate`)包成
147
+ 「持續感知 trigger」:模型自己決定何時主動發話,PAI 治理層仍負責是否放行、用什麼等級打擾。
148
+ 微調走 `LlamaFactoryBackend`(包 LLaMA-Factory 做 LoRA),其餘 self-finetuning 編排(EvalGate /
149
+ promote / rollback / 稽核)完全沿用。詳見 `pack_minicpm_o.py` 與 `pai/omni_brain.py`。
150
+
151
+ ## 接上 LLM
152
+
153
+ ```python
154
+ from pai import LLMBrain, RuleBrain
155
+
156
+ brain = LLMBrain(
157
+ available_actions=["cleanup", "archive_file", "__notify__"],
158
+ model="claude-sonnet-4-6", # 需設 ANTHROPIC_API_KEY
159
+ fallback=RuleBrain([...]), # LLM 失敗時退回規則
160
+ user_profile="工程師,上班時間 9-18,討厭被打擾",
161
+ )
162
+ ```
163
+
164
+ 成本控制採「雙層觸發」:RuleBrain 當前線哨兵過濾大多數事件,只有規則判定值得深入時才喚醒 LLM。
165
+
166
+ ## 落地建議
167
+
168
+ 1. **預設 Human-in-the-loop**:初期把所有有副作用的動作上限設為 ASK,跑出信任後再逐步開放 ACT。
169
+ 2. **可撤銷性**:所有自動化動作應提供 Undo(demo 的歸檔動作即可逆)。
170
+ 3. **回饋驅動**:使用者連續拒絕同類建議時,policy 會自動降級該動作(內建)。
171
+
172
+ ---
173
+ Author: vito1317 <service@vito1317.com>
@@ -0,0 +1,111 @@
1
+ # PAI Self-Finetuning 架構(即時自我學習)
2
+
3
+ 讓 PAI agent 從使用者回饋中持續自我校準。採三層遞進設計,風險由低到高、即時性由高到低,全部以 `.pai` 為載體。
4
+
5
+ ## 為什麼不直接「線上改權重」
6
+
7
+ 直接對 26B 主幹做線上梯度更新在主動式 agent 場景是反模式:
8
+ 1. **災難性遺忘**——單樣本 SGD 會破壞既有能力,且不可逆。
9
+ 2. **污染風險**——壞樣本/對抗回饋直接寫進權重,無法回滾。
10
+ 3. **成本**——全量微調需數百 GB 顯存;即使 QLoRA,單步也要數秒並佔用推理資源。
11
+
12
+ 因此正確做法是把「學習」與「主幹權重」解耦:能即時學的用記憶,要改行為的用可插拔 adapter,且任何權重變更都必須通過離線品質閘門。
13
+
14
+ ---
15
+
16
+ ## 第一層:記憶/檢索式學習(已實作 ✅)
17
+
18
+ **即時性**:毫秒級 **風險**:零 **動權重**:否
19
+
20
+ 每次 (事件 → 意圖 → 回饋) 存成經驗向量;下次相似事件檢索 top-k 經驗,把「過往教訓」注入決策腦 prompt。
21
+
22
+ - 模組:`pai/learning.py` 的 `ReflectiveMemory`
23
+ - embedding:`EmbeddingClient`(llama-server `/v1/embeddings` 語義檢索)或 `HashingEmbedder`(零依賴詞袋)
24
+ - 啟用:`brain.json` 設 `"learning": true`
25
+ - 回饋 API:`agent.record_user_feedback(event, intent, "accepted|rejected|modified|ignored")`
26
+ - 已驗證:使用者連續拒絕某類通知後,PAI 自動把該類行為從 SUGGEST 降為靜默,全程未動權重
27
+
28
+ 這層解決了 80% 的「希望它記住我的偏好」需求,且立即生效、可解釋、可刪除單筆。
29
+
30
+ ---
31
+
32
+ ## 第二層:LoRA adapter 熱插拔(設計)
33
+
34
+ **即時性**:分鐘~小時級(背景) **風險**:低(可回滾) **動權重**:只動 adapter,主幹不變
35
+
36
+ 當第一層累積足夠回饋(例如 ≥200 筆、且涵蓋多種情境),在背景把回饋轉成偏好資料集,跑一次 LoRA/QLoRA 微調,產生一個幾十 MB 的 adapter。
37
+
38
+ ```
39
+ 回饋資料庫 ──> build dataset (accepted=正例, rejected=負例)
40
+ ──> QLoRA 訓練 (背景, 不阻塞推理)
41
+ ──> adapter.safetensors
42
+ ──> 存進 .pai 新段 adapters/<timestamp>.safetensors
43
+ ──> llama-server --lora 熱載入(主幹權重不動)
44
+ ```
45
+
46
+ `.pai` 格式擴充(新慣例段,向後相容):
47
+
48
+ | 段 | 內容 |
49
+ |---|---|
50
+ | `adapters/active.safetensors` | 目前生效的 LoRA |
51
+ | `adapters/<ts>.safetensors` | 歷史 adapter(可一鍵回滾) |
52
+ | `training/feedback.jsonl` | 累積的偏好樣本 |
53
+ | `training/state.json` | 上次訓練時間、樣本數、版本 |
54
+
55
+ 關鍵安全設計:主幹權重段 `weights.gguf` **永遠不變**,學習只新增/切換 adapter 段。要回滾就把 `active` 指回舊 adapter。
56
+
57
+ 訓練引擎建議:`llama.cpp` 的 `llama-finetune`(純 C++、無重依賴、能直接吃 GGUF)或 PEFT+bitsandbytes(功能強、依賴重)。`brain.json` 以 `"finetune": {"engine": "...", "min_samples": 200, "schedule": "daily"}` 設定。
58
+
59
+ ---
60
+
61
+ ## 第三層:排程重訓 + Eval Gate(設計)
62
+
63
+ **即時性**:天/週級 **風險**:中(有閘門擋住) **動權重**:adapter(不上線就丟棄)
64
+
65
+ 新 adapter 不是訓完就用,**必須先通過離線品質閘門**才會切成 active:
66
+
67
+ ```
68
+ 新 adapter ──> 在固定 eval set 上跑(保留的歷史情境 + 黃金答案)
69
+ ──> 比較 新 vs 現役 adapter 的指標(決策正確率、打擾精準度、拒絕率)
70
+ ──> 新的「顯著勝出」才 promote 成 active;否則保留現役、丟棄新 adapter
71
+ ──> 每次 promote 寫入稽核紀錄(誰、何時、用哪批資料、指標多少)
72
+ ```
73
+
74
+ Eval set 從 PAI Protocol 紀錄自動累積(使用者明確 accepted/rejected 的情境就是天然標註)。閘門條件可設保守,例如「新 adapter 決策正確率 ≥ 現役 + 2%,且打擾精準度不下降」。
75
+
76
+ 這層防止「越學越壞」——這正是線上學習最大的坑。
77
+
78
+ ---
79
+
80
+ ## 實作狀態
81
+
82
+ 全部三層已實作並通過端到端測試(`finetune_demo.py`,EchoBackend 無 GPU 驗證):
83
+
84
+ - [x] 第一層 ReflectiveMemory(記憶式即時學習)
85
+ - [x] 第二層 訓練後端(`EchoBackend` 測試用 / `LlamaFinetuneBackend` 真實,包 `llama-finetune`)
86
+ - [x] 第二層 `export_preference_dataset`(回饋→偏好資料集)
87
+ - [x] 第二層 `AdapterStore`(側車 adapter 管理、active 指標、歷史、回滾)
88
+ - [x] 第二層 `LlamaServerBrain` 以 `--lora` 熱載入現役 adapter(主幹不動)
89
+ - [x] 第二層 `bake_adapter_into_pai`(發布時把現役 adapter 烘焙進 `.pai`)
90
+ - [x] 第三層 `EvalGate`(主指標增益門檻 + 非退化指標檢查)
91
+ - [x] 第三層 `SelfFinetuneManager`(訓練→閘門→promote/丟棄→稽核 jsonl)
92
+
93
+ 實測驗證:第一次訓練 +0.07 增益通過上線;無增益再訓練被閘門擋下(保護「越學越壞」);
94
+ 新增回饋後 v2 +0.05 通過;可一鍵回滾到 v1;全程主幹權重 `weights.gguf` 未變更。
95
+
96
+ ### 用真實 LoRA 訓練
97
+
98
+ ```python
99
+ from pai import SelfFinetuneManager, EvalGate, LlamaFinetuneBackend
100
+ mgr = SelfFinetuneManager(
101
+ db_path="pai_memory.db", adapters_root="pai_adapters",
102
+ trainer=LlamaFinetuneBackend("llama-finetune"), # 需 llama.cpp 編出 llama-finetune
103
+ eval_gate=EvalGate(my_eval_fn, min_gain=0.02),
104
+ base_gguf="models/gemma-4-26B_q4_0-it.gguf", min_samples=200)
105
+ mgr.maybe_train_and_promote() # 可放進排程(每日/每週背景跑)
106
+ ```
107
+
108
+ loader 會自動偵測 `pai_adapters/` 的現役 adapter 並在啟動 llama-server 時 `--lora` 掛上。
109
+
110
+ ---
111
+ Author: vito1317 <service@vito1317.com>
@@ -0,0 +1,37 @@
1
+ """PAI — Proactive AI Framework (主動式 AI 框架)
2
+
3
+ 感知 (Triggers) → 決策 (Brain) → 治理 (Policy) → 行動 (Actions) → 記憶/回饋 (Memory)
4
+ """
5
+ from .core import PAIAgent, Event, Intent, AutonomyLevel
6
+ from .triggers import IntervalTrigger, ScheduleTrigger, FileWatchTrigger, ThresholdTrigger
7
+ from .brain import RuleBrain, LLMBrain, Rule
8
+ from .policy import ProactivityPolicy
9
+ from .actions import ConsoleNotifier, WebhookNotifier, CallbackAction
10
+ from .memory import Memory
11
+ from .protocol import PAI_PROTOCOL_VERSION, build_record, to_json, save_pai, load_pai
12
+ from .paifile import PaiWriter, PaiReader, pack_agent, load_agent, bake_adapter_into_pai
13
+ from .finetune import (
14
+ AdapterStore, EvalGate, SelfFinetuneManager,
15
+ EchoBackend, LlamaFinetuneBackend, LlamaFactoryBackend, export_preference_dataset,
16
+ )
17
+ from .omni_brain import MiniCPMoBrain, DuplexOmniLoop
18
+ from .loader import load_runtime
19
+ from .learning import ReflectiveMemory, HashingEmbedder, EmbeddingClient
20
+
21
+ __version__ = "0.1.0"
22
+ __author__ = "vito1317 <service@vito1317.com>"
23
+
24
+ __all__ = [
25
+ "PAIAgent", "Event", "Intent", "AutonomyLevel",
26
+ "IntervalTrigger", "ScheduleTrigger", "FileWatchTrigger", "ThresholdTrigger",
27
+ "RuleBrain", "LLMBrain", "Rule",
28
+ "ProactivityPolicy",
29
+ "ConsoleNotifier", "WebhookNotifier", "CallbackAction",
30
+ "Memory",
31
+ "PAI_PROTOCOL_VERSION", "build_record", "to_json", "save_pai", "load_pai",
32
+ "PaiWriter", "PaiReader", "pack_agent", "load_agent", "load_runtime",
33
+ "ReflectiveMemory", "HashingEmbedder", "EmbeddingClient",
34
+ "bake_adapter_into_pai", "AdapterStore", "EvalGate", "SelfFinetuneManager",
35
+ "EchoBackend", "LlamaFinetuneBackend", "LlamaFactoryBackend", "export_preference_dataset",
36
+ "MiniCPMoBrain", "DuplexOmniLoop",
37
+ ]