顯示具有 Gitlab 標籤的文章。 顯示所有文章
顯示具有 Gitlab 標籤的文章。 顯示所有文章

2026年1月12日 星期一

AI 實作股票系統 - 環境建置

 

第一部分:步驟大綱 (Outline)

  1. 環境準備 (WSL2 & Docker)

    • 確認 WSL2 Ubuntu 環境。

    • 配置 Docker Compose 以運行 SQL Server (作為資料庫) 和未來的 Seq (日誌) 或其他服務。

    • 建立專案根目錄。

  2. 後端專案建置 (.NET 9 WebAPI)

    • 使用 .NET CLI 建立 Solution 與 WebAPI 專案。

    • 加入必要的 Nuget 套件 (EF Core, SQL Server)。

    • 配置 appsettings.json 連接 Docker 中的資料庫。

    • 建立 Dockerfile (後端)。

  3. 前端專案建置 (React + Vite + Tailwind)

    • 使用 npm (create-vite) 建立前端專案。

    • 初始化 Tailwind CSS 與 shadcn/ui (UI 元件庫)。

    • 配置 vite.config.ts 設定 Proxy (解決開發跨域問題)。

    • 建立 Dockerfile (前端)。

  4. 整合與啟動 (Docker Compose)

    • 編寫 docker-compose.yml 整合 DB、Backend、Frontend。

    • 啟動服務並驗證連線。

第二部分:資料夾結構圖 (Folder Structure)

您執行完所有步驟後,您的專案結構 ~/projects/stock-system 將會長這樣:

Plaintext
stock-system/                # [專案根目錄]
├── docker-compose.yml       # [核心] 定義 DB, Backend, Frontend 如何一起啟動
├── .env                     # [設定] 存放資料庫密碼等環境變數
├── backend/                 # [.NET WebAPI 後端目錄]
│   ├── StockSystem.sln      # Solution 檔案
│   ├── StockSystem.Api/     # 主 API 專案
│   │   ├── Dockerfile       # 後端映像檔定義
│   │   ├── Program.cs       # 程式進入點
│   │   ├── Controllers/     # API 接口
│   │   └── appsettings.json # DB 連線字串設定
│   └── StockSystem.Core/    # (選用) 放置純邏輯或 DTO
├── frontend/                # [React 前端目錄]
│   ├── Dockerfile           # 前端映像檔定義 (通常是 Nginx 用於 Production)
│   ├── package.json
│   ├── vite.config.ts       # 前端設定 (含 Proxy)
│   ├── src/
│   │   ├── App.tsx
│   │   ├── main.tsx
│   │   └── components/      # UI 元件
│   └── index.html
└── data/                    # [自動生成] SQL Server 的資料掛載目錄 (不進版控)

第三部分:詳細指令與檢核機制

執行環境說明:

  • 所有指令請在 WSL2 (Ubuntu) 的終端機中執行。

  • 請確保您已安裝 .NET 9 SDKNode.js (v20+) 在 WSL2 中 (非 Windows Host)。

  • 您目前的目錄假設為使用者家目錄 ~

步驟 0: 安裝 .NET 9 SDK 和 Node.js 

安裝 Node.js (v20+) 使用 NVM

使用 NVM (Node Version Manager) 是開發者的最佳實踐,因為它允許您在不需要 sudo 的情況下安裝全域套件,且方便切換版本。

3.1 下載並安裝 NVM

  • 執行位置~ (家目錄)

  • 指令意圖:從 GitHub 下載 NVM 安裝腳本並執行。

Bash
curl -C - -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
  • 參數說明

    • curl: 傳輸工具。

    • -C -: (續載參數) 自動從上次中斷處繼續下載。

    • -o-: 將下載內容直接輸出到標準輸出 (stdout),以便後面的 | bash 執行。

    • | bash: 將下載的腳本內容傳遞給 bash 執行。

3.2 啟用 NVM 環境變數

安裝完後,需要重新載入設定檔才能使用 nvm 指令。

  • 執行位置~ (家目錄)

  • 指令意圖:重新讀取 .bashrc 設定檔,使 NVM 立即生效。

Bash
source ~/.bashrc

(註:若您使用 zsh,請執行 source ~/.zshrc)

3.3 安裝 Node.js v20 (LTS)

  • 執行位置~ (家目錄)

  • 指令意圖:安裝 Node.js 第 20 版 (長期支援版本)。

Bash
nvm install 20
  • 參數說明

    • install 20: 下載並安裝 v20 系列的最新版本 (例如 v20.11.0)。安裝後會自動設為預設使用版本。

  • 檢核機制: 分別檢查 Node 與 NPM 的版本。

    Bash
    node -v && npm -v
    

    預期輸出範例v20.x.x 10.x.x (對應的 npm 版本)


安裝 .NET 9 SDK

請在 backend 資料夾或回到家目錄執行皆可。

步驟 1:下載並執行安裝腳本

  • 執行位置:目前的目錄

  • 指令意圖:下載微軟官方腳本,賦予執行權限,並要求它安裝 .NET 9 通道 (Channel) 的最新版。

Bash
wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
chmod +x ./dotnet-install.sh
./dotnet-install.sh --channel 9.0
  • 參數說明

    • wget ... -O ...: 下載並存檔為 dotnet-install.sh

    • chmod +x: 讓腳本變成可執行檔。

    • --channel 9.0: 指示腳本去抓取 9.0 系列的最新穩定版 (STS)。

  • 執行後預期結果:螢幕會跑一段下載進度條,最後顯示 Installation finished successfully.

步驟 2:設定環境變數 (關鍵步驟)

因為是手動安裝,終端機目前還不知道 dotnet 指令在哪裡,我們需要把它加到 .bashrc

  • 執行位置:任何位置

  • 指令意圖:將 .NET 的路徑寫入您的個人設定檔,並立即載入。

Bash
echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc
echo 'export PATH=$PATH:$HOME/.dotnet:$HOME/.dotnet/tools' >> ~/.bashrc
source ~/.bashrc
  • 參數說明

    • echo '...' >> ~/.bashrc: 將引號內的文字「附加」到檔案最後一行。

    • DOTNET_ROOT: 告訴依賴 .NET 的工具 (如 IDE) 核心檔案在哪。

    • PATH: 告訴終端機去哪裡找 dotnet 這個指令。

步驟 3:最終檢核

現在 Node.js 和 .NET 9 應該都好了。

  • 指令意圖:一次檢查兩個環境。

Bash
node -v && dotnet --version
  • 預期輸出

    Plaintext
    v20.19.6
    9.0.101 (或類似的 9.0.x 版本號)

步驟 1: 專案初始化與資料庫環境

意圖: 建立專案資料夾,並透過 Docker 啟動 SQL Server,確保資料庫就緒。

使用原本 ai-workspace 裡面的 SQL Server
# 現有的 docker-compose.yml (無需大改)
networks:
  ai_mesh:
    driver: bridge
    name: shared_ai_network  # [建議新增] 明確指定網路名稱,方便別人連進來

檢核機制:

  • 指令:docker ps

  • 預期結果:看到 stock-db 狀態為 Up

  • 指令:docker logs stock-db

  • 預期結果:看到日誌最後顯示 "SQL Server is now ready for client connections"。

步驟 2: 建置 .NET 9 WebAPI 後端

意圖: 建立 C# 後端專案,安裝 EF Core,並測試 API 能否運行。

Bash
# 1. 建立後端目錄並進入
mkdir backend
cd backend

# 2. 建立 Solution 和 WebAPI 專案
# 參數: -n 指定名稱, -o 指定輸出目錄
dotnet new sln -n StockSystem
dotnet new webapi -n StockSystem.Api -o StockSystem.Api
dotnet sln add StockSystem.Api/StockSystem.Api.csproj

# 3. 進入 API 專案目錄安裝套件
cd StockSystem.Api
# 意圖: 安裝 EF Core SQL Server 驅動與工具
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
# 安裝 CORS 套件 (避免瀏覽器擋住前端連線)
dotnet add package Microsoft.AspNetCore.Cors

# 4. 設定 HTTPS 開發憑證 (讓瀏覽器信任 Localhost)
dotnet dev-certs https --trust

# 5. 回到 backend 根目錄試跑
cd ..
# 參數: --project 指定執行的專案
dotnet run --project StockSystem.Api/StockSystem.Api.csproj --urls "http://localhost:5000"
  • 檢核機制:

    • 指令:(保持上述指令執行,開啟新的 WSL 終端機) curl http://localhost:5000/weatherforecast

    • 預期結果:看到回傳一串 JSON 天氣資料。

    • (檢核完畢後可在原視窗按 Ctrl+C 停止後端)

步驟 3: 建置 React + Vite 前端

意圖: 建立現代化前端,並配置 Proxy 以便呼叫後端 API。

Bash
# 1. 回到專案根目錄
cd ~/projects/stock-system

# 2. 建立前端專案 (使用 Vite 樣板)
# 參數: frontend 是目錄名, --template react-ts 表示使用 React + TypeScript
npm create vite@latest frontend -- --template react-ts

# 3. 進入目錄並安裝依賴
cd frontend
npm install

# 4. 安裝 Tailwind CSS (現代化樣式)
# 讓您的開發最順暢,且讓 Cursor (AI) 能準確生成程式碼,
# 強烈建議強制使用 Tailwind CSS v3
# 目前的 AI 模型對 v3 的支援度是最完美的,v4 的設定方式變動太大,AI 容易寫錯。

npm install -D tailwindcss@3.4.17 postcss autoprefixer
npx tailwindcss init -p

# 5. 修改 tailwind.config.js (讓 Tailwind 掃描檔案)
# 意圖: 覆蓋設定檔,指定 content 路徑
cat <<EOF > tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
EOF

# 6. 在 src/index.css 加入 Tailwind 指令
echo "@tailwind base; @tailwind components; @tailwind utilities;" > src/index.css

# 7. 設定 Vite Proxy (關鍵步驟:讓前端開發時能連到後端)
# 意圖: 修改 vite.config.ts,將 /api 開頭的請求轉發到 http://localhost:5000
cat <<EOF > vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})
EOF
  • 檢核機制:

    • 指令:npm run dev

    • 預期結果:看到 "Local: http://localhost:5173/"。

    • 開啟 Windows 瀏覽器訪問 http://localhost:5173,應看到 Vite + React 預設畫面。

步驟 4: 整合啟動 (開發模式)

意圖: 現在您有資料庫 (Docker)、後端 (C#)、前端 (Node.js)。在開發階段,我們通常手動啟動前後端,資料庫常駐 Docker。

  1. 啟動順序:

    • Terminal 1 (WSL): 確保資料庫活著 docker compose up -d db

    • Terminal 2 (WSL): 啟動後端

      Bash
      cd ~/projects/stock-system/backend
      dotnet watch --project StockSystem.Api/StockSystem.Api.csproj --urls "http://localhost:5000"
      

      (說明: dotnet watch 支援熱重載,改 C# code 會自動重啟)

    • Terminal 3 (WSL): 啟動前端

      Bash
      cd ~/projects/stock-system/frontend
      npm run dev
      
  2. Cursor 開發設定 (下一步):

    • 現在您可以用 Cursor 打開 ~/projects/stock-system 資料夾。

    • 提示 Cursor (使用 Qwen3-Coder): 「這是我的專案結構,Backend 是 .NET 9 WebAPI,Frontend 是 React+Vite。請幫我修改 Backend 的 Program.cs 來連線 Docker 中的 SQL Server...」

新專案的 docker-compose.yml (股票系統)

在您的新專案資料夾 (~/projects/stock-system) 中,建立一個新的 compose 檔。這個檔案只包含股票系統的服務,並掛載到上面的 shared_ai_network

YAML
# ~/projects/stock-system/docker-compose.yml
services:
  # 1. .NET Backend
  backend:
    build: ./backend
    container_name: stock_api
    ports:
      - "5000:8080"
    environment:
      # 直接使用現有 SQL Server 的 container_name
      - ConnectionStrings__DefaultConnection=Server=sql_srv;Database=StockDB;User Id=sa;Password=${SQL_PASSWORD};TrustServerCertificate=True;
      # 連線到現有的 SGLang 用於財報分析
      - AI_SERVICE_URL=http://sglang_srv:30000/v1
    networks:
      - stock_net        # 內部網路
      - shared_ai_network # [關鍵] 連線到外部的 AI 基礎設施

  # 2. React Frontend (開發時可用 Node,正式部署用 Nginx)
  frontend:
    build: ./frontend
    container_name: stock_web
    ports:
      - "5173:5173" # Vite 開發埠
    environment:
      - VITE_API_URL=http://localhost:5000
    networks:
      - stock_net

networks:
  stock_net:
    driver: bridge
  
  # 定義外部網路,讓這個專案能抓到 sql_srv 和 sglang_srv
  shared_ai_network:
    external: true

這樣做如何達成您的需求?

  1. 關於 SQL Server:

    • 不用開新容器。 您的 .NET Backend 透過 shared_ai_network 直接連線到 sql_srv

    • 資料隔離: 您只需要在現有的 SQL Server 中 CREATE DATABASE StockDB,這與其他資料庫(如果有)是分開的。

  2. 關於 AI 財報分析 (SGLang):

    • 不用重複下載模型。

    • 您的 .NET Backend 程式碼中,會使用 Semantic KernelHttpClient 發送請求給 http://sglang_srv:30000/v1

    • 因為都在 Docker 網路內,速度極快 (vibe coding 體驗)。

  3. 關於 Nginx:

    • 在開發階段(目前),其實不需要 Nginx。直接用 npm run dev (Vite) 的容器即可。

    • 等您要「正式發布」這套系統給自己長期使用時,才將前端 build 成靜態檔放入 Nginx 容器。

環境變數 (.env): 新專案的 .env 只需要存 SQL_PASSWORD (跟原本的一樣) 即可。



把程式碼版控起來,是開發系統最重要的一步。

由於您的 GitLab 是架設在本地 Docker (http://localhost:8929),我們可以直接透過 HTTP 協定將 WSL 裡的程式碼推上去。

請依照以下三個步驟操作:

第一步:在 GitLab 網頁上建立「空專案」

  1. 開啟瀏覽器,進入您的 GitLab: http://localhost:8929

    • (登入帳號通常是 root,密碼是您當初設定的,或者是您後來建立的帳號)

  2. 點選 New Project (或右上角的 + 號 -> New project/repository)。

  3. 選擇 Create blank project

  4. 填寫資訊:

    • Project name: stock-system

    • Project URL: 保持預設 (通常是您的帳號名)。

    • Visibility: Private 或 Internal 皆可。

    • 重要: 取消勾選 "Initialize repository with a README" (因為我們本地已經有檔案了)。

  5. 按下 Create project


第二步:設定 .gitignore (非常關鍵!)

在把程式碼推上去之前,我們必須告訴 Git 忽略 那些暫存檔 (如 node_modules, bin, obj),否則您的 Git 倉庫會變得巨大且混亂。

請在 WSL 終端機 (~/projects/stock-system 目錄下) 執行以下指令,這會自動產生一個針對 C# 和 React 的忽略清單:

Bash
# 確保在專案根目錄
cd ~/projects/stock-system

# 建立 .gitignore 檔案,排除不必要的暫存檔
cat <<EOF > .gitignore
# --- Cursor / VS Code ---
.vscode/
.idea/
*.code-workspace

# --- OS ---
.DS_Store
Thumbs.db

# --- Node.js (Frontend) ---
frontend/node_modules/
frontend/dist/
frontend/.env
frontend/.env.local
frontend/npm-debug.log*
frontend/yarn-debug.log*
frontend/yarn-error.log*

# --- .NET (Backend) ---
backend/bin/
backend/obj/
backend/.vs/
backend/Properties/launchSettings.json
*.user
[Dd]ebug/
[Rr]elease/
appsettings.Development.json
EOF

注意: 我沒有把 .env 加入忽略,因為這是您本地的練習環境。但如果是正式專案,建議把含有密碼的 .env 也加入 .gitignore


第三步:初始化 Git 並推送到 GitLab

請在 WSL 終端機 繼續執行:

Bash
# 1. 初始化 Git 倉庫
git init

1. 設定 Git 作者身分 (請依喜好修改引號內內容)

Bash
# 設定您的名字 (會顯示在 GitLab 的提交歷史中)
git config --global user.name "Frankie"

# 設定您的 Email (建議設定成跟您 GitLab 帳號相同的 Email,這樣頭像才會正確顯示)
git config --global user.email "frankie@example.com"

說明: --global 表示這台 WSL 所有的專案都預設使用這個身分。


# 2. 將所有檔案加入暫存區 (這時候會自動套用 .gitignore)
git add .

# 3. 提交第一次版本
git commit -m "Initial commit: React Frontend + .NET 9 Backend setup"

# 4. 設定分支名稱為 main (現在標準都用 main 而非 master)
git branch -M main

# 5. 加入遠端倉庫 (請將 <您的帳號> 替換成您的 GitLab 帳號,通常是 root)
# 如果您不確定,看瀏覽器網址列,例如 http://localhost:8929/root/stock-system
git remote add origin http://localhost:8929/root/stock-system.git

# 6. 推送上去
git push -u origin main

🔐 關於驗證 (如果跳出輸入帳密)

當您執行 git push 時,它會要求輸入 Username 和 Password:

  • Username: 輸入您的 GitLab 帳號 (例如 root)。

  • Password:

    • 您可以輸入您的 登入密碼

    • 或者,因為您之前提過有 GitLab PAT (Personal Access Token),這裡直接貼上那個 glpat-... 開頭的 Token 也是最安全的方式。






請切換到 Cursor 視窗:

  1. 確認 Cursor 開啟的是 stock-system 資料夾。

  2. 按下 Ctrl + I (Composer) 開啟對話框。

  3. 複製貼上 下面這段提示詞,讓 AI 幫您把「空殼」變成「股票系統」:

我已完成專案初始化,現在要開始開發功能。

環境資訊:

  • Frontend: React + Vite + Tailwind CSS v3 (已啟動於 port 5173)。

  • Backend: .NET 9 WebAPI (已啟動於 port 5000)。

  • Database: SQL Server 2022 (Docker container: sql_srv, port 1433, sa密碼: 7788@7788)。

任務 1 - 後端基礎建設:

  1. 請修改 Program.cs,註冊 SQL Server DbContext,並設定 CORS 允許 http://localhost:5173

  2. 建立 Data/AppDbContext.csModels/Stock.cs (欄位: Id, Symbol, Name, Price, ChangePercentage)。

  3. 請提供我「執行 Migration」的終端機指令,我要建立資料庫。

任務 2 - API 開發:

  1. 建立 StocksController,實作 GET (列表) 和 POST (新增) 功能。

任務 3 - 前端串接:

  1. 修改 App.tsx,用 Tailwind 畫一個深色模式的股票表格。

  2. 使用 fetch('/api/stocks') 抓取資料並顯示。

請一步步執行,先從「任務 1」開始寫程式碼。

 

複製貼上給 Cursor 的提示詞 (Prompt):

我正在開發一個股票投資紀錄系統。

目前的專案結構:

  • Backend: .NET 9 WebAPI (位於 /backend),已安裝 EF Core SQL Server。

  • Frontend: React + Vite + TypeScript + Tailwind CSS (位於 /frontend)。

  • Database: Docker 運行的 SQL Server 2022 (連線字串在 appsettings.json,密碼是 7788@7788)。

請幫我完成以下「第一階段開發」任務:

  1. 後端 (C#):

    • StockSystem.Api 中建立一個 Stock Entity (欄位包含:Id, Symbol(代號), Name(名稱), Exchange(交易所), CurrentPrice(現價))。

    • 設定 EF Core 的 AppDbContext 並在 Program.cs 中註冊 SQL Server 連線。

    • 執行 Migration 建立資料表 (請告訴我需要執行的指令)。

    • 建立 StocksController 提供基本的 CRUD API。

  2. 前端 (React):

    • App.tsx 中建立一個簡單的介面。

    • 使用 fetch 呼叫 /api/stocks (Vite Proxy 已設定好指向後端)。

    • 用 Tailwind CSS 畫一個現代化的表格顯示股票清單。

    • 增加一個「新增股票」的按鈕與表單。

請一步步引導我,先從後端設定與 Migration 開始。



2025年11月27日 星期四

AI - 本地 LLM Coding Agent 部署指南 (Win11 + Docker GitLab 雙帳號版)

 

本地 LLM Coding Agent 部署指南 (Win11 + Docker GitLab 雙帳號版)

本文件整合了在 Windows 11 筆電上建立「口語/文字驅動程式開發 Agent」的完整步驟。 此架構利用 NVIDIA 5090 的強大算力,結合 Ollama 與 Docker,實現從需求輸入到 GitLab 專案創建、程式碼提交、MR 建立的全自動化流程。

🗺️ 第一部分:總體步驟大綱

階段

步驟名稱

執行環境

執行頻率

目的

I

基礎設施準備

Windows (Admin)

僅需一次

安裝 Docker Desktop, Ollama, Git, .NET SDK

II

GitLab 與模型配置

Docker & Ollama

僅需一次

啟動本地 GitLab 容器,下載 DeepSeek Coder 模型

III

隔離工作區建置

各自帳號的 PowerShell

每個帳號各做一次

建立 Python Venv, 設定獨立的 .env (含 PAT)

IV

C# 專案初始化

各自帳號的 PowerShell

每個帳號各做一次

建立基礎 C# WinForm 專案結構

V

啟動服務與執行

PowerShell & WebUI

每次開發時

啟動 Agent API, Open WebUI, 執行自動化開發任務

📁 第二部分:資料夾結構圖

1. 系統共享資源 (C 槽根目錄)

此目錄存放 GitLab 容器的資料庫與儲存庫,所有使用者共用此服務。

C:\
└── gitlab_data\        <-- [共享] GitLab 容器的永續儲存空間
    ├── config\
    ├── data\
    └── logs\

2. 使用者隔離工作區 (各自的 User Home 目錄)

注意: 個人帳號與網域帳號需分別在其 Home 目錄下建立此結構。

C:\Users\<USERNAME>\
└── LLM_Coding_Agent\
    ├── .env                <-- [關鍵隔離] 存放該使用者的 GitLab PAT 和初始設定
    │
    ├── Agent_Scripts\      <-- [獨立] Python Agent 核心程式碼
    │   └── agent_api.py    <-- Flask API 啟動檔 (程式碼附於文件末尾)
    │
    ├── CSharp_Project\     <-- [獨立] C# 專案操作區
    │   ├── .git/
    │   └── WinFormApp/     <-- 實際的 C# 程式碼
    │
    └── venv\               <-- [獨立] Python 虛擬環境

💻 第三部分:詳細指令與驗證機制

階段 I:基礎設施準備 (系統共享)

執行身分: 具有管理員權限的 Windows 帳號。

步驟

環境

指令 / 操作

驗證機制 (Validation)

I.1

GUI

安裝 Docker Desktop

下載並安裝 Docker Desktop for Windows。

注意:安裝完成後請確保設定中開啟 WSL 2 backend。

PowerShell: docker --version

應顯示 Docker版本號。

I.2

GUI

安裝 Ollama (Desktop)

下載並安裝 Ollama Windows版。

PowerShell: ollama -v

應顯示 Ollama 版本號。

I.3

PowerShell

安裝開發工具

winget install Microsoft.Git -e

winget install Microsoft.DotNet.SDK.8 -e

PowerShell: git --version

dotnet --list-sdks

確認皆已安裝。

I.4

PowerShell

建立資料目錄

mkdir C:\gitlab_data

檔案總管: 確認 C 槽有 gitlab_data 資料夾。

階段 II:GitLab 與模型配置 (系統共享)

執行身分: 管理員或任何能執行 Docker 的帳號。

步驟

環境

指令 / 操作

驗證機制 (Validation)

II.1

PowerShell

啟動 GitLab 容器

docker run --detach --hostname localhost --publish 8080:80 --name gitlab --restart always --volume C:/gitlab_data/config:/etc/gitlab --volume C:/gitlab_data/logs:/var/log/gitlab --volume C:/gitlab_data/data:/var/opt/gitlab gitlab/gitlab-ce:latest

PowerShell: docker ps

應看到 gitlab 容器狀態為 Up

II.2

Browser

配置 GitLab (需等待 5-15分鐘啟動)

1. 開啟 http://localhost:8080

2. 設定 root 密碼並登入。

3. 關鍵: 進入 User Settings -> Access Tokens,生成一個 Personal Access Token (PAT),權限勾選 api

瀏覽器: 成功登入並取得 PAT 字串 (例如 glpat-xxxxxx)。

II.3

PowerShell

下載 LLM 模型

ollama run deepseek-coder:33b-instruct

PowerShell: ollama list

應看到 deepseek-coder 模型。

階段 III:隔離工作區建置 (各自執行)

執行身分: 分別在「個人帳號」與「網域帳號」登入後執行。

步驟

環境

指令 / 操作

驗證機制 (Validation)

III.1

PowerShell

建立目錄與虛擬環境

cd ~

mkdir LLM_Coding_Agent; cd LLM_Coding_Agent

mkdir Agent_Scripts CSharp_Project

python -m venv venv

.\venv\Scripts\Activate.ps1

PowerShell: 命令列前方出現 (venv)

III.2

(venv) PowerShell

安裝 Python 套件

pip install flask langchain langchain-ollama python-dotenv pyodbc requests

PowerShell: 無錯誤訊息,顯示安裝成功。

III.3

Editor

建立 .env 設定檔

LLM_Coding_Agent 根目錄建立 .env 檔案,內容如下:

GITLAB_URL=http://localhost:8080

GITLAB_PAT=你的_專屬_PAT_貼在這裡

SQL_SERVER=(localdb)\MSSQLLocalDB

手動檢查: 確認檔案存在,且 PAT 是該帳號專屬的。

III.4

Editor

部署 Agent 程式碼

本文末尾附錄的 Python 程式碼存檔為 Agent_Scripts\agent_api.py

手動檢查: 確認檔案已建立。

階段 IV:C# 專案初始化 (各自執行)

執行身分: 分別在兩個帳號下執行。

步驟

環境

指令 / 操作

驗證機制 (Validation)

IV.1

PowerShell

建立 C# 專案

cd LLM_Coding_Agent\CSharp_Project

dotnet new winforms -n WinFormApp

PowerShell: dir 應看到 WinFormApp 資料夾。

IV.2

PowerShell

Git 初始化

git init

git add .

git commit -m "Initial structure"

(註:不需要手動加 remote,Agent 會自動處理)

PowerShell: git log 應看到一筆 commit。

階段 V:啟動服務與執行 (日常操作)

執行身分: 當下要進行開發的帳號。

步驟

環境

指令 / 操作

驗證機制 (Validation)

V.1

PowerShell

啟動 Agent API (後端)

cd LLM_Coding_Agent

.\venv\Scripts\Activate.ps1

python Agent_Scripts\agent_api.py

PowerShell: 顯示 Running on http://127.0.0.1:5000

V.2

PowerShell

啟動 Open WebUI (前端)

docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

PowerShell: docker ps 顯示 open-webui 運作中。

V.3

Browser

WebUI 操作

1. 開啟 http://localhost:3000

2. 確保已設定 Tool Calling 指向 Flask API。

3. 輸入指令:

"我要開發一個計算機功能。請先在 GitLab 建立名為 Calculator_App 的私有專案。然後在 WinFormApp/Program.cs 加入註釋 '// Start',提交到 feat-calc 分支並建立 MR。"

GitLab (localhost:8080): 看到新專案 Calculator_App 被建立,且有一個新的 Merge Request。

PowerShell (V.1視窗): 看到 Agent 依序呼叫 create_gitlab_project -> write_file -> git 等工具的 Log。

🐍 附錄:Python Agent 核心程式碼 (agent_api.py)

請將以下程式碼複製並儲存至 Agent_Scripts\agent_api.py

import os
import subprocess
from flask import Flask, request, jsonify
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import Ollama
from langchain.tools import tool
from dotenv import load_dotenv
import pyodbc
import requests
import json

# 載入 .env 檔案
load_dotenv()

# --- 設定 ---
OLLAMA_BASE_URL = "http://localhost:11434"
MODEL_NAME = "deepseek-coder:33b-instruct" 
# 設定專案根目錄位置
PROJECT_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'CSharp_Project')

# 從 .env 讀取設定
GITLAB_URL = os.getenv("GITLAB_URL")
GITLAB_PAT = os.getenv("GITLAB_PAT")
SQL_SERVER = os.getenv("SQL_SERVER")

# 初始化 Flask
app = Flask(__name__)

# 用來暫存當前操作的 GitLab Project ID
current_project_id = None

# --- 工具定義 (Tools) ---

@tool
def create_gitlab_project(name: str, description: str = "", visibility: str = "private") -> str:
    """
    使用 GitLab API 創建新專案。必須在開始新功能開發前調用此工具。
    成功後會自動將本地 Git remote 設定為新專案的 URL。
    name: 專案名稱 (如 'My-App')。
    """
    global current_project_id
    if not GITLAB_PAT or not GITLAB_URL:
        return "錯誤:缺少 GitLab PAT 或 URL。"

    url = f"{GITLAB_URL}/api/v4/projects"
    headers = {'Private-Token': GITLAB_PAT, 'Content-Type': 'application/json'}
    data = {'name': name, 'description': description, 'visibility': visibility, 'namespace_id': 1} # 預設 namespace 1 (root)
    
    try:
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        project_info = response.json()
        current_project_id = str(project_info['id'])
        repo_url = project_info['http_url_to_repo']
        
        # 更新本地 Git Remote
        try:
            subprocess.run(['git', 'remote', 'set-url', 'origin', repo_url], cwd=PROJECT_ROOT, check=True, capture_output=True)
        except subprocess.CalledProcessError:
            try:
                subprocess.run(['git', 'remote', 'add', 'origin', repo_url], cwd=PROJECT_ROOT, check=True, capture_output=True)
            except:
                pass # 忽略錯誤,可能 remote 已存在
        
        return f"專案創建成功 ID: {current_project_id}, URL: {repo_url}"
    except Exception as e:
        return f"創建專案失敗: {e}"

@tool
def execute_local_git_command(command: str) -> str:
    """執行本地 Git 命令 (如 'add .', 'commit -m "msg"'). 不含 push。"""
    try:
        result = subprocess.run(['git'] + command.split(), cwd=PROJECT_ROOT, capture_output=True, text=True, check=True)
        return f"Git 執行成功: {result.stdout}"
    except subprocess.CalledProcessError as e:
        return f"Git 錯誤: {e.stderr}"

@tool
def push_to_gitlab_remote(branch_name: str) -> str:
    """執行 'git push origin <branch>' 推送至遠端。需先 Commit。"""
    try:
        result = subprocess.run(['git', 'push', 'origin', branch_name], cwd=PROJECT_ROOT, capture_output=True, text=True, check=True)
        return f"Push 成功: {result.stdout}"
    except subprocess.CalledProcessError as e:
        return f"Push 失敗: {e.stderr}"

@tool
def write_file_to_project(filepath: str, content: str) -> str:
    """在 C# 專案中寫入檔案。filepath 為相對路徑。"""
    full_path = os.path.join(PROJECT_ROOT, filepath)
    os.makedirs(os.path.dirname(full_path), exist_ok=True)
    try:
        with open(full_path, 'w', encoding='utf-8') as f:
            f.write(content)
        return f"寫入成功: {filepath}"
    except Exception as e:
        return f"寫入失敗: {e}"

@tool
def create_gitlab_merge_request(title: str, source_branch: str, target_branch: str = "main") -> str:
    """在 GitLab 創建 Merge Request。需在 Push 後調用。"""
    if not GITLAB_PAT or not current_project_id:
        return "錯誤:缺少 PAT 或尚未創建專案 (無 Project ID)。"

    url = f"{GITLAB_URL}/api/v4/projects/{current_project_id}/merge_requests"
    headers = {'Private-Token': GITLAB_PAT, 'Content-Type': 'application/json'}
    data = {'source_branch': source_branch, 'target_branch': target_branch, 'title': title}
    
    try:
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        return f"MR 創建成功: {response.json()['web_url']}"
    except Exception as e:
        return f"MR 創建失敗: {e}"

@tool
def execute_sql_script(sql_query: str) -> str:
    """連接 SQL Server 執行查詢。"""
    if not SQL_SERVER: return "錯誤:未設定 SQL_SERVER。"
    conn_str = f"Driver={{ODBC Driver 17 for SQL Server}};Server={SQL_SERVER};Database=master;Trusted_Connection=yes;"
    try:
        conn = pyodbc.connect(conn_str)
        cursor = conn.cursor()
        cursor.execute(sql_query)
        if sql_query.strip().upper().startswith('SELECT'):
            rows = cursor.fetchall()
            conn.close()
            return f"查詢結果: {rows}"
        conn.commit()
        conn.close()
        return "SQL 執行成功。"
    except Exception as e:
        return f"SQL 錯誤: {e}"

# --- Agent 初始化 ---
def create_agent():
    llm = Ollama(model=MODEL_NAME, base_url=OLLAMA_BASE_URL)
    tools = [create_gitlab_project, execute_local_git_command, push_to_gitlab_remote, write_file_to_project, create_gitlab_merge_request, execute_sql_script]
    
    system_prompt = (
        "您是 C# 開發 Agent。請根據指令自主調用工具完成任務。"
        "若需要新專案,請務必先調用 create_gitlab_project。"
        "標準流程:建專案 -> 寫檔 -> Git Add/Commit -> Git Push -> 建立 MR。"
    )
    
    prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt),
        ("user", "{input}"),
        ("placeholder", "{agent_scratchpad}")
    ])
    
    agent = create_tool_calling_agent(llm, tools, prompt)
    return AgentExecutor(agent=agent, tools=tools, verbose=True)

agent_executor = create_agent()

# --- API Route ---
@app.route('/run_task', methods=['POST'])
def run_task():
    data = request.json
    user_input = data.get('prompt')
    if not user_input: return jsonify({"status": "error"}), 400
    try:
        response = agent_executor.invoke({"input": user_input})
        return jsonify({"status": "success", "result": response['output']})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    print(f"Agent 啟動於 C# 專案路徑: {PROJECT_ROOT}")
    app.run(host='127.0.0.1', port=5000)