feat: AI Self-Loop 專案骨架 — 爬站健檢版

完整實作建構順序 1-8(rule-based):
- Task Queue(SQLite):tasks/attempts/results + claim 防重複
- LLM 後端:OllamaBackend(num_ctx=32768) + LLMRouter
- Prompt Builder(YAML+Jinja2,重試注入 feedback)
- Context Assembler / Output Judge / Feedback Builder
- Loop Controller + Circuit Breaker
- Driver 層(BaseDriver + ApiClientDriver)
- Agent 層(BaseAgent + SiteHealthAgent:爬站/健檢/issue 生成)
- pipeline.py 入口,驗收:pending→done,output/ 落地

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Yellow
2026-06-14 17:35:54 +08:00
commit 27f98712ee
31 changed files with 1480 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# =============================================================================
# 憑證佔位檔(範本)。
#
# 使用方式:
# 1. 複製成 config/credentials.yaml已被 .gitignore 忽略,不會進版控)
# 2. 填入真實值,或留空改用環境變數
#
# 讀取優先序(見 src/config.py
# 環境變數 > credentials.yaml > 這裡的預設
#
# TODO(security): 日後要加密時,這個檔就是掛載解密層的位置——
# 例如改讀 SOPS / age / Vault介面不變。
# =============================================================================
credentials:
# 範例:未來若目標站需要登入或 API key 才能測
target_basic_auth:
username: "${TARGET_USER:-}"
password: "${TARGET_PASS:-}"
# 範例:若改用雲端 LLM
ollama_api_key: "${OLLAMA_API_KEY:-}"

70
config/environments.yaml Normal file
View File

@@ -0,0 +1,70 @@
# =============================================================================
# 環境設定(明文,先不加密)
# 各環境的 URL / 端點都集中在這裡,程式碼不寫死任何網址。
# 切換環境只要改 active 或設環境變數 APP_ENV。
# =============================================================================
active: ${APP_ENV:-dev} # 預設 dev可被環境變數 APP_ENV 覆蓋
environments:
dev:
# --- 受測目標 ---
target:
start_url: "https://www.pluspay.com.tw/"
# 只爬這個主網域底下的頁面;其餘視為「外部」只檢查可達性
internal_domain: "pluspay.com.tw"
# 記錄但不深入的外部 / 子網域(外連只檢查連得到嗎)
do_not_crawl:
- "104.com.tw"
- "facebook.com"
- "event2023.pluspay.com.tw"
- "member.pluspay.com.tw"
max_pages: 200 # 爬蟲安全上限,避免失控
min_pages_expected: 5 # 驗收sitemap 至少要有這麼多頁,低於視為漏抓
request_timeout_sec: 10
crawl_delay_sec: 0.5 # 禮貌性延遲,別把對方站打掛
# --- LLM 後端(依序嘗試,用第一個可用的)---
llm:
num_ctx: 32768 # 強制覆蓋 Ollama 預設 4K
backends:
- type: ollama
base_url: "http://localhost:11434"
model: "gemma4:e4b"
- type: ollama
base_url: "http://localhost:11434"
model: "minimax-m2.7:cloud"
# --- Loop 引擎參數 ---
loop:
max_attempts: 3
circuit_breaker:
failure_threshold: 5 # 視窗內失敗幾次就跳閘
window_sec: 60 # 觀察視窗
cooldown_sec: 30 # 跳閘後暫停多久
# 之後要加正式環境,照 dev 的結構複製一份即可
prod:
target:
start_url: "https://www.pluspay.com.tw/"
internal_domain: "pluspay.com.tw"
do_not_crawl:
- "104.com.tw"
- "facebook.com"
- "event2023.pluspay.com.tw"
- "member.pluspay.com.tw"
max_pages: 1000
min_pages_expected: 10
request_timeout_sec: 15
crawl_delay_sec: 1.0
llm:
num_ctx: 32768
backends:
- type: ollama
base_url: "http://localhost:11434"
model: "gemma4:e4b"
loop:
max_attempts: 3
circuit_breaker:
failure_threshold: 5
window_sec: 60
cooldown_sec: 30