2025年11月10日 星期一

在Visual Studio 2022使用提示檔協助開發-3


本文是本站《在Visual Studio 2022使用提示檔協助開發》系列文章的第三篇,介紹如何在Visual Studio 2022開發工具中,使用指示檔(instruction file)與提示檔案(Prompt files)跟Github Copilot溝通的互動步驟。

延續本站《在Visual Studio 2022使用提示檔協助開發》系列文章的第一篇第二篇建立的專案、指示檔(instruction file)與提示檔案(Prompt files)互動步過程如下:


加入提示檔案(Promptfiles)

從Visual Studio 2022開發工具「Solution Explorer」視窗方案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」>「Existing Item」項目,選取提示檔(Prompt files),它也是一個文字檔,以本文使用的「my.prompt.md」範例為例,它是一個檔案名稱後綴「.prompt」字串且副檔名為「md」的Markdown格式檔。


目前檔案內容如下列表,其中包含本文要設計專案的提示,提示檔案分為兩大區塊,表頭與內容。

l  「---」符號:是 YAML Front Matter 的開始標記,常用於 Markdown 文件的開頭,定義一些metadata

l  「mode: 'agent'」:指定執行模式為「agent」模式,代表這份指令是給自動化代理人(GitHub Copilot)使用。

l  「model: GPT-4.1」:指定要使用的 AI 模型版本為 GPT-4.1。

l  「description: 」:提供這份檔案的描述,說明這是 Copilot 的指令步驟設計檔,目的是讓 Copilot 依照步驟逐步完成程式開發。

l  「---」符號:YAML Front Matter 的結束標記。


檔案剩餘部分為提示內容,表列如下:

 

my.prompt.md

---

mode: 'agent'

model: GPT-4.1

description: 本檔案為 Copilot 指令步驟設計,請依步驟逐步完成程式開發。

---

你是高效且自主的代理人,你肯定能獨立解決問題,無需每次都向使用者詢問。

請花時間仔細思考每一個步驟 - 記得嚴格檢查你的解決方案,你必須不斷迭代直到問題被解決。且所有待辦事項皆已勾選。

不要在未完成所有步驟且確認一切運作良好之前結束回合。當你說「接著我要做 X」或「現在我要做 Y」或「我要做 X」時,你必須真的去做,而非僅說說而已。

接下來請使用繁體中文回應我。

 

#建立待辦事項Todo清單

- 根據我提供的`程式設計步驟`建立待辦事項Todo清單。

- 每一個步驟都要成為一個待辦事項。

- 每一步驟開始之前都要列出所有待辦事項。

- 建立 Markdown 格式代辦清單以追蹤。

- 每完成一項用 `[x]` 標示。

- 每次標示完成都顯示更新清單給我。

- 完成每一項目,暫停執行,確認程式碼能夠正確編譯,然後等我確認,待我回應 OK,才可進行下一步。

 

 

使用以下格式建立待辦事項Todo清單,務必使用Markdown 格式

```markdown

- [ ] 步驟1:第一步描述

- [ ] 步驟2:第二步描述

- [ ] 步驟3:第三步描述

```

 

## 程式設計步驟

- 請花時間仔細思考每一個程式設計步驟,記得嚴格檢查你的解決方案,是否符合微軟Asp.net Core 9 版的框架,要符合SOLID軟體設計原則,使用DI等設計模式。

- 思考專案與專案之間的相互參考關係,思考是否正確引用命名空間。

- 是否需要額外安裝套件以協助開發。

- 必要時利用網路搜尋相關文件、文章及論壇,研究問題。

- 每一步驟完成,列出更動的程式碼,供我參考。

 

 

### Step 1

 

`CopilotWeb` 專案設計一個 `VacationDaysCalculator` 服務,包含一個 C# 方法,輸入月份,回傳特休日數,規則如下:

 

1. 6個月以上1年未滿者,3日。

2. 1年以上2年未滿者,7日。

3. 2年以上3年未滿者,10日。

4. 3年以上5年未滿者,每年14日。

5. 5年以上10年未滿者,每年15日。

6. 10年以上者,每1年加給1日,加至30日為止。

 

#### 範例

 

| 勞工服務年資特別休假天數 | 天數 |

|--------------------------|------|

| 6個月至未滿1           | 3    |

| 滿第1                  | 7    |

| 滿第2                  | 10   |

| 滿第3                  | 14   |

| 滿第4                  | 14   |

| 滿第5                  | 15   |

| 滿第6                  | 15   |

| 滿第7                  | 15   |

| 滿第8                  | 15   |

| 滿第9                  | 15   |

| 滿第10                 | 16   |

| 滿第11                 | 17   |

| 滿第12                 | 18   |

| 滿第13                 | 19   |

| 滿第14                 | 20   |

| 滿第15                 | 21   |

| 滿第16                 | 22   |

| 滿第17                 | 23   |

| 滿第18                 | 24   |

| 滿第19                 | 25   |

| 滿第20                 | 26   |

| 滿第21                 | 27   |

| 滿第22                 | 28   |

| 滿第23                 | 29   |

| 滿第24                 | 30   |

| 滿第25                 | 30   |

 

 

---

 

### Step 2

 

`VacationDaysCalculator.Tests` 專案中,加入一個測試 `VacationDaysCalculator` 服務的程式碼。 並進行單元測試,確認所有測試案例都通過。

 

 

---

 

### Step 3

 

`CopilotWeb` 專案設計一個適用 .NET 9 Web API,名為VacationController,使用DI,利用 `VacationDaysCalculator` 服務計算特休日數並傳回。 

 

---

 

### Step 4

 

`CopilotWeb` 專案加入 Swagger 功能來測試 Web API 自行安裝相關套件。

 

---

 

### Step 5

 

`CopilotWeb` 專案註冊 Razor Page 功能,然後加入一個 Razor Page 網頁,名為Index,使用完整類別名稱存取Index對應的IndexModel

使用 Bootstrap 5.3.3 版美化畫面。 

Razor Page 網頁加入一個文字方塊輸入月數,還有一個按鈕。 

按下按鈕利用 fetch httpget 請求,傳入文字方塊的值為參數,從 Step 3 設計的 Web API 取得特休天數,顯示在按鈕下方。


使用指示檔案(Instruction files)與指示檔(Prompt files)

在「Github Copilot Chat」視窗從下方的下拉式清單方塊中,選取「Agent」模式,筆者選用泛用性高的最新OpenAI旗艦模型「GPT-4.1」來執行任務。

在「Github Copilot Chat」視窗加入指示檔案Instruction files,點選「Reference>File」,請參考下圖所示:

1:加入指示檔案Instruction files


選取指示檔案Instruction files請參考下圖所示:

2:選取指示檔Instruction files

 

加入與執行提示檔案

在「Github Copilot Chat」視窗加入提示檔案Prompt files,點選「Reference>Prompts」,請參考下圖所示:

3:加入提示檔案Prompt files

 

選取提示檔案Prompt files請參考下圖所示:

4:選取提示檔案Prompt files


接著按下執行按鈕送出提示,請參考下圖所示:

5:送出提示


由於生成式AI每次的回應都不太一樣,你的操作畫面可能會與本文描述的不相同,以下為筆者測試時Github Copilot的回應,首先它會根據提示的要求,建立「程式設計步驟」待辦事項清單,請參考下圖所示:

6Github Copilot的回應

步驟一

待筆者回覆「OK」之後,Github Copilot便開始執行「步驟一」,並撰寫了一個新的「VacationDaysCalculator.cs」檔案,請參考下圖所示:

7 Github Copilot的回應


為了驗證它寫出的程式有符合我們的設計要求,筆者在當下的「Github Copilot Chat」視窗下達提示進行複驗:

照目前邏輯滿第20年會休幾天


務必確認
Github Copilot的回應結果是正確的,請參考下圖所示:

8 Github Copilot的回應


若回應不正確,可以持續與Github Copilot溝通,請它修訂程式碼來符合需求。若複驗沒問題,可以按下「Keep」按鈕接受變更,請參考下圖所示:

9 Github Copilot的回應


以下列表是Github Copilot產出的程式碼,從程式中可以看到Github Copilot根據我們的指示檔(Instruction files)中要求的的風格來撰寫程式碼,例如:「 為每個函式撰寫清楚且簡潔的註解」。

VacationDaysCalculator.cs

using System;

namespace CopilotWeb.Services

{

    /// <summary>

    /// 計算特休日數的服務。

    /// </summary>

    public class VacationDaysCalculator : IVacationDaysCalculator

    {

        /// <summary>

        /// 根據工作月數計算特休日數。

        /// </summary>

        /// <param name="months"> 工作月數 </param>

        /// <returns> 特休日數 </returns>

        /// <exception cref="ArgumentOutOfRangeException"> 當月數小於0時拋出 </exception>

        public int GetVacationDays( int months )

        {

            if ( months < 0 )

            {

                throw new ArgumentOutOfRangeException( nameof(months), "月數不可為負值。" );

            }

 

            if ( months < 6 )

            {

                return 0;

            }

            if ( months < 12 )

            {

                return 3;

            }

            int years = months / 12;

            if ( years == 1 )

            {

                return 7;

            }

            if ( years == 2 )

            {

                return 10;

            }

            if ( years >= 3 && years < 5 )

            {

                return 14;

            }

            if ( years >= 5 && years < 10 )

            {

                return 15;

            }

            if ( years >= 10 )

            {

                int days = 15 + ( years – 9 );

                return days > 30 ? 30 : days;

            }

            return 0;

        }

    }

 

    /// <summary>

    /// 特休日數計算服務介面。

    /// </summary>

    public interface IVacationDaysCalculator

    {

        /// <summary>

        /// 根據工作月數計算特休日數。

        /// </summary>

        /// <param name="months"> 工作月數 </param>

        /// <returns> 特休日數 </returns>

        int GetVacationDays( int months );

    }

}


步驟二

當「步驟一」順利完成後,我們就可以請Github Copilot進行下一個步驟,在「Github Copilot Chat」視窗下提示,進行下一個步驟:

OK進行Step 2


第二步驟要求Github Copilot撰寫單元測試程式碼,請參考下圖所示:

10 Github Copilot的回應


我們只要扮演複驗程式是否正確的角色,繼續與Github Copilot溝通,然後接受它產出的程式碼,請參考下圖所示:

11 Github Copilot的回應


在這個步驟中產生的「VacationDaysCalculatorTests.cs」測試程式如下列表:

VacationDaysCalculatorTests.cs

using CopilotWeb.Services;

using Xunit;

 

namespace CopilotWeb.Tests

{

    /// <summary>

    /// VacationDaysCalculator 單元測試。

    /// </summary>

    public class VacationDaysCalculatorTests

    {

        private readonly IVacationDaysCalculator _calculator = new VacationDaysCalculator();

 

        [Theory]

        [InlineData( 0, 0 )]

        [InlineData( 5, 0 )]

        [InlineData( 6, 3 )]

        [InlineData( 11, 3 )]

        [InlineData( 12, 7 )]

        [InlineData( 23, 7 )]

        [InlineData( 24, 10 )]

        [InlineData( 35, 10 )]

        [InlineData( 36, 14 )]

        [InlineData( 47, 14 )]

        [InlineData( 48, 14 )]

        [InlineData( 59, 14 )]

        [InlineData( 60, 15 )]

        [InlineData( 119, 15 )]

        [InlineData( 120, 16 )]

        [InlineData( 132, 17 )]

        [InlineData( 144, 18 )]

        [InlineData( 156, 19 )]

        [InlineData( 168, 20 )]

        [InlineData( 180, 21 )]

        [InlineData( 192, 22 )]

        [InlineData( 204, 23 )]

        [InlineData( 216, 24 )]

        [InlineData( 228, 25 )]

        [InlineData( 240, 26 )]

        [InlineData( 252, 27 )]

        [InlineData( 264, 28 )]

        [InlineData( 276, 29 )]

        [InlineData( 288, 30 )]

        [InlineData( 300, 30 )]

        public void GetVacationDays_ReturnsExpectedDays( int months, int expectedDays )

        {

            var result = _calculator.GetVacationDays (months );

            Assert.Equal( expectedDays, result );

        }

 

        [Fact]

        public void GetVacationDays_NegativeMonths_ThrowsException()

        {

            Assert.Throws<ArgumentOutOfRangeException>( () => _calculator.GetVacationDays( -1 ) );

        }

    }

}

 

步驟三

在「Github Copilot Chat」視窗下提示,進行下一個步驟:

OK

 

執行結果請參考下圖所示:

12 Github Copilot的回應


這階段產生的「VacationController.cs」程式碼參考如下:

VacationController.cs

using Microsoft.AspNetCore.Mvc;

using CopilotWeb.Services;

 

namespace CopilotWeb.Controllers

{

    /// <summary>

    /// 提供特休日數查詢的 API

    /// </summary>

    [ApiController]

    [Route( "api/[controller]" )]

    public class VacationController : ControllerBase

    {

        private readonly IVacationDaysCalculator _calculator;

 

        /// <summary>

        /// 建構子,注入特休日數計算服務。

        /// </summary>

        /// <param name="calculator"> IVacationDaysCalculator 實例 </param>

        public VacationController( IVacationDaysCalculator calculator )

        {

            _calculator = calculator;

        }

 

        /// <summary>

        /// 根據工作月數取得特休日數。

        /// </summary>

        /// <param name="months"> 工作月數 </param>

        /// <returns> 特休日數 </returns>

        [HttpGet]

        public ActionResult<int> GetVacationDays( [FromQuery] int months )

        {

            try

            {

                var days = _calculator.GetVacationDays( months );

                return Ok( days );

            }

            catch ( ArgumentOutOfRangeException ex )

            {

                return BadRequest( ex.Message );

            }

        }

    }

}


這階段產生的「Program.cs」程式碼參考如下,叫用「AddScoped<T>」方法註冊服務:

Program.cs

var builder = WebApplication.CreateBuilder( args );

 

// Add services to the container.

builder.Services.AddControllers();

// 註冊特休日數計算服務(DI

builder.Services.AddScoped<CopilotWeb.Services.IVacationDaysCalculator, CopilotWeb.Services.VacationDaysCalculator>();

// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi

builder.Services.AddOpenApi();

 

var app = builder.Build();

 

// Configure the HTTP request pipeline.

if ( app.Environment.IsDevelopment() )

{

    app.MapOpenApi();

}

 

app.UseHttpsRedirection();

 

app.UseAuthorization();

 

app.MapControllers();

 

app.Run();


步驟四

在「Github Copilot Chat」視窗下提示,進行下一個步驟:

OK


執行結果請參考下圖所示:

13 Github Copilot的回應

 

在這個階段中Github Copilot自動安裝了「Swashbuckle.AspNetCore」套件,並在「Program.cs」程式碼中註冊Swagger服務,參考如下:

Program.cs

var builder = WebApplication.CreateBuilder( args );

 

// Add services to the container.

builder.Services.AddControllers();

// 註冊特休日數計算服務(DI

builder.Services.AddScoped<CopilotWeb.Services.IVacationDaysCalculator, CopilotWeb.Services.VacationDaysCalculator>();

// Swagger/OpenAPI 註冊

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();

 

var app = builder.Build();

 

// Configure the HTTP request pipeline.

if ( app.Environment.IsDevelopment() )

{

    app.UseSwagger();

    app.UseSwaggerUI();

}

 

app.UseHttpsRedirection();

 

app.UseAuthorization();

 

app.MapControllers();

 

app.Run();

 

我們可以執行這個網站,手動驗證看看是否一切符合需求,按CTRL+F5執行目前網站,預設Visual Studio 2022開發工具會啟動開發階段的Web伺服器動態給一個埠號,請參考下圖所示:

14 Github Copilot的回應


開啟瀏覽器,輸入網站所在URL,後綴「Swagger」,例如:

https://localhost:7234/swagger


執行結果請參考下圖所示:

15:驗證Swagger


使用Swagger圖型介面測試特休功能是否正常,請參考下圖所示:

16 使用Swagger測試Web API


步驟五

在「Github Copilot Chat」視窗下提示,進行下一個步驟:

OK


執行結果請參考下圖所示:

17 Github Copilot的回應

 

這階段產生的「Index.cshtml」程式碼參考如下:

Index.cshtml

@page

@model CopilotWeb.Pages.IndexModel

@{

    ViewData["Title"] = "特休日數查詢";

}

 

<!DOCTYPE html>

<html lang="zh-Hant">

<head>

    <meta charset="utf-8" />

    <meta name = "viewport" content = "width=device-width, initial-scale=1" />

    <title> @ViewData["Title"] </title>

    <link href = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel = "stylesheet" crossorigin = "anonymous">

</head>

<body>

    <div class = "container py-5">

        <h1 class = "mb-4"> 特休日數查詢 </h1>

        <div class = "mb-3">

            <label for = "monthsInput" class = "form-label"> 請輸入工作月數: </label>

            <input type = "number" class = "form-control" id = "monthsInput" min = "0" placeholder = "例如:48">

        </div>

        <button id = "queryBtn" class = "btn btn-primary mb-3"> 查詢特休日數 </button>

        <div id = "result" class = "mt-3"> </div>

    </div>

    <script>

        document.getElementById( 'queryBtn' ).addEventListener( 'click', async function () {

            const months = document.getElementById( 'monthsInput' ).value;

            const resultDiv = document.getElementById( 'result' );

            resultDiv.innerHTML = '';

            if (!months || months < 0) {

                resultDiv.innerHTML = '<div class="alert alert-warning">請輸入有效的月數。</div>';

                return;

            }

            try {

                const response = await fetch( `/api/vacation?months=${months}` );

                if ( response.ok ) {

                    const days = await response.json();

                    resultDiv.innerHTML = `<div class="alert alert-success">特休日數:<strong>${days}</strong> </div>`;

                } else {

                    const msg = await response.text();

                    resultDiv.innerHTML = `<div class="alert alert-danger">${msg}</div>`;

                }

            } catch (e) {

                resultDiv.innerHTML = '<div class="alert alert-danger">查詢失敗,請稍後再試。</div>';

            }

        });

    </script>

</body>

</html>

 

網站目前已經開發完成,按CTRL+F5執行目前網站,預設將顯示網站首頁,請參考下圖所示:

18 特休查詢網站

 

總結

Visual Studio 2022開發工具 中運用提示檔(prompt file與指示檔(instruction file來整合生成式 AI,不僅能讓開發過程更快速、更有條理,也能確保專案的長期品質與一致性。這樣的方式讓AI真正從「輔助工具」進化為「開發流程的一部分」,使得開發者能更專注於解決核心業務問題,而不是浪費時間在重複性或低層次的工作上。隨著這項整合方式的成熟與普及,它勢必將成為未來軟體開發中不可或缺的利器。

 


0 意見:

張貼留言