ChatGPT編程秀-7: 別拿編程語言不當語言

TDD第一步就卡住了

寫完小工具光涂,這一篇回來我們接著寫我們的程序忆某。再看一眼我們的程序運行視圖:

07-01-final-process-view.png

帶著TDD思路衡载,我進入了 ejs_and_yaml_dsl_loader 這個模塊允乐,這塊因為我切的不是很好篓吁,所以這代碼有點難寫茫因,不過沒關(guān)系,正好我們實際工作大部分的場景都是這樣的杖剪《逞海看看我們在這里能玩出點什么來驰贷。

那么這次的需求呢是這個樣子的,我們需要把ejs模版引擎渲染出的yaml轉(zhuǎn)換為json洛巢,那么我們這個功能會非常復(fù)雜括袒,所以我們沒有以上來就去做ejs的部分。而是先從yaml的部分入手稿茉。如果只是yaml轉(zhuǎn)json的話其實沒什么意思锹锰,一行代碼就實現(xiàn)了,關(guān)鍵是yaml里面有一個語法叫做json指針漓库。

這個東西很重要恃慧。我們之前畫的那個圖還是有一點點。簡化的我們只畫了豎向的分層渺蒿。但是在橫向上痢士,如果你要實現(xiàn)像我們說的,按照規(guī)模進行分解的話茂装,如果一個case比較簡單的話怠蹂,還比較好辦。通常我們的case會變得越來越復(fù)雜训唱。可能就需要把它拆成多個挚冤。DSL文件况增,然后最后通過一個dsl把它組裝起來。為了實現(xiàn)這種組裝的能力呢训挡,我們就要支持類似的語法澳骤,那么壓帽里的jason指針的恰好是這樣一個很好用的語法。當然他有他的一些缺陷澜薄,他可能不支持動態(tài)的參數(shù)为肮,這個是我們后面的擴展。具體的json指針語法什么樣的肤京?一會大家看我們的prompt就知道了颊艳。

之所以需要這個語法以及它的擴展語法,是因為還記得咱們說的我們需要一個派發(fā)引擎嗎忘分? 其實派發(fā)與組合不過是動態(tài)和靜態(tài)的區(qū)別棋枕。派發(fā)引擎也需要一套組合邏輯。而我們現(xiàn)在做這個功能就是為未來我們可能能實現(xiàn)一個派發(fā)引擎積累一些經(jīng)驗妒峦。

而我們使用的庫呢重斑,他不是原生支持JSON指針。他不支持呢肯骇,也挺好窥浪,因為我們后面會擴展這個功能祖很。如果他支持的話,我們自定義的語法擴展起來反而很麻煩漾脂。背景知識就是這些假颇,我們開始實現(xiàn),下面試提問prompt:

我要用nodejs實現(xiàn)一個yaml的loader函數(shù)符相,可以讀入yaml轉(zhuǎn)為json拆融,并且可以將其中JSON指針語法轉(zhuǎn)換為具體的值.

這是base.yml:

- item:
    $ref: "/refed.yml#simple_value_keya"
- item:
    keya: 
    $ref: "/refed.yml#simple_value_keya"

這是在同一路徑的refed.yml

simple_value_keya: value_of_keya

兩個yaml文件都在一個文件夾里,比如叫yaml
而js文件與yaml文件夾同級

我期望的輸出為:

[{
    "item":"value_of_keya"
},{
"item":
        {
            "keya": "value_of_keya"
        }
}]

我還希望:

  1. 這個函數(shù)是async的啊终。
  2. 讀取文件的fs镜豹,要使用const fs = require('fs/promise')引入。
  3. 用js-yaml庫解析yaml蓝牲。
  4. 解析JSON指針的過程需要被封裝為一個專門的函數(shù)趟脂。
    代碼要怎么實現(xiàn)?(直接給出最后的代碼就可以)

結(jié)果給我生成了很長的代碼:

const fs = require('fs/promises');
const yaml = require('js-yaml');

/**
* 從JSON指針中獲取對應(yīng)的值
* @param {Object} obj - 要獲取值的對象
* @param {string} pointer - JSON指針
* @returns {any} 對應(yīng)的值
*/
function getValueByPointer(obj, pointer) {
const parts = pointer.split('/').slice(1); // 去掉開頭的'#'字符例衍,然后拆分為路徑的數(shù)組
return parts.reduce((acc, cur) => acc[cur], obj); // 依次按路徑訪問對象屬性
}

/**
* 讀取指定路徑的YAML文件昔期,并解析其中的JSON指針
* @param {string} path - YAML文件的路徑
* @returns {Promise<any>} 解析后的JSON對象
*/
async function loadYamlFile(path) { 
const content = await fs.readFile(path, 'utf8'); // 讀取文件內(nèi)容
const data = yaml.load(content); // 解析YAML為JSON對象

// 遍歷JSON對象,查找$ref屬性
const processRef = async (obj) => {
    if (typeof obj === 'object' && obj !== null) { // 如果是對象
    if ('$ref' in obj) { // 如果包含$ref屬性
        const refPath = obj.$ref.split('#')[0]; // 獲取引用文件路徑
        const pointer = obj.$ref.split('#')[1]; // 獲取JSON指針

        const refData = await loadYamlFile(refPath); 
        const value = getValueByPointer(refData, `#${pointer}`); // 獲取引用文件中對應(yīng)JSON指針的值
        return value;
    } else { // 如果不包含$ref屬性佛玄,遞歸處理子屬性
        for (const prop in obj) {
        obj[prop] = await processRef(obj[prop]);
        }
    }
    }
    return obj;
};

return await processRef(data); // 處理JSON對象中的$ref屬性
}

// 調(diào)用loadYamlFile函數(shù)并輸出結(jié)果
(async () => {
const data = await loadYamlFile('./yaml/base.yml');
console.log(JSON.stringify(data, null, 2));
})();

不出意外的硼一,這個代碼他是錯的,我讓他反復(fù)生成了很多次梦抢,結(jié)果總是差那么點般贼,說實在的,差那么點我自己手改也不是不能改奥吩,但是勝負欲起來了哼蛆。不能完全生成這個事還是有點讓我感覺不爽,考慮到如果真的在實際場景中使用的話霞赫,這50行的長度也寫不了太復(fù)雜的東西腮介,但是一到這個長度,就沒法細調(diào)整了太致命了端衰,這又不是人叠洗,我不能指著這一行跟他說,這里有問題……嗯旅东?指著這一行惕味?我頓時靈光一閃。

破門而入玉锌,針對性反饋

在日常開發(fā)中名挥,我們是怎么通過文字指出某一行有問題呢?答案再明顯不過了:通過注釋主守。而且禀倔,下面兩個注釋已經(jīng)是約定俗成的使用方式了:

  • // TODO: 表示后續(xù)需要新增的功能榄融,或其他任務(wù)項
  • // FIXME: 表示這里有Bug要修復(fù)

使用這兩個注釋,你甚至不用過多解釋救湖,你只要告訴他你用這個注釋標了出來愧杯,讓他按要求修改即可。

所以我就這么給他說:

下面代碼不能滿足我的需求鞋既,我會用//TODO: 來標記問題所在行

const fs = require('fs/promises');
const yaml = require('js-yaml');

/**
* 從JSON指針中獲取對應(yīng)的值
* @param {Object} obj - 要獲取值的對象
* @param {string} pointer - JSON指針
* @returns {any} 對應(yīng)的值
*/
function getValueByPointer(obj, pointer) {
const parts = pointer.split('/').slice(1); // 去掉開頭的'#'字符力九,然后拆分為路徑的數(shù)組
return parts.reduce((acc, cur) => acc[cur], obj); // 依次按路徑訪問對象屬性
}

/**
* 讀取指定路徑的YAML文件,并解析其中的JSON指針
* @param {string} path - YAML文件的路徑
* @returns {Promise<any>} 解析后的JSON對象
*/
async function loadYamlFile(path) { //TODO: 這個path參數(shù)需要作為遞歸讀取時的的workdir邑闺,具體需求見下一個TODO
const content = await fs.readFile(path, 'utf8'); // 讀取文件內(nèi)容
const data = yaml.load(content); // 解析YAML為JSON對象

// 遍歷JSON對象跌前,查找$ref屬性
const processRef = async (obj) => {
    if (typeof obj === 'object' && obj !== null) { // 如果是對象
    if ('$ref' in obj) { // 如果包含$ref屬性
        const refPath = obj.$ref.split('#')[0]; // 獲取引用文件路徑
        const pointer = obj.$ref.split('#')[1]; // 獲取JSON指針

        const refData = await loadYamlFile(refPath); //TODO: refPath 通常是相對于當前yaml文件的,需要拼接一個指定的前綴作才是正確的路徑陡舅,這個前綴通常是path參數(shù)自己的directory路徑前綴抵乓,比如"./yaml/base.yaml"則是"./yaml"
        const value = getValueByPointer(refData, `#${pointer}`); // 獲取引用文件中對應(yīng)JSON指針的值
        return value;
    } else { // 如果不包含$ref屬性,遞歸處理子屬性
        for (const prop in obj) {
        obj[prop] = await processRef(obj[prop]);
        }
    }
    }
    return obj;
};

return await processRef(data); // 處理JSON對象中的$ref屬性
}

// 調(diào)用loadYamlFile函數(shù)并輸出結(jié)果
(async () => {
const data = await loadYamlFile('./yaml/base.yml');
console.log(JSON.stringify(data, null, 2));
})();

上面代碼靶衍,這一行寫錯了:
const refPath = path.resolve(workdir, obj.$ref.split('#')[0]); // 獲取引用文件路徑
應(yīng)該用path.join

給我完整的代碼

通過這樣的方式灾炭,我初步到了我想要的代碼。之所以用TODO而不用FIXME颅眶,是因為我站在他的視角蜈出,把這個場景定義為了擴展新功能,而不是修bug涛酗。說某一行寫錯那個確實應(yīng)該用FIXME铡原,但是我怕混在一起會出錯,而且后面已經(jīng)有注釋了煤杀,我不知道刪掉好不好眷蜈,畢竟注釋也是幫他理解我代碼的一種方式沪哺,所以單拎出來說了沈自。

這個玩法不見得要那么精準,有的時候可能代碼太復(fù)雜了辜妓,你可能看不出來哪里有Bug枯途,畢竟不是你寫的,也很正常籍滴,但是通過調(diào)試或者失敗的測試數(shù)據(jù)酪夷,你能收斂到一個函數(shù)或者一個代碼塊,也可以通過這個方式來編寫prompt孽惰。

比如下面這個:

給下面代碼種FIXME標記的函數(shù)處有一些bug:

module.exports = function render_my_yaml_dsl(data){
    const vm = require('vm');

    // 定義一個函數(shù)用于渲染字符串模板
    function render_string_template(originalScriptTemplate, intention) {
        const execScriptTemplate = "`" + originalScriptTemplate + "`";
        const script = new vm.Script(execScriptTemplate);
        const execScript = script.runInNewContext(intention);
        // console.debug(execScript);
        return execScript;
    }

    // 定義一個函數(shù)用于展開屬性組合
    function expand_attributes(attributes) { // FIXME: 這個函數(shù)有bug
        const result = [];
        attributes.forEach(obj => {
            Object.values(obj).forEach(val => {
                if (Array.isArray(val)) {
                    val.forEach(v => {
                        result.push({ ...obj, [Object.keys(obj).find(key => obj[key] === val)]: v });
                    });
                } else {
                    result.push(obj);
                }
            });
        });
        return result;
    }


    const polys = [];

    for (const poly of data.poly) {
        const { template_prompt, ...other } = poly;
        const { template, meta } = template_prompt;

        const variableGroups = expand_attributes(meta);
        const prompts = variableGroups.map(variables => render_string_template(template, variables));

        for (const prompt of prompts) {
            polys.push({ prompt, ...other });
        }
    }

    const result = polys.map(poly => ({ ...data.base, ...poly }));
    return result;
}

給定的輸入:
//....省略json數(shù)據(jù)

期望的輸出應(yīng)該是:
//....省略json數(shù)據(jù)

而實際上是把數(shù)組里唯一的元素重復(fù)了8遍晚岭,
我需要修正這個錯誤,但同時勋功,對于給定的輸入:
//....省略json數(shù)據(jù)

我還希望得到輸出
//....省略json數(shù)據(jù)

結(jié)合這兩個需求坦报,請問代碼哪里有錯誤库说?代碼應(yīng)該怎么寫?

上面我省略掉了輸入輸出的數(shù)據(jù)內(nèi)容片择,方便大家聚焦于我在代碼上標記了FIXME(看潜的,這個prompt對人也工作_)。這里是我寫完ejs_and_yaml_dsl_loader之后字管,把所有代碼集成起來運行的時候發(fā)現(xiàn)了一個bug啰挪,但是我也不知道bug是什么?(其實是懶得去看嘲叔,用這個玩意久了亡呵,人真的是會變懶)所以我直接讓他告訴我Bug是什么,然后怎么改借跪,我來評估它的方案政己,在評估方案的過程中我就搞明白了bug是什么。這個效率可高了很多掏愁。

這個技巧不僅可以用于編程領(lǐng)域歇由。在編程領(lǐng)域呢,我們?nèi)×藗€巧果港,恰好有注釋和兩個配合注釋使用的關(guān)鍵字以表達我們的意圖沦泌,這些東西我們不用告訴ChatGPT,它已經(jīng)學(xué)習寫程序的時候?qū)W過了辛掠。如果是在編程之外谢谦,可能我們要教他我們使用的標記是什么意思。
比如萝衩,我前一陣跟朋友們討論要設(shè)計一個ChatGPT編程秀回挽,在今天這個時代了,我們就想讓ChatGPT幫我們設(shè)計猩谊,于是我們問:

我準備進行一個ChatGPT編程秀千劈,給大家展示怎么用ChatGPT進行編程,時間為一個小時牌捷,可不可以給我一個編程秀的設(shè)計墙牌,并且附上時間安排.

于是我得到了下面的輸出:

ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(10 分鐘)
介紹 ChatGPT,包括其基本原理暗甥、應(yīng)用場景喜滨、優(yōu)缺點等。
演示如何使用 OpenAI API 調(diào)用 ChatGPT撤防。
以一個簡單的例子說明 ChatGPT 的使用虽风,比如生成一句話。
階段 2:生成文本(20 分鐘)
介紹如何使用 ChatGPT 生成文本,包括如何控制生成文本的長度辜膝、樣式等陌凳。
演示如何用 ChatGPT 生成一篇文章,比如一篇新聞稿内舟。
演示如何用 ChatGPT 生成一組對話合敦,比如模擬一次客服對話。
階段 3:生成代碼(20 分鐘)
介紹如何使用 ChatGPT 生成代碼验游,包括如何控制生成代碼的復(fù)雜度充岛、風格等。
演示如何用 ChatGPT 生成一段簡單的代碼耕蝉,比如一個打印 "Hello, World!" 的程序崔梗。
演示如何用 ChatGPT 生成一段復(fù)雜的代碼,比如一個排序算法的實現(xiàn)垒在。
階段 4:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié)蒜魄,回答關(guān)于 ChatGPT 的任何問題。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景场躯。
感謝觀眾的收看谈为。

很明顯,我們是個編程秀踢关,所以我們不需要階段2伞鲫,所以我說:

這是一個編程秀,所以只要設(shè)計編程的環(huán)節(jié)就可以了

然后他回復(fù):

ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(5 分鐘)
簡單介紹 ChatGPT 的基本原理和應(yīng)用場景签舞。
階段 2:生成文本(20 分鐘)
演示如何使用 ChatGPT 生成一段文章秕脓,比如一篇新聞稿。
演示如何使用 ChatGPT 生成一組對話儒搭,比如模擬一次客服對話吠架。
階段 3:生成代碼(25 分鐘)
演示如何使用 ChatGPT 生成一段簡單的代碼,比如一個打印 "Hello, World!" 的程序搂鲫。
演示如何使用 ChatGPT 生成一段復(fù)雜的代碼傍药,比如一個排序算法的實現(xiàn)。
階段 4:優(yōu)化代碼生成(10 分鐘)
介紹如何調(diào)整 ChatGPT 的參數(shù)來優(yōu)化生成的代碼質(zhì)量默穴。
演示如何優(yōu)化前面演示的代碼生成怔檩。
階段 5:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié)褪秀,回答關(guān)于 ChatGPT 的任何問題蓄诽。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景。
感謝觀眾的收看媒吗。

可以看到仑氛,并沒有刪除,這可能是大多數(shù)人在面臨對長文本進行反饋時都會面臨的尷尬了,駕馭不住ChatGPT锯岖,非常的難受介袜。
于是我這樣做:

我會用代碼注釋的形式在內(nèi)容上標記給你反饋 ,比如"http:// FIXME: "表示這里有問題出吹,冒號后面會跟隨我要修改的意圖遇伞。下面是我的輸入:
ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(5 分鐘)
簡單介紹 ChatGPT 的基本原理和應(yīng)用場景。
階段 2:生成文本(20 分鐘) // FIXME: 我不需要這個階段2捶牢,
演示如何使用 ChatGPT 生成一段文章鸠珠,比如一篇新聞稿。
演示如何使用 ChatGPT 生成一組對話秋麸,比如模擬一次客服對話渐排。
階段 3:生成代碼(25 分鐘)
演示如何使用 ChatGPT 生成一段簡單的代碼,比如一個打印 "Hello, World!" 的程序灸蟆。
演示如何使用 ChatGPT 生成一段復(fù)雜的代碼驯耻,比如一個排序算法的實現(xiàn)。
階段 4:優(yōu)化代碼生成(10 分鐘)
介紹如何調(diào)整 ChatGPT 的參數(shù)來優(yōu)化生成的代碼質(zhì)量炒考。
演示如何優(yōu)化前面演示的代碼生成可缚。
階段 5:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié),回答關(guān)于 ChatGPT 的任何問題斋枢。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景城看。
感謝觀眾的收看。

就得到了這樣的輸出:

ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(5 分鐘)
簡單介紹 ChatGPT 的基本原理和應(yīng)用場景杏慰。
階段 2:生成代碼(35 分鐘)
演示如何使用 ChatGPT 生成一段簡單的代碼测柠,比如一個打印 "Hello, World!" 的程序。
演示如何使用 ChatGPT 生成一段復(fù)雜的代碼缘滥,比如一個排序算法的實現(xiàn)轰胁。
介紹如何調(diào)整 ChatGPT 的參數(shù)來優(yōu)化生成的代碼質(zhì)量。
演示如何優(yōu)化前面演示的代碼生成朝扼。
階段 3:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié)赃阀,回答關(guān)于 ChatGPT 的任何問題。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景擎颖。
感謝觀眾的收看榛斯。

是不是掌控感就強了許多?TODO也是可以用的搂捧,比如:

我會用代碼注釋的形式在內(nèi)容上標記給你反饋 驮俗,比如"http:// TODO: "表示我希望你改進的點,冒號后面會跟隨我要達成的效果允跑。下面是我的輸入:
ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(5 分鐘)
簡單介紹 ChatGPT 的基本原理和應(yīng)用場景王凑。
階段 2:生成代碼(35 分鐘)// TODO: 我希望整個階段是用一個例子串起來的搪柑,請幫我設(shè)計一個具體的例子來進行這個階段的演示,并重新設(shè)計這個階段的子步驟
演示如何使用 ChatGPT 生成一段簡單的代碼索烹,比如一個打印 "Hello, World!" 的程序工碾。
演示如何使用 ChatGPT 生成一段復(fù)雜的代碼,比如一個排序算法的實現(xiàn)百姓。
介紹如何調(diào)整 ChatGPT 的參數(shù)來優(yōu)化生成的代碼質(zhì)量渊额。
演示如何優(yōu)化前面演示的代碼生成。
階段 3:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié)垒拢,回答關(guān)于 ChatGPT 的任何問題端圈。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景。
感謝觀眾的收看子库。

于是我就得到了:

ChatGPT 編程秀設(shè)計
階段 1:介紹 ChatGPT(5 分鐘)
簡單介紹 ChatGPT 的基本原理和應(yīng)用場景舱权。
階段 2:生成代碼(35 分鐘)
以一個例子串起來整個階段的演示,比如:使用 ChatGPT 生成一個簡單的數(shù)獨求解程序仑嗅。
首先演示如何使用 ChatGPT 生成一個基本的數(shù)獨求解程序宴倍,包括生成偽代碼和相應(yīng)的 Python 代碼。
然后演示如何使用 ChatGPT 生成一個更復(fù)雜的數(shù)獨求解程序仓技,包括優(yōu)化算法和生成相應(yīng)的代碼鸵贬。
最后介紹如何調(diào)整 ChatGPT 的參數(shù)來優(yōu)化生成的代碼質(zhì)量。
注意脖捻,本階段演示的例子不一定要是數(shù)獨求解程序阔逼,可以根據(jù)需要選擇其他適合的例子。
階段 3:Q&A 互動(10 分鐘)
與觀眾進行問答互動環(huán)節(jié)地沮,回答關(guān)于 ChatGPT 的任何問題嗜浮。
總結(jié)(5 分鐘)
簡要總結(jié) ChatGPT 的特點和應(yīng)用場景。
感謝觀眾的收看摩疑。

接下來我就可以基于數(shù)獨游戲的例子是不是合適跟他展開對話了危融。這種方法是不是很強大?
通過這種技巧我可以針對性的對AI給我的內(nèi)容進行反饋。

類比AI畫圖里雷袋,也有類似的技巧吉殃,叫做inpaint。比如眾所周知楷怒,AI不擅長畫手蛋勺,所以呢就有人發(fā)明了這樣的技巧,比如這是個失敗的手:

07-02-a-bad-hand-image.png

用PS涂抹一下大概的手的輪廓以表達意圖:

07-03-a-pre-inpaint-hand-image.png

然后在AI里用標記工具把這個區(qū)域涂黑鸠删,并告訴他抱完,這個區(qū)域是手:

07-04-a-inpaint-mark-hand-image.png

他就會基于我們涂抹的樣子畫一個手出來:

07-05-a-post-inpaint-hand-image.png

這里Denoising strength設(shè)置的不夠大,所以還不夠清晰冶共,但是可以看出這個意思乾蛤。

同樣的思想我們用在編程里就是上面的那個技巧了,類似于涂抹一個手的輪廓我還用過給他偽代碼捅僵,比如在后面png_info_post_inject這個模塊家卖,生成測試框架的時候我就用過:

根據(jù)1.json中的數(shù)據(jù)結(jié)構(gòu),我需要把上面三個分支就可以簡化為一個分支庙楚。

    if (given.targetFile === '1.png') {
        actualResult = await readPng(path.join(__dirname, 'cases', given.targetFile));
        assert.deepStrictEqual(actualResult, then.expectedResult);
      } else if (given.targetFile === '2.png') {
        await writePng(path.join(__dirname, 'cases', given.targetFile), 'hello', then.expectedResult);
        actualResult = await readPng(path.join(__dirname, 'cases', given.targetFile));
        assert.deepStrictEqual(actualResult, then.expectedResult);
      } else if (given.targetFile === '3.png') {
        await updatePng(path.join(__dirname, 'cases', given.targetFile), 'hello', then.expectedResult);
        actualResult = await readPng(path.join(__dirname, 'cases', given.targetFile));
        assert.deepStrictEqual(actualResult, then.expectedResult);
      }

偽代碼如下:

if(given.type!=='read'){
        await png_info[given.entrypoint](given_file_path, given_params);
}
actualResult = await readPng(given_file_path);
assert.deepStrictEqual(actualResult, then.expectedResult);

這個偽代碼執(zhí)行的時候上荡,第一次可能不讓我滿意,但是我可以根據(jù)他生成的繼續(xù)修改這段偽代碼馒闷,很快就得到了我想要的代碼酪捡。所以說,語言就是語言纳账,編程語言也是語言逛薇,也可以用在prompt里。

總結(jié)一下

本篇試圖按照TDD思路繼續(xù)寫程序疏虫,但第一步就遇到生成的代碼有問題的窘境永罚。

然后,我們就發(fā)明了一種新技巧:通過在代碼中使用注釋(如 // TODO: 和 // FIXME:)來指出問題所在卧秘,以便更好地與ChatGPT進行交互呢袱。這樣我們就可以針對性的對AI的內(nèi)容進行反饋。

這種技巧不僅適用于編程領(lǐng)域翅敌,還可以應(yīng)用于其他領(lǐng)域的文本生成羞福。例如,在設(shè)計一個編程秀時蚯涮,我們也可以通過使用TODO和FIXME注釋來對長文本進行反饋治专,從而更好地控制輸出。

接著我們類比了AI畫圖中的類似技巧:inpaint遭顶,舉例我們可以通過偽代碼來扮演inpaint時用輪廓給圖片生成AI反饋的方式看靠,來給AI進行反饋。

所以可以看到液肌,別拿編程語言不當語言挟炬。很多人都在按照比較弱的產(chǎn)品經(jīng)理跟程序員交流的方式跟AI交流,并以此幻想說未來可能不需要程序員了嗦哆,但其實這種交流方式是很糟糕的谤祖,稍微專業(yè)點的產(chǎn)品經(jīng)理也會有很多手段給程序員提供更精準的反饋,更何況程序員自己讓AI生成代碼的時候呢老速?

所以粥喜,當文本過長的時候,我們要學(xué)會破門而入橘券,直接對長文本進行反饋额湘。而不是很蠢的只是站在文本的外面卿吐,靠間接的描述來試圖反饋的更精準,我們要明白锋华,語言就是語言嗡官,AI生成的內(nèi)容也是語言,編程語言也是語言毯焕,甚至我們發(fā)明的DSL也是語言衍腥,只要是語言,大語言模型的AI就能學(xué)會纳猫,就能理解婆咸。

我這一段時間的編程秀里,可能很多人都發(fā)現(xiàn)芜辕,我經(jīng)常會在心里吐槽尚骄,我發(fā)現(xiàn)所有這些心里的吐槽,其實如果直面它侵续,都是解決方案本身乖仇。在ChatGPT時代,每當ChatGPT給你的東西讓你心里產(chǎn)生了什么不滿询兴,千萬不要輕易放過這個不滿乃沙,因為你的不滿可能就是改進的源泉。要直面這些不滿诗舰,用自然語言把這些不滿說清楚警儒,到底你不滿的是什么。在以前眶根,你想清楚這個蜀铲,你可能無力改變現(xiàn)實,徒增痛苦属百。但是在今天记劝,大多數(shù)情況下,一旦你想清楚了族扰,現(xiàn)實都會隨之改變厌丑,實在不行,你還可以跟ChatGPT商量怎么辦嘛渔呵,他可比一個真正的人好脾氣多了怒竿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扩氢,隨后出現(xiàn)的幾起案子耕驰,更是在濱河造成了極大的恐慌,老刑警劉巖录豺,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朦肘,死亡現(xiàn)場離奇詭異饭弓,居然都是意外死亡,警方通過查閱死者的電腦和手機媒抠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門弟断,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人领舰,你說我怎么就攤上這事夫嗓〕俾荩” “怎么了冲秽?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矩父。 經(jīng)常有香客問我锉桑,道長,這世上最難降的妖魔是什么窍株? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任民轴,我火速辦了婚禮,結(jié)果婚禮上球订,老公的妹妹穿的比我還像新娘后裸。我一直安慰自己,他們只是感情好冒滩,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布微驶。 她就那樣靜靜地躺著,像睡著了一般开睡。 火紅的嫁衣襯著肌膚如雪因苹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天篇恒,我揣著相機與錄音扶檐,去河邊找鬼。 笑死胁艰,一個胖子當著我的面吹牛款筑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腾么,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼醋虏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哮翘?” 一聲冷哼從身側(cè)響起颈嚼,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饭寺,沒想到半個月后阻课,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叫挟,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年限煞,在試婚紗的時候發(fā)現(xiàn)自己被綠了抹恳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡署驻,死狀恐怖奋献,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旺上,我是刑警寧澤瓶蚂,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站宣吱,受9級特大地震影響窃这,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜征候,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一杭攻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疤坝,春花似錦兆解、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畔裕,卻和暖如春衣撬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扮饶。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工具练, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甜无。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓扛点,卻偏偏與公主長得像,于是被迫代替她去往敵國和親岂丘。 傳聞我的和親對象是個殘疾皇子陵究,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容