Skip to content
Greg's Space
Go back

終端機個人助理(一):用 cfg.py 管理工作資料夾與模型設定

這個系列會用三個檔案,做出一個在終端機裡運作的個人助理:

檔案負責的事文章
cfg.py工作資料夾、作業系統、模型金鑰本篇
krl.py建立 deep agent,把回答、工具資訊、審核請求串流出來第二篇
tui.pyTextual 聊天介面與核准視窗第三篇

三篇的程式碼都是完整檔案,照順序複製貼上就能跑起來。

專案結構

personal-assistant/
├── src/
│   ├── cfg.py
│   ├── krl.py
│   └── tui.py
├── pyproject.toml
└── .env.sample

步驟 1:pyproject.toml

檔案位置:pyproject.toml

[project]
name = "personal-assistant"
version = "0.1.0"
description = "Personal assistant built on deepagents with a Textual TUI"
requires-python = ">=3.12"
dependencies = [
    "deepagents>=0.7.19",
    "langchain-openai>=1.6.6",
    "langchain-core>=1.6.5",
    "langgraph>=1.2.12",
    "textual>=8.2.8",
    "python-dotenv>=1.2.3",
]

[project.scripts]
lpa = "tui:activate"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
only-include = ["src"]
sources = ["src"]

[project.scripts] 這一行會在安裝後產生 lpa 指令,執行時呼叫 tui.py 裡的 activate()。sources = ["src"] 讓 src/ 底下的 cfg、krl、tui 直接成為最上層模組,所以三個檔案之間可以用 from cfg import Profile 互相引用。每一段設定的詳細說明在這篇補充文章。

步驟 2:.env

助理需要三個設定值:模型名稱、API 位址、API 金鑰。任何相容 OpenAI 格式的服務都可以,以下用 OpenRouter 示範:

檔案位置:.env.sample

# 複製一份成 .env 再填入:cp .env.sample .env
MODEL_NAME=google/gemma-4-31b-it
MODEL_URL=https://openrouter.ai/api/v1
API_KEY=your-api-key-here

注意:cfg.py 是從你執行 lpa 時所在的資料夾讀取 .env,不是從專案資料夾讀取。之後在哪個資料夾啟動助理,那個資料夾就要有一份 .env。

步驟 3:cfg.py

檔案位置:src/cfg.py

import platform
import os
from dotenv import dotenv_values
from pathlib import Path


class Profile:

    def __init__(self) -> None:
        """"""

        return

    @property
    def workspace(self) -> Path:
        """
        在指定的路徑啟用應用程式的時候,
        在該路徑底下新增一個 workspace 資料夾,
        將該資料夾作為工作目錄,保存執行過程中儲存檔案的位置。
        """

        workspace = Path.cwd() / "workspace"
        workspace.mkdir(parents=True, exist_ok=True)
        return workspace

    @property
    def os(self) -> str:
        """
        獲得作業系統名稱,可以是 "Linux", "Windows", "Darwin"等。 
        """

        return platform.system()

    @property
    def secret(self) -> dict:
        """
        獲得模型訪問的設定,
        從啟用應用程式時所在路徑的 .env 讀取。
        """

        path = Path.cwd() / '.env'
        if not path.exists():
            raise FileNotFoundError(f"找不到設定檔,請在 {path} 建立 .env")

        secret = dict(dotenv_values(path))
        return secret

    pass

workspace:助理的工作資料夾

Path.cwd() 是啟動程式時所在的資料夾。助理會在底下建立 workspace/,之後產生的暫存檔、分析結果都放在這裡。exist_ok=True 表示資料夾已經存在也不會報錯,所以每次存取這個屬性都是安全的。

這個設計的好處是:在哪裡啟動助理,它就在哪裡工作。不同專案各自啟動一次,檔案就不會混在一起。

os:告訴模型現在是什麼系統

platform.system() 會回傳 "Linux"、"Windows" 或 "Darwin"(macOS)。第二篇會把這個值寫進 system prompt,讓模型知道該用 ls 還是 dir。

secret:讀取模型設定

dotenv_values() 會把 .env 讀成字典,但不會寫進環境變數,所以金鑰不會外洩給助理執行的 shell 指令。找不到 .env 時直接丟出 FileNotFoundError,錯誤訊息會附上完整路徑,方便知道要把檔案放在哪裡。

讀出來的結果長這樣:

{
    "MODEL_NAME": "google/gemma-4-31b-it",
    "MODEL_URL": "https://openrouter.ai/api/v1",
    "API_KEY": "sk-or-...",
}

小提醒

三個設定都寫成 @property,每次存取都會重新計算,所以 secret 每讀一次就會重新開一次 .env。這點效能影響不大;如果想只讀一次,可以把 @property 換成 functools.cached_property。

步驟 4:安裝專案

在專案資料夾裡以可編輯模式安裝,之後修改 src/ 底下的檔案不需要重新安裝:

cd personal-assistant
pip install -e .

三個檔案都寫完後就能用 lpa 指令啟動,目前只要確認安裝沒有出錯。

下一步

設定準備好之後,第二篇會用 Profile 建立 deep agent,並把它包成一個可以串流回答的 Assistant 類別。



Previous Post
終端機個人助理(二):用 krl.py 建立 deep agent 並串流回答
Next Post
沒有網路也能搬 Python 環境:把 venv 裡已安裝的套件重新打包成 .whl