我是如何使用ChatGPT和CoPilot作为编码助手的

2023-07-31 10:55:29 浏览数 (1)

原文链接:https://notes.drdroid.io/how-i-use-ai-for-code-assistance

我已经探索过一些在编写高质量、功能性代码方面的 AI 实践应用,它们能在你编程时提供诸多便利。我一直在工作中使用 ChatGPT 网页工具和 Copilot(我们可以将 Copilot 视为 GPT 的一个变体,因为它们都基于同一核心技术构建)。

核心概括

  • Github Copilot: 用于提升代码自动完成的速度,可以将其视作一个为初级软件工程师的职位面试做了充分准备的应聘者,你可以把需要编写的代码任务交给它处理。
    • 我欣赏的特性:
      • 它提供了 VSCode、IntelliJ、Sublime 插件
      • 它能够很好地预测我想编写什么,尽管并非完美无瑕,但已经可以帮助我快速编写了一些常见的代码片段
  • ChatGPT:获取解决问题的端对端指令集,或者编写覆盖多个类和函数的完整用例的代码。此外,它还会解释它生成的代码,这是 Copilot 在自动完成时所无法提供的。

接下来,我将介绍我在编程时运用 AI 的六种方法:

1. CSS 生成 (Github Copilot)

在构建 Dr Droid 的过程中,我设定了一个自行编写 reactjs 应用并创建新的组件的目标。尽管我们使用 Figma 制作了原型,但是要将其嵌入到你的页面设计中,依然需要一些技巧。我主要从事后端开发,因此编写 CSS 来处理网格、移动适配性和间距对我来说有些困难。我创建了一个包含 HTML 元素的类,并在提示中描述了我们 Figma 原型中的元素。Copilot 为这个类添加了 CSS,它基于一些实际测量做出了预测,我稍后可以对其进行调整,但它已经解决了我在选择使用哪些 CSS 样式上的疑惑。

输入:

“”“给 3 个类别定义 CSS,一个是父 div,两个是子 div,子 div 应该水平对齐,它们的内部文字分别对齐到左和右”“”

输出:

代码语言:javascript复制
.parentDiv {
  flex-direction: 'inherit';
  display: 'flow-root';
  padding: '2px';
}

.leftDiv {
  width: '30%';
  height: '100%';
  background: 'white';
  float: 'left';
  border: '1px solid black';
    text-align: 'left';
}

.rightDiv {
  width: '70%';
  height: '100%';
  background: 'white';
  float: 'right';
  border: '1px solid black';
    text-align: 'right';
}

2. 利用 Copilot 编写函数:专注于排序和数据操作

在 Dr Droid 平台上,我们需要进行大量的数据转换来实现各种功能。根据我的测试,Copilot 在基于提示编写这些转换函数时表现出很强的实力。它也很擅长参考老字段描述新字段,编写将两个数据对象合并为一个具有不同模式的单一对象的函数。

比如,我需要一个函数来在数组中合并 JSON 对象,基于它们的两个字符串键,给出第三个数字键的不同统计。Copilot 能在你的代码环境中进行编写,无需重命名变量,而且你可以告诉它用哪个库来执行。

输入:

“”“编写一个函数,该函数在数组中合并 JSON 对象,并在它们的两个字符串键上,并给出第三个数字键的平均值和中位数统计”“”

输出:

代码语言:javascript复制
function mergeJsonArray(jsonArray, key1, key2, key3) {
  let mergedJson = {};
  let mergedJsonArray = [];

  jsonArray.forEach(item => {
    if (item[key1] in mergedJson) {
      if (item[key2] in mergedJson[item[key1]]) {
        mergedJson[item[key1]][item[key2]].push(item[key3]);
      } else {
        mergedJson[item[key1]][item[key2]] = [item[key3]];
      }
    } else {
      mergedJson[item[key1]] = {};
      mergedJson[item[key1]][item[key2]] = [item[key3]];
    }
  });

  for (const key1 in mergedJson) {
    for (const key2 in mergedJson[key1]) {
      let sum = 0.0;
      let median = 0.0;
      let mean = 0.0;
      let count = 0;
      let min = 0.0;
      let max = 0.0;

      mergedJson[key1][key2].forEach(item => {
        sum  = item;
        count  = 1;
      });

      mean = sum / count;

      mergedJson[key1][key2].sort((a, b) => a - b);
      median = mergedJson[key1][key2][Math.floor(mergedJson[key1][key2].length / 2)];

      min = mergedJson[key1][key2][0];
      max = mergedJson[key1][key2][mergedJson[key1][key2].length - 1];

      mergedJsonArray.push({
        [key1]: key1,
        [key2]: key2,
        'count': count,
        'sum': sum,
        'mean': mean,
        'median': median,
        'min': min,
        'max': max
      });
    }
  }
    return mergedJsonArray;
}

3. Co-pilot 的代码编写:识别并运用重复模式

我正在为我的测试环境编写一个跨多个数据库表进行操作的数据删除脚本。这些表都有时间戳列,但名称各不相同。我在注释中以逗号分隔的方式列出了所有的表名,然后编写了第一张表的删除 SQL 查询,以及整个删除命令的连接光标使用。完成这些后,Co-pilot 开始自动建议为这些表中的每一个迭代选择代码块,同时还根据其中的时间戳列的名称修改它们的列名。然而,它无法理解那个删除可能的顺序,它只按照模型文件中书写的顺序进行。

我在 IntelliJ 和 Sublime Text 中使用了 Co-pilot 插件。我发现 IntelliJ 插件在推荐上更具智能,尤其是在处理其他文件中的类定义的上下文时。

4. 通过描述需求使用 ChatGPT 生成整个 React.js 组件,只需进行少量变量调整

我在使用名为 react-flow 的 React.js 库时,想要定制部分组件替换库中的原有部分。我的目标是为其添加个性化的视觉效果,以及在组件顶部增添一些附加的文字。尽管文档详细地介绍了如何用新组件替换原有组件,但并没有明确地提到如何在保留原功能的情况下进行扩展。

于是,我向 ChatGPT 提出了问题:

如何在 react-flow 中创建自定义边,这条边是粗大的紫色线条,并且末端有一个大箭头

以下是我收到的答复:

代码语言:javascript复制
import React from 'react';

const CustomEdge = ({ id, sourceX, sourceY, targetX, targetY, style = {} }) => {
  const edgePath = `M ${sourceX},${sourceY} L ${targetX},${targetY}`;

  // 计算箭头的角度
  const angle = Math.atan2(targetY - sourceY, targetX - sourceX);
  const arrowLength = 10;// 箭头的长度

// 计算箭头头部的点
  const arrowPoints = [
    [targetX - arrowLength * Math.cos(angle - Math.PI / 6), targetY - arrowLength * Math.sin(angle - Math.PI / 6)],
    [targetX, targetY],
    [targetX - arrowLength * Math.cos(angle   Math.PI / 6), targetY - arrowLength * Math.sin(angle   Math.PI / 6)],
  ];

  return (
    <>
      <path
        id={id}
        d={edgePath}
        style={{
          fill: 'none',
          strokeWidth: '4px',
          stroke: 'violet',
          ...style, // 允许覆盖样式
        }}
      />
      <polygon
        points={arrowPoints.map(p => p.join(',')).join(' ')}
        fill="violet"
        stroke="violet"
        strokeWidth="1"
      />
    </>
  );
};

export default CustomEdge;

// 在你的 React Flow 图中使用自定义边缘组件
import ReactFlow from 'react-flow-renderer';
import CustomEdge from './CustomEdge';

const elements = [
// ... 你的节点和边
];

const App = () => {
  return (
    <div style={{ height: '500px' }}>
      <ReactFlow elements={elements} edgeTypes={{ customEdge: CustomEdge }} />
    </div>
  );
};

export default App;

对于这段代码,我只需要对选定的 CSS 样式进行一些微调。这段代码帮我节省了大约 30 分钟的编码时间,并且代码也能顺利运行。

5. 向 ChatGPT 请求代码片段,若运行未能成功,反馈错误信息,ChatGPT 将根据反馈进行修正直至问题解决

ChatGPT 擅长根据详尽的反馈来优化其答案。然而,反馈不只是请求再次生成或寻找更好的解决方案,你也可以在反馈中提供上下文信息。例如,我想在 react-flow 图中实现节点的自动布局,我发现有一个叫做 cola 的布局能够实现这个目标。由于在网络上难以找到具体实现的示例,我向 ChatGPT 提问:

给我一个样本代码,展示如何使用 react-flow 和 cola 布局来排列我的节点

输出:

代码语言:javascript复制
import React from 'react';
import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls } from 'react-flow-renderer';
import { ColaLayout } from 'react-flow-renderer/dist/layoutCola';

const MyFlowComponent = () => {
  const initialElements = [
    { id: '1', type: 'input', data: { label: 'Input Node' }, position: { x: 0, y: 0 } },
    { id: '2', data: { label: 'Node 2' }, position: { x: 200, y: 50 } },
    { id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
    { id: 'e1-2', source: '1', target: '2' },
    { id: 'e2-3', source: '2', target: '3' },

  ];

  const onLoad = (reactFlowInstance) => {
    reactFlowInstance.fitView();  // 使图形适应视口
  };

  const layout = {
    type: 'cola',
    edgeLength: 180,
    animate: true,
    randomize: false,
    maxSimulationTime: 1500,
  };

  return (
    <div style={{ height: '500px' }}>
      <ReactFlowProvider>
        <ReactFlow elements={initialElements} onLoad={onLoad} layout={layout}>
          <Controls />
        </ReactFlow>
      </ReactFlowProvider>
    </div>
  );
};

export default MyFlowComponent;

// 使用 npm 安装 cola:
npm install react-flow react-flow-renderer

然而,即便我按照提示进行了安装,代码仍然无法运行,出现了一个错误。

于是,我再次向 ChatGPT 提问:

它给我这样的错误 “Module not found: Error: Package path ./dist/layoutCola is not exported from package”。

输出:

代码语言:javascript复制
我为这个混淆道歉。看来 layoutCola 模块不再直接在 react-flow-renderer 包中可用。要在 React Flow 中使用 "cola" 布局算法,你可以安装 react-flow-dagre 包,它提供了包括 "cola" 布局在内的额外布局选项。

然后,ChatGPT 提供了替代的代码块,并且推荐我安装一个新的库:

代码语言:javascript复制
# 使用 npm
npm install react-flow react-flow-renderer react-flow-dagre

但这次安装过程中出现了错误:

代码语言:javascript复制
npm ERR! 404 Not Found - GET <https://registry.npmjs.org/react-flow-dagre> - Not found

现在,ChatGPT 已经明白我的需求,即使我没主动提问,它也开始提出其他建议,指导我实现节点布局的初衷。最后,尽管并未使用 cola 布局,我还是达成了我的目标,我的问题得到了解决。

近期,我打算在 Kafka 集群和 OpenSearch 服务之间建立消息连接。虽然 Kafka 提供了相应的连接器,但我对这方面的知识了解不够。我在网上寻找了一些配置示例,尽管我找到了详细的配置 Kafka 连接到 S3 桶的示例,但我并未找到使用 OpenSearch 作为数据接收端的示例。于是,我询问了 ChatGPT 该如何操作,它提供了一套完整的指导步骤来帮助我完成这个操作。我在网上搜索了这个答案,想要弄清楚它是 ChatGPT 自我生成的,还是基于其他示例推导的,但结果发现并无类似的文章。

局限性与挑战

尽管 AI 编程辅助工具极大地提高了编程效率,但我们也必须清醒地认识到,它并非完美无缺。我们不能完全依赖它生成的代码,而应该逐步检查和测试它的输出结果。

我在使用过程中,也发现了一些局限性:

  1. 有时,Copilot 会生成一些在当前代码上下文中不存在的变量。这可能是因为虽然编码过程中考虑到了变量命名的逻辑性,但并不能保证代码的正确运行。
  2. 当向 ChatGPT 查询某些工具或技术的操作指南时,可能由于其训练数据库的时效性问题,输出的结果有时会显得过时。有些工具可能已经进行了更新,界面也发生了改变,与 ChatGPT 提供的结果不一致。我在使用 AWS 的一些服务时就遇到过这样的情况。

你是否已经在工作中用 AI 来辅助编程? 你有什么看法和经验?

0 人点赞