1、打造LLM高質量代碼生成的神兵利器陳雅菲 中興通訊演講嘉賓陳雅菲中興通訊 公司資深軟件架構師 資深敏捷教練深耕軟件領域20余年,擁有豐富的大型軟件項目架構、設計與開發經驗,在軟件設計開發理論與實踐上均有獨到見解。長期致力于敏捷技術實踐指導與推廣,多次獲得公司十佳敏捷教練稱號。目前研究方向是LLM輔助設計編碼。目 錄CONTENTS1.LLM代碼生成面臨的問題2.問題的解決思路與方案3.實踐情況與效果評估4.總結&展望LLM代碼生成面臨的問題PART 01LLM代碼生成面臨的問題軟件開發目標之一高效輸出高質量代碼編碼人需要充分理解設計才能編寫出高質量的代碼好的設計設計如何讓LLM充分理解設計問題
2、的解決思路與方案PART 02解決思路語義模型驅動設計(Semantic Model Driven Design)一種應對高軟件復雜度的設計方法抽象出針對特定問題領域的語義模型采用結構化表達描述語義模型不同LLM有不同使用約束根據不同使用約束提煉提示模式需求測試(UT)設計編碼SMDD解決方案:SMDD需求測試(UT)設計SMDD編碼語義模型驅動設計(SMDD)總覽匹配的人員能力思想通過構建語義模型驅動出好的設計語義模型構建三步法DSL語義模型的語義與問題領域的核心需求相匹配語義模型提供的框架具備可組合性原則語義模型驅動設計(SMDD)框架深入分析特定問題領域、挖掘問題領域核心需求核心需求使用
3、語義模型構建語義模型構建三步法三步法,從核心需求抽象出語義模型語義模型,其語義要與特定問題領域的核心需求相匹配基于語義模型提供一套DSLDSL(Domain-Specific Language,領域特定語言)設計核心需求特定問題領域分析語義模型構建三步法抽象匹配語義模型語義模型是提供了與問題領域核心需求相匹配的語義、框架具備可組合性的計算模型原子原子最簡單、最基本的實體組合方法組合方法把原子組合起來構成更復雜實體的方法命名復雜實體的手段,命名后的復雜實體可以像原子一樣通過組合方法組合成更為復雜的實體抽象手段抽象手段解決方案:提示模式需求測試(UT)設計SMDD編碼提示模式:不同使用約束、不同提
4、示模式交互方式:單輪對話+有代碼上傳提示模板:每個場景對應一個提示模板提示模式二交互方式:多輪對話+無代碼上傳提示模板:每輪對話對應一個提示模板提示模式一。是否支持多輪對話信息安全、合規要求LLM的使用約束提示模式一:多輪對話+無代碼上傳請按如下建議修改代碼:1.aaa2.bbb.請按如下建議補充代碼:1.xxx2.yyy.請你自己檢查一下代碼是否完整、正確地實現了這套DSL描述。先不要改代碼,先告訴我檢查結果。請給出目前所有代碼。請你采用等價類與邊界值的測試設計方法,使用JUNIT4生成所有類的單元測試代碼,注意每個類對應一個測試類、每個測試用例一個測試方法。請按如下建議修改代碼:1.aaa
5、2.bbb.請按如下建議補充代碼:1.xxx2.yyy.請你自己檢查一下單元測試代碼是否完善。先不要改代碼,先告訴我檢查結果。請給出目前所有單元測試代碼。你是一名.資深程序員,請編寫程序實現一個系統:1.系統的輸入是.,系統的輸出是.。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|.|.|.|.|.|.|.|.|.|請先不要給出代碼。如果你對于這一套DSL描述有疑問,特別是Markdown表格概念語義列中的內容,請向我提問,我來回答你。請先不要給出代碼。你確定沒有疑問了嗎?請生成代碼。使用初始Prompt確認L
6、LM正確理解了Prompt內容使用LLM生成代碼審查LLM生成的代碼執行必要的修改或補充使用LLM生成單元測試代碼審查LLM生成的單元測試代碼執行必要的修改或補充提示模式二:場景代碼生成代碼缺陷修復全量代碼生成增量代碼生成單元測試代碼生成無依賴代碼的單元測試代碼生成有依賴代碼的單元測試代碼生成交互方式:單輪對話+有代碼上傳提示模板:每個場景對應一個提示模板提示模式二提示模式二:代碼生成說明:1.使用Markdown語法、按總分總結構書寫提示。2.在任務重申部分強調一下需要LLM做的事情和注意事項。#任務概述你是一名.資深程序員,請編寫程序實現一個系統:1.系統的輸入是.,系統的輸出是.。2.實
7、現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|.|.|.|.|.|.|.|.|.|#任務重申1.請編寫程序實現上述系統。.全量代碼生成初始全量代碼生成#任務概述你是一名.資深程序員,請編寫程序實現一個系統:1.系統的輸入是.,系統的輸出是.。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|.|.|.|.|.|.|.|.|.|3.已實現的條件或規則未列入表格。相關的實現代碼在已有代碼中。4.請在/TODO處新增代碼。#已有代碼java.#
8、待實現的代碼java./TODO:.#任務重申1.請在/TODO處按要求新增代碼。.增量代碼生成基于已有代碼,增量生成新的代碼#任務概述你是一名.資深程序員,請編寫程序實現一個系統:1.系統的輸入是.,系統的輸出是.。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|.|.|.|.|.|.|.|.|.|3.已實現的條件或規則未列入表格。相關的實現代碼在已有代碼中。4.請在/FIXME處修復代碼缺陷。#已有代碼java.#待修復的代碼java./FIXME:.#任務重申1.請在/FIXME處按要求修復代碼缺陷。.代碼
9、缺陷修復基于已有代碼,修復已有代碼缺陷提示模式二:單元測試代碼生成#任務概述你是一名Java資深程序員。請你采用等價類與邊界值的測試設計方法,使用JUNIT4生成所有被測代碼的單元測試代碼,注意每個類對應一個測試類、每個測試用例一個測試方法。#被測代碼java.#任務重申1.請使用JUNIT4生成所有被測代碼的單元測試代碼。*注意采用等價類與邊界值的測試設計方法。*每個類對應一個測試類、每個測試用例一個測試方法。.無依賴代碼的單元測試代碼生成1.初始全量單元測試代碼生成2.針對對其他代碼無依賴的被測代碼生成單元測試代碼#任務概述你是一名Java資深程序員。請你采用等價類與邊界值的測試設計方法,
10、基于已有代碼使用JUNIT4生成被測代碼的單元測試代碼,注意每個類對應一個測試類、每個測試用例一個測試方法。#已有代碼java.#被測代碼java.#任務重申1.請基于已有代碼使用JUNIT4生成所有被測代碼的單元測試代碼。*注意采用等價類與邊界值的測試設計方法。*每個類對應一個測試類、每個測試用例一個測試方法。.有依賴代碼的單元測試代碼生成針對對其他代碼有依賴的被測代碼生成單元測試代碼LLM高質量代碼生成的神兵利器LLM高質量代碼生成的神兵利器SMDD(語義模型驅動設計)做出好的設計,輸出結構化表達的語義模型,使得LLM能夠充分理解設計提示模式交互方式+提示模板,使得LLM基于語義模型高效生
11、成高質量代碼實踐情況與效果評估PART 03實踐案例:字符串轉換重構相同邏輯的不同實現重復字符串轉換重構:語義模型驅動設計示例核心概念概念語義原子/組合形式化表達規則規則的輸入是源字符串,輸出是Optional,其中String是轉換后的字符串/rule:srcStr-Optional一一映射規則該規則由映射列表構造而成,映射列表的每個元素由一對mappingFrom和mappingTo構成。該規則接受的源字符串即mappingFrom,找到對應的mappingTo并輸出原子規則oneToOne(mappingFrom,mappingTo)保留指定位數小數規則該規則由保留小數位數構造而成。該規
12、則對接受的源字符串進行保留指定位數小數處理后并輸出原子規則decimalDigits(digitNum)條件應用分支規則該規則由條件、then規則、else規則構造而成。當條件滿足時應用then規則,否則應用else規則組合規則whenThenElse(condition,thenRule,elseRule)順序應用規則該規則由規則列表構造而成。按照給定的順序依次應用多條規則。當某條規則應用成功,則返回該條規則的應用結果;如果該條規則應用失敗,則繼續應用下一條規則組合規則seq(rule)條件條件的輸入是源字符串、輸出boolean,條件滿足時輸出true、條件不滿足時輸出false/cond
13、ition:srcStr-true|false null條件該條件無構造參數。當該條件接受的源字符串為null時為true,否則為false原子條件nullString()空白字符串條件該條件無構造參數。當該條件接受的源字符串僅含空白字符或為空時為true,否則為false原子條件blankString()或條件布爾代數的或組合條件or(condition1,condition2)與條件布爾代數的與組合條件and(condition1,condition2).字符串轉換重構:提示模式一交互方式:單輪對話+有代碼上傳提示模板:每個場景對應一個提示模板提示模式二交互方式:多輪對話+無代碼上傳提示模
14、板:每輪對話對應一個提示模板提示模式一字符串轉換重構:代碼生成A:好的,我理解了你對這一套DSL的描述。如果你對其中的任何部分有疑問,我會盡力回答。請告訴我如果你需要任何進一步的解釋或有其他問題。Q:你是一名Java資深程序員,請編寫程序實現一個系統:1.系統的輸入是源字符串。系統的輸出是Optional,其中String是轉換后的字符串,如果轉換成功,輸出非empty的Optional,如果轉換失敗,輸出Optional.empty。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|規則|規則的輸入是源字符串,輸
15、出是Optional,其中String是轉換后的字符串|/|rule:srcStr-Optional|一一映射規則|該規則由映射列表構造而成,映射列表的每個元素由一對mappingFrom和mappingTo構成。該規則接受的源字符串即mappingFrom,找到對應的mappingTo并輸出|原子規則|oneToOne(mappingFrom,mappingTo)|.|條件|條件的輸入是源字符串、輸出boolean,條件滿足時輸出true、條件不滿足時輸出false|組合條件|condition:srcStr-true|false|null條件|該條件無構造參數。當該條件接受的源字符串為nu
16、ll時為true,否則為false|原子條件|nullString()|.請先不要給出代碼。如果你對于這一套DSL描述有疑問,特別是Markdown表格概念語義列中的內容,請向我提問,我來回答你。A:我已經仔細閱讀了您提供的DSL描述,并沒有特別的疑問。我明白這是一個規則轉換系統,其中包含了原子規則和組合規則,以及一些條件用于判斷是否應用規則。您可以繼續說明您的需求,我將等待您的指示。如果您需要對DSL的某些方面進行澄清或有其他問題,請隨時告訴我,我會盡力回答。Q:請先不要給出代碼。你確定沒有疑問了嗎?A:好的,下面是用Java實現這套DSL的代碼:Q:請生成代碼。字符串轉換重構:單元測試代碼
17、生成A:好的,我會使用等價類與邊界值的測試設計方法,并使用JUnit 4生成單元測試代碼。請注意,由于描述的規則和條件比較復雜,測試覆蓋所有情況可能會比較繁瑣。因此,我將選擇一些典型的等價類和邊界值來生成測試用例,以便展示測試的基本思路。你可以在此基礎上進一步擴展測試用例,以確保代碼的正確性。首先,我們將每個規則和條件對應的測試代碼放在獨立的測試類中,并使用JUnit 4進行測試。以下是測試類和測試方法的示例代碼:.上述代碼中,每個規則和條件對應一個測試類,測試類中包含了若干測試方法,每個方法對應一個測試用例。我選擇了一些簡單的測試用例來演示測試方法的設計,你可以根據實際需求添加更多測試用例。
18、在實際測試中,需要覆蓋各種等價類和邊界值來確保代碼的正確性。請注意,上述測試代碼僅用于演示目的,實際測試中應該盡可能全面地覆蓋各種情況,以保證系統的穩健性和正確性。Q:請你采用等價類與邊界值的測試設計方法,使用JUNIT4生成單元測試代碼,注意每個類對應一個測試類、每個測試用例一個測試方法。字符串轉換重構:提示模式二交互方式:單輪對話+有代碼上傳提示模板:每個場景對應一個提示模板提示模式二交互方式:多輪對話+無代碼上傳提示模板:每輪對話對應一個提示模板提示模式一字符串轉換重構:全量代碼生成#任務概述你是一名Java資深程序員,請編寫程序實現一個系統:1.系統的輸入是源字符串。系統的輸出是Opt
19、ional,其中String是轉換后的字符串,如果轉換成功,輸出非empty的Optional,如果轉換失敗,輸出Optional.empty。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|規則|規則的輸入是源字符串,輸出是Optional,其中String是轉換后的字符串|/|rule:srcStr-Optional|一一映射規則|該規則由映射列表構造而成,映射列表的每個元素由一對mappingFrom和mappingTo構成。該規則接受的源字符串即mappingFrom,找到對應的mappingTo并輸出|
20、原子規則|oneToOne(mappingFrom,mappingTo)|.|條件|條件的輸入是源字符串、輸出boolean,條件滿足時輸出true、條件不滿足時輸出false|組合條件|condition:srcStr-true|false|null條件|該條件無構造參數。當該條件接受的源字符串為null時為true,否則為false|原子條件|nullString()|.#任務重申1.請編寫程序實現上述系統。字符串轉換重構:增量代碼生成#任務概述你是一名Java資深程序員,請編寫程序實現一個系統:1.系統的輸入是源字符串。系統的輸出是Optional,其中String是轉換后的字符串,如果
21、轉換成功,輸出非empty的Optional,如果轉換失敗,輸出Optional.empty。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性。|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|null或空白字符串條件|該條件應基于或條件生成,null條件與空白字符串條件相或。|組合條件|or(nullString(),blankString()|3.已實現的條件或規則未列入表格。相關的實現代碼在已有代碼中。4.請在/TODO處新增代碼。#已有代碼java/規則FunctionalInterfacepublic interface Rule Optional ap
22、ply(String srcStr);#待實現的代碼java/日期時間規則。static Rule dateTime(String format)return srcStr-/TODO:請完成日期時間規則的實現。該規則對接受的源字符串按照日期時間格式字符串進行日期時間格式處理后并輸出。return Optional.of(srcStr);#任務重申1.請在/TODO處按要求新增代碼。字符串轉換重構:代碼缺陷修復#任務概述你是一名Java資深程序員,請編寫程序實現一個系統。請使用OpenJDK 8實現。請使用函數式編程,不要使用面向對象編程。1.系統的輸入是源字符串。系統的輸出是Optional
23、,其中String是轉換后的字符串,如果轉換成功,輸出非empty的Optional,如果轉換失敗,輸出Optional.empty。2.實現如下面的Markdown表格描述的一套DSL,注意可組合性:|核心概念|概念語義|原子/組合|形式化表達|-|-|-|-|順序應用規則|該規則由規則列表構造而成。按照給定的順序依次應用多條規則。當某條規則應用成功,則返回該條規則的應用結果;如果該條規則應用失敗,則繼續應用下一條規則|組合規則|seq(rule)|3.已實現的條件或規則未列入表格。相關的實現代碼在已有代碼中。4.請在/FIXME處修復代碼缺陷。#已有代碼java/規則FunctionalI
24、nterfacepublic interface Rule Optional apply(String srcStr);#待修復的代碼javapublic static Rule seq(List rules)/FIXME:按照給定的順序依次應用多條規則。當某條規則應用成功,則返回該條規則的應用結果;如果該條規則應用失敗,則繼續應用下一條規則#任務重申1.請在/FIXME處按要求修復代碼缺陷。字符串轉換重構:無依賴代碼的單元測試代碼生成#任務概述你是一名Java資深程序員。請你采用等價類與邊界值的測試設計方法,使用JUNIT4生成所有被測代碼的單元測試代碼,注意每個類對應一個測試類、每個測試用
25、例一個測試方法。#被測代碼java/規則FunctionalInterfacepublic interface Rule Optional apply(String srcStr);class Rules ./條件FunctionalInterfacepublic interface Condition boolean apply(String srcStr);class Conditions .#任務重申1.請使用JUNIT4生成所有被測代碼的單元測試代碼。*注意采用等價類與邊界值的測試設計方法。*每個類對應一個測試類、每個測試用例一個測試方法。字符串轉換重構:有依賴代碼的單元測試代碼生成#
26、任務概述你是一名Java資深程序員。請你采用等價類與邊界值的測試設計方法,基于已有代碼使用JUNIT4生成被測代碼的單元測試代碼,注意每個類對應一個測試類、每個測試用例一個測試方法。#已有代碼java/條件FunctionalInterfacepublic interface Condition boolean apply(String srcStr);#被測代碼javaclass Conditions /或條件 public static Condition or(Condition condition1,Condition condition2)return srcStr-conditio
27、n1.apply(srcStr)|condition2.apply(srcStr);#任務重申1.請基于已有代碼使用JUNIT4生成被測代碼的單元測試代碼。*注意采用等價類與邊界值的測試設計方法。*每個類對應一個測試類、每個測試用例一個測試方法。神兵利器效果評估LLM高質量代碼生成的神兵利器SMDD(語義模型驅動設計)做出好的設計,輸出結構化表達的語義模型,使得LLM能夠充分理解設計提示模式交互方式+提示模板,使得LLM基于語義模型高效生成高質量代碼 消除了原有代碼中的“重復”與“相同邏輯不同實現”等問題,使得可維護性大幅度提升可維護性可維護性可理解性可理解性 LLM生成的代碼容易理解,一方面
28、是因為SMDD做出了好的設計,另一方面是LLM充分理解了該設計一致性一致性 LLM生成的代碼與設計的核心概念實現了一一對應 LLM生成的代碼與人編寫的代碼是相似的,甚至更好總結&展望PART 04總結LLM高質量代碼生成的神兵利器SMDD(語義模型驅動設計)做出好的設計,輸出結構化表達的語義模型,使得LLM能夠充分理解設計提示模式交互方式+提示模板,使得LLM基于語義模型高效生成高質量代碼適用場景適用場景 適用于軟件復雜度高的場景亮點亮點 提示模式簡單易學 多人多輪多案例驗證,結果穩定、有效展望LLMs如何應對LLM的差異性如何寫出好的Prompt代碼生成的工程化人的能力要求 根據不同的LLM采用相應的提示模式 Prompt中關于SMDD的核心內容是不變的、適用于多種大模型 Prompt中的其他內容以及與LLM的交互方式需要調整,以適應不同的LLM 充分應用提示工程的基本原則 像跟人溝通一樣跟LLM溝通 對軟件架構提出了更高的要求 人員能力要求不降反升,既要具備軟件設計、編碼技能,又要掌握提示工程技能 提煉可落地、可推廣的提示模式,盡量讓LLM能夠穩定生成代碼,穩定不是100%準確 不建議過度追求100%的代碼可用率 需要人來兜底THANKS