提高您的AI助手的生产力。

最近,我开始尝试使用不同的AI助手来发现更多利用这些工具的可能性,而且我很惊喜地了解到了一些我以前不知道的东西。

GitHub Copilot被认为能够了解您项目的上下文。这在某种程度上是正确的。它能理解您项目的堆栈和所使用的库。但是,上下文并不完整;它不能详细理解它。根据GitHub上的这一讨论,我们现在了解了嵌入在背后生成提示的基本逻辑(从VS Code插件到LLM)。

Copilot从代码编辑器中获取上下文信息。它不需要访问您的存储库。发送给这个模型的代码上下文通常被称为“提示”。我们不断尝试新的方法来创建提示,以便从模型中获取更高质量的建议。

这就是为什么AI助手并不能始终提供一成不变的答案。今天它可能会提出精彩的建议,但明天可能会产生一些奇怪的建议。

举个例子,我们今天使用的一种技术是在相邻的文件(即在代码编辑器中打开的选项卡)中寻找相关的代码。想象一下,你打开了两个文件 —— 一个定义了一个类,另一个是该类的单元测试。通过同时查看这两个文件,我们可以更多地了解相关代码的上下文,这将导致更高质量的建议。

是的,没错,但正如我所说,上下文还不完整。让我们尝试用一个简单的例子来重现它。假设我们有一个经典的NestJS应用程序,其中有一个名为“Tasks”的模块。当然,我们有一个负责数据存储的TasksService,并且设计用于TasksController使用。

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Task } from './task.entity';
import { CreateTaskDto } from './dto/create-task.dto';

@Injectable()
export class TasksService {
constructor(
@InjectRepository(Task)
private taskRepository: Repository<Task>,
) {}

async create(createTaskDto: CreateTaskDto): Promise<Task> {
const task = this.taskRepository.create(createTaskDto);
await this.taskRepository.save(task);
return task;
}

async findAll(): Promise<Task[]> {
return this.taskRepository.find();
}

async findOne(id: number): Promise<Task> {
return this.taskRepository.findOne(id);
}

async update(id: number, updateTaskDto: CreateTaskDto): Promise<Task> {
const task = await this.taskRepository.findOne(id);
if (!task) {
return null;
}
Object.assign(task, updateTaskDto);
await this.taskRepository.save(task);
return task;
}

async remove(id: number): Promise<void> {
const task = await this.taskRepository.findOne(id);
if (!task) {
return;
}
await this.taskRepository.remove(task);
}
}

现在,我想要创建一个控制器,以下是我的聊天提示:

基于TasksService,实现TasksController和CRUD方法。

import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { Task } from './task.entity';

@Controller('tasks')
export class TasksController {
constructor(private tasksService: TasksService) {}

@Get()
async findAll(): Promise<Task[]> {
return this.tasksService.findAll();
}

@Get(':id')
async findOne(@Param('id') id: string): Promise<Task> {
return this.tasksService.findOne(id);
}

@Post()
async create(@Body() task: Task): Promise<Task> {
return this.tasksService.create(task);
}

@Put(':id')
async update(@Param('id') id: string, @Body() task: Task): Promise<Task> {
return this.tasksService.update(id, task);
}

@Delete(':id')
async delete(@Param('id') id: string): Promise<void> {
return this.tasksService.delete(id);
}
}

好的,很酷。乍一看,一切似乎都很好。除了一些问题,这段代码是不兼容的,也没有计算TasksService类的方法。

❌ TasksService没有“delete”方法,但有“remove”方法。❌ id参数是字符串,但TasksService需要数字类型。❌ 它没有计算CreateTaskDto,这在项目中也存在。

当然,我可以手动修复它;看起来似乎没有问题。但是如果我付费使用这项服务,我希望能从中获得最大的价值。

在这里,我之前不知道的“工作区”功能派上了用场。在提示符中添加“@workspace”命令,你会得到魔法:

➡️ @workspace 基于TasksService实现TasksController的CRUD方法

import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { CreateTaskDto } from './dto/create-task.dto';

@Controller('tasks')
export class TasksController {
constructor(private readonly tasksService: TasksService) {}

@Post()
async create(@Body() createTaskDto: CreateTaskDto) {
return this.tasksService.create(createTaskDto);
}

@Get()
async findAll() {
return this.tasksService.findAll();
}

@Get(':id')
async findOne(@Param('id') id: number) {
return this.tasksService.findOne(id);
}

@Put(':id')
async update(@Param('id') id: number, @Body() updateTaskDto: CreateTaskDto) {
return this.tasksService.update(id, updateTaskDto);
}

@Delete(':id')
async remove(@Param('id') id: number) {
return this.tasksService.remove(id);
}
}

最终,这就是我想要的 - 使用我的项目的背景和现有的类,并在保存文件后立即运行的兼容代码。

✅ TasksService调用“remove”方法。 ✅ id参数是数字类型。 ✅ CreateTaskDto的使用。

顺便说一下,该插件会指示有哪些文件被用于上下文。LLM拥有越多的上下文,结果将会越好。

Files that were used to create the context before sending the request to LLM.

我不明白为什么默认情况下不使用“@workspace”前缀的功能。我更倾向于反向使用它:在非项目上下文的问题中使用“@everywhere”,并在日常编码例程中不使用前缀。

但是答案可能相当琐碎 —— 它更便宜。对于每个“提示”,使用额外的上下文可以极大地增加服务器负载,并使得微软付出巨大代价。并且在使用此功能时要注意 —— 对于与您的项目无关的问题,使用“@workspace”没有意义 —— 响应会更快且更广泛,因为有时候超越项目的范围去思考会更好 ;)

2024-02-14 04:22:09 AI中文站翻译自原文