当我刚开始成为一名初级软件工程师时(大约 14 年前),我记得自己做的一个前端项目需要用纯色部分填充一朵“云”的 SVG,做出一个漂亮的进度条。
作为一名刚入职的初级开发人员,彼时我急着证明自己的技能水平。我记得自己疯狂地在谷歌上搜索解决方案,但只找到了填充整个 SVG 对象的示例。在针对这个问题调整了一段时间后,我想出了一个巧妙的解决方案,关键是操纵一个渐变停止点。
这个技巧是使用有两个停止点的线性渐变,一个是透明色,另一个是纯色。通过操纵这些停止点的偏移量,渐变分界线会随着数据加载而不断移动,并逐渐用颜色填充那朵云。
由于当时网上没有这方面的资源,我记得自己觉得这是个非常巧妙的技巧,并想写一篇关于它的博客文章,结果我直到现在才开始做这件事情。
我的解决方案
这是我当时使用的技巧的现代版示例。
const CloudFillHuman: React.FC<CloudFillProps> = ({ percentage }) => {
/*
calculate the offset of the gradient stops based on the passed
percentage and render the cloud filled with the gradient
*/
const clampedPercentage = Math.max(0, Math.min(percentage, 100));
const offset = 100 - clampedPercentage;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="200"
height="200"
strokeWidth={0.5}
viewBox="0 0 24 24"
stroke="#fff"
>
/* Define the Gradient with two stops */
<defs>
<linearGradient id="cloud-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset={`${offset}%`} style={{stopColor: "#ffffff00", stopOpacity: 0}} />
<stop offset={`${offset}%`} style={{stopColor: "#5cc6fe", stopOpacity: 1}} />
</linearGradient>
</defs>
/* Define the Shape to be filled */
<path
fill="url(#cloud-gradient)"
strokeLinecap="round"
strokeLinejoin="round"
d="M 2.25 15a4.5 4.5 0 0 0 4.5 4.5
H 18a3.75 3.75 0 0 0 1.332-7.257
3 3 0 0 0-3.758-3.848 5.25 5.25
0 0 0-10.233 2.33 A 4.502 4.502
0 0 0 2.25 15Z"
/>
</svg>
)
};
复制代码
考虑到 LLM 模型已经训练过大量在线数据,加上我第一次解决这个问题后已经过去了这么久的时间,我很好奇 ChatGPT-o1 今天会如何解决这个问题。所以我决定测试一下。
提示
这是我用来测试 ChatGPT-o1 的提示。公平地说,我给了它非常明确的指示,我希望我当时的老板也能这样做就好了。
我有一个云形状的 SVG,我希望你编写一个 typescript 函数,以 0 到 100 之间的整数作为输入,并用纯色部分填充云。例如,如果输入值为 50,我希望一半的云填充蓝色,另一半是透明的。
SVG 形状如下……
I have an SVG in the shape of a cloud, I want you to write a typescript function that takes an integer number between 0 and 100 as input and partially fill the cloud with a solid color. For example, if the input value is 50, I expect half the cloud to be filled with the color blue and the other half to be transparent.
here is the SVG shape ...
O1 思考了 30 秒,然后提供了以下解决方案
const CloudFill: React.FC<CloudWithFillProps> = ({ percentage }) => {
// Ensure percentage is within 0 to 100
const clampedPercentage = Math.max(0, Math.min(percentage, 100));
const yPosition = (24 * (100 - clampedPercentage)) / 100; // Calculate Y position based on percentage
// Generate a unique ID for the clip path to avoid ID conflicts if multiple clouds are rendered
const clipPathId = React.useMemo(() => `clip-${Math.random().toString(36).substr(2, 9)}`, []);
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
strokeWidth={0.5}
stroke="currentColor"
width={200}
height={200}
>
<defs>
<clipPath id={clipPathId}>
{/* Rectangle that determines the filled area based on the percentage */}
<rect x="0" ={yPosition} width="24" height={24 - yPosition} />
</clipPath>
</defs>
{/* Filled cloud shape clipped to the percentage */}
<path
fill="#5cc6fe"
d="M2.25 15a4.5 4.5 0 0 0 4.5 4.5H18a3.75
3.75 0 0 0 1.332-7.257 3 3 0 0 0-3.758-3.848
5.25 5.25 0 0 0-10.233
2.33A4.502 4.502 0 0 0 2.25 15Z"
clipPath={`url(#${clipPathId})`}
/>
{/* Cloud outline */}
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M2.25 15a4.5 4.5 0 0 0 4.5 4.5H18a3.75
3.75 0 0 0 1.332-7.257 3 3 0 0 0-3.758-3.848
5.25 5.25 0 0 0-10.233
2.33A4.502 4.502 0 0 0 2.25 15Z"
/>
</svg>
);
};
复制代码
GPT o1 使用了一个 ClipPath(https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath),在云的轮廓后面渲染了一朵填充颜色云的一部分。
老实说,这个解决方案非常好,它对提示的理解程度令我印象深刻。
现在我们来对这两个解决方案做做对比测试。
对比解决方案
乍一看,这两个解决方案看起来非常像。LLM 给出的解决方案似乎符合预期。但我们来看看当我们操纵百分比的值时它们的表现如何。
可以看到,LLM 解决方案直到滑块超过 20% 才开始填充形状,并且当百分比为 80% 或以上时,它就已经填充了整个形状。
结论
那么这给我们留下了什么结论?LLM 是否准备好了代替人类完成中等复杂度的前端任务?
虽然这项技术无疑是很有用的,但 LLM 是否准备好了在没有任何人工监督的情况下接管工程任务呢?答案仍然是斩钉截铁的“否”,尽管这并不意味着一些公司不会尝试走这条路。
很难从单个例子中推断出太多信息,但有一点是肯定的,软件工程一直看重准确度和精确性,就像它看重创造力和创新一样。
虽然 LLM 擅长生成内容、回答问题和辅助开发人员,但要让它们自己编写出一致、无错误的代码还需要该领域取得重大突破。
也许让多个代理对同一代码进行迭代可能是朝着正确方向迈出的一步? 然而,我相信在可预见的未来这依旧会是一个挑战,毕竟,LLM 是在数十亿行由人类编写的“不完美”代码上进行训练的,而我们自己依旧没有解决这个问题。
原文链接:https://www.charbzg.com/blog/gpt-frontend-task
评论