面向对象第八次实验指导书
实验仓库
公共信息发布: exp_8。
个人仓库:
oo_homework_2025/homework_2025_你的学号_exp_8。请同学们作答完成后,将 md 文件与 json 文件提交到个人仓库,并将需要提交的md文件内容填入内容提交区,再在本页面下方选择对应的
commit,最后点击最下方的按钮进行提交。详细的提交过程请参见_实验结果提交_章节。
实验说明
本实验需要大量使用大语言模型,你可以自由选择任意大语言模型完成你的实验。
实验各个阶段的输入设计请参考“LLM提示方法指导”一节以及oolens推送,助教会检查输入设计的合理性。不要完全照抄示例的Prompt。
实验目标
体会大语言模型(LLM)在长文本情景下正向建模的能力。
通过分阶段生成类与关系,理解LLM建模中问题分解(Question Decomposition)的重要性。
理解并掌握设计高效Prompt与Chain-of-Thought(COT)的关键技巧。
实验情景
题目情景
1 | 一个城市正在使用公交运输管理系统(BTMS)来简化与城市相关的日常活动,以下是BTMS有关的功能介绍 |
任务要求
按照题目情景描述的需求,设计出符合情景的类图,只需要包括类、成员属性、关系(关联、实现、泛化),可以使用大语言模型帮助生成。
格式要求:
为方便评测,需要将回答统一成以下格式:
(1) 对于每个类和属性,请固定使用对应格式:
枚举类:
枚举类名(枚举项1名称, 枚举项2名称,......)接口:
interface 接口名()一般类和成员属性:
类名(属性1类型: 属性1名称, 属性2类型: 属性2名称, ......)抽象类:
abstract 类名(属性1类型: 属性1名称, 属性2类型: 属性2名称, ......)
(2) 对于每个关系,请固定使用对应格式,其中()内表示可选项,*用于表示1对多关系:
- 关联:
类A名 associates (*)类B名,表示类A关联了类B(A的一个成员类型是B) - 实现:
类A名 implements 接口B名,表示类A实现了接口B - 泛化:
类A名 extends 类B名,表示子类A继承了父类B
(3) 提交最终答案的输出格式以json格式给出,参考如下:
1 | { "Enumeration": [ "Enum1(ONE, TWO, THREE)" ], "Class": [ "Class1(int: attribute1, Class2: attribute2)", "Class2(Enum1: attribute3, List<Class3>: attribute4)", "Class3(int: attribute5)" ], "Relationship": [ "Class1 associates *Class2", "Class2 associates Enum1", "Class2 extends Class3" ] } |
为了方便建模,以下属性类型不需要额外定义类:
- 基本数据类型(int, char, boolean, double等)
- 引用数据类型(String, List<>, Map<>等)
- 表示时间的数据类型(日期:LocalDate,时间:LocalTime)
实验步骤
实验1:直接建模
请尝试直接将完整的题目情景、任务要求、格式要求复制粘贴给大模型输入,不添加任何额外的提示词:
1 | [题目情景] 一个城市正在使用公交运输管理系统(BTMS)…… |
观察模型输出结果并思考:
类的命名是否清晰?成员属性的类型是否合理?
LLM是否遗漏关键类或属性?(有没有主类?)
LLM是否构建了冗余的类或属性?
定义的枚举类、抽象类、接口类是否有合理性?
类之间的关系是否合理?是否有遗漏的关系?
请将LLM的输入输出保存至template.md的相应位置。
实验2:分阶段建模
首先让我们回顾一下我们人类在正向建模中的思考过程是什么样的呢?一般来说,我们会先从需求中抽象提取出对象,确定这些对象包含的属性和方法,再把这些对象包装成类,然后分析并建立类之间的关系。因此我们很自然的想到,如果想要提升大语言模型的建模能力,可以让模型按照人类的思考方式来执行。本实验也需要你分三阶段利用LLM完成类图的设计:
阶段1:初步分析需求
让LLM从情景中理解需求,识别出关键对象,并抽象成类。
首先我们希望LLM利用其强大的上下文信息捕捉能力,抽象出关键的对象,并提炼相关的属性,包装成类。
我们需要告诉LLM:
- 你的任务是什么:从情景中完成需求分析并抽象出类
- 任务提示:任务的关键要求有哪些?需要抽象出哪些层次行为?类的成员属性可能有哪些?
- 情景描述
注意,这一阶段我们不着急让模型按照规定格式直接输出类图,因为在面向对象的建模中,从需求中识别类是一项至关重要的任务,对后续步骤有深远的影响,而提前固定输出形式可能会限制模型的思考。
请参考“LLM提示方法指导”中的“ROSES设计”完成这一阶段的模型输入设计,将阶段1 LLM的输入输出保存至template.md的相应位置。
阶段2:提炼类
让LLM回顾阶段1的总结,重新审核并按输出格式提炼类。
如何让AI在生成结果后,能够像人类一样进行自我审视和改进,从而提升输出质量,成为了AI研究者们关注的焦点。而反思模式,正是为了解决这一问题而应运而生。我们希望模型通过反思机制自我识别问题,并给出修改和优化。
我们需要告诉LLM:
- 你的任务是什么:反思并按格式输出类及属性
- (可选项)明确指出回答中出现的问题
- 任务提示:从哪些角度进行反思?核心判断标准是什么?(准确性/完整性/必要性)
- 格式要求
在这一阶段我们需要LLM反思自己的答案,并且按照我们要求的格式给出回答。
请参考“LLM提示方法指导”中的“ROSES设计”完成这一阶段的模型输入设计,并对比实验1的类图结果,分析分阶段提问效果是否更好?将阶段2 LLM的输入输出保存至template.md的相应位置。
阶段3:提取关系
完成了类的提取之后,接下来我们要完成类之间关系的提取。我们推荐将“提取关系”这一大任务拆分成“提取xx关系”等几个子任务,针对不同关系设计不同的输入。
在生成类的时候,你可能已经体会到了模型反思的重要性,同样我们希望模型在提取关系时也能自我反思。这次我们采取设计思维链(Chain of Thought,COT)的方法完成模型自反思。
抽象的讲,我们可以这样提问LLM:
- 明确任务要求:要求模型寻找xx关系
- (可选项)提示模型什么是xx关系
- 思维链提示:(示例)
- step 1: 初步寻找xx关系
- step 2: 检查找到的关系是否存在问题
- step3: 修改并完善结果
- step4: 按格式要求输出结果
- 格式要求
- (可选项)完整的情景描述和阶段1得到的类图结果
请参考“LLM提示方法指导”中的“COT设计”完成关联关系提炼的模型输入设计,并对比实验1的关系结果,分析利用COT提取关联关系的效果是否更好?请将阶段3 LLM的输入输出保存至template.md的相应位置。
注意,阶段2需要提交的结果只有关联关系的提炼过程,但你应当完成提炼其他关系的对话,以完成最终结果的提交。
实验结果提交
请将阶段1、2和3得到的类图结果汇总,按照原问题的输出格式提交answer.json文件。
1 | { "Enumeration": [ "枚举类1(枚举项1, 枚举项2, 枚举项3)" ], "Class": [ "类1(类型1: 属性1, 类型2: 属性2)" ], "Relationship": [ "类1 关系名 类2", "类1 关系名 *类2" ] } |
同时,按照仓库中template.md的格式,将template.md中的部分内容替换成与大模型对话的结果,并在开头填写上使用的大模型名称:
1 | > 使用的大模型是:*填写使用的大模型名称,如 deepseek-r1, GPT-4o等* # 实验1输入 (此处粘贴与大模型对话的原输入) # 实验1输出 (此处粘贴与大模型对话的原输出) # 实验2阶段1输入 (此处粘贴与大模型对话的原输入) # 实验2阶段1输出 (此处粘贴与大模型对话的原输出) # 实验2阶段2输入 (此处粘贴与大模型对话的原输入) # 实验2阶段2输出 (此处粘贴与大模型对话的原输出) # 实验2阶段3输入 (此处粘贴与大模型对话的原输入) # 实验2阶段3输出 (此处粘贴与大模型对话的原输出) |
请将实验1和实验2的相关结果template.md和answer.json一起提交到个人仓库下,并将template.md中的内容填入内容提交区。
LLM提示方法指导
什么是Prompt
Prompt是指在大语言模型应用中,用简单的“提示词”来唤醒模型以解决特定任务的提问方式。简单来说,prompt就是一把钥匙,可以引导模型从预训练的海量信息中捕捉到能满足用户需求的信息,可以显著提升模型理解复杂文本、提取信息、逻辑推理、总结结论等能力。设计优质的prompt对利用好大语言模型意义重大。
prompt的基本要素包括:
- 指令:指定模型需要完成的任务
- 上下文:额外信息,引导LLM更好响应任务
- 输入数据:用户的问题或内容
- 输出指示:输出格式或规范
为什么需要Prompt
用户需求的多样性推动了prompt的广泛应用,涉及信息获取、内容创作和问题解答等多个方面。通过设计有效的prompt,用户能够快速获取所需信息,提升工作效率,减少反复试错的过程。
针对具体的情景我们需要设计不同的prompt,以下推荐一些简单好用的prompt设计框架:
RTF框架
RTF(Role-Task-Format)框架是一个非常简单通用的提示框架,其基本思想是让LLM担当某一角色(程序员、研究员、算法工程师等等),让模型能够快速响应相关领域的问答。适用于明确角色、任务、格式的简单任务。
- Role:指定大模型担当的角色
- Task:告诉大模型任务定义和要求
- Format:定义大模型返回回答的格式
例如:
1 | [Role] 你是一位资深市场分析师。 |
ROSES框架
ROSES框架在RTF框架的基础上将输入细分为5个核心部分,以确保清晰、有目的的交互。ROSES在明确角色和目标的基础上,更强调场景和解决方案。
- Role:指定大模型担当的角色
- Objective:描述想要实现的目标或想要完成的任务
- Scenario:提供与请求相关的背景信息或上下文
- Expected Solution:描述期望解决方案或结果
- Steps:询问实现问题的具体方法或步骤
例如:
1 | [Role] 你是某科技公司的公关经理。 |
COT模式
COT(Chain of Thought)模式适合分析型逻辑推理型或分析型任务,可以很好的改善大模型的推理能力,在一些决策步骤中能发挥高效作用。我们需要提供情景下模型思考问题或解决问题的步骤样例,引导模型形成一个完整的推理逻辑链,并在输入的最后加上“让我们逐步思考”,这样完成了COT的设计。
例如如下问题场景:
1 | 问题:甲从A地以5km/h速度出发,乙1小时后从B地以7km/h速度出发,AB两地相距20km。问:乙需要多久追上甲? |
可以给模型如下示例:
1 | 步骤1:设乙出发后经过t小时追上甲,则甲的行驶时间为(t+1)小时。 |
这样就能引导模型按照示例提供的逻辑链进行思考,给出完整的推理过程。
其他框架
其他常用的prompt框架还有诸如SAGE,SCOPE,RISEN等,同时prompt还有一些关键方法,例如零样本提示(Zero-shot)或少样本提示(Few-shot),同学们可以自行学习并在日常与大模型的交流对话中使用。
使用示例
理论学习之后少不了实战,下面举一个来自课堂的例子:
1 | 设出租车的状态有四种:服务状态(把乘客送往目的地过程中所处的状态),接单状态(被派遣了乘客请求后,去接乘客过程中所处的状态),等待服务状态(无服务可接单的空车运行状态)和停止服务状态(无服务、不接单)。出租车在等待服务状态时可以获得派单,从而变成接单状态,一旦接到乘客,即变为服务状态。出租车只能从等待服务状态变为停止服务状态。 |
首先为了提取类,我们采用ROSES模版向大模型提问:
1 | [Role]你是一个面向对象设计专家,擅长从业务场景中识别核心实体并构建对象模型。 |
接着为了总结类之间的关系,我们采用COT模版向大模型提问(关联关系和聚合关系):
1 | 你是一名资深面向对象设计专家,擅长分析类之间的关系。你需要结合之前的出租车派单系统需求说明和你提炼出的类,分析类之间的UML类图关系。你只需要考虑关联关系和聚合关系。你可以参考以下步骤完成: |
写到最后
本次实验目的并不是希望教大家怎么用大模型,而是希望引导大家更高效、更智慧的运用大模型。在这个过程中,我们不是简单地把任务要求抛给大模型,而是希望通过一些设计,引导大模型获得更好的结果,这就需要同学本身对正向建模设计有一定的理解,不然只会适得其反。
目前也有研究表明似乎LLM建模的思路与人类思路是不完全一样的,或许本次实验中使用Prompt的效果还不如直接生成,但设计Prompt引导大模型完成任务的方法已经在很多领域得到了验证。即使抛开UML建模的设计,我们也可以在其他场景中尝试设计更好的提示来提升提问效果。
本学期OO最后一次实验也落下帷幕,回归了面向对象的设计,也拥抱了大模型,希望能对同学们有所帮助!