Help us learn about your current experience with the documentation. Take the survey.

---
stage: AI-powered
group: AI Framework
info: 本页面由开发者关系团队维护,作者@dnsmichi,详见 https://handbook.gitlab.com/handbook/marketing/developer-relations/developer-advocacy/content/#maintained-documentation
description: 原生AI功能和特性。
title: GitLab Duo用例
---

以下用例提供了使用GitLab Duo的实用示例、练习和工作流程。学习如何:

- 重构现有源代码。
- 使用GitLab Duo根因分析排查失败作业。
- 解决安全漏洞。

如果您使用GitLab自托管版:GitLab Duo需要GitLab 17.2及以上版本以获得最佳用户体验和结果。早期版本可能仍能运行,但体验可能会下降。

## 使用GitLab Duo解决开发挑战 ### 从C#应用开始 在这些示例中,打开您的C# IDE,确保[已启用GitLab Duo](turn_on_off.md),并探索如何使用GitLab Duo的原生AI功能来提高效率。 #### 查询GitLab REST API的CLI工具 <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> 观看 [GitLab Duo咖啡聊天:开始使用C#](https://www.youtube.com/watch?v=AdRtX9L--Po) <!-- 视频发布于2024-01-30 --> 挑战是创建一个用于查询GitLab REST API的CLI工具。 - 向GitLab Duo Chat询问如何启动新的C#项目以及如何使用dotNET CLI: ```markdown 如何在VS Code中开始创建一个空的C#控制台应用程序
  • 使用代码建议生成带有新代码注释的REST API客户端:

    // 连接到REST API并打印响应
  • 生成的源代码可能需要解释:使用代码任务/explain了解REST API调用的工作原理。

生成源代码后,您需要配置CI/CD。

  • Chat可以帮助提供C#项目的.gitignore文件的最佳实践:

    显示C#项目的.gitignore和.gitlab-ci.yml配置。
  • 如果您的CI/CD作业失败,请使用根因分析来排查失败的CI/CD作业。或者,您可以将错误消息复制到GitLab Duo Chat中寻求帮助:

    解释CI/CD错误:当前的.NET SDK不支持定位.NET 8.0
  • 要稍后创建测试,请要求GitLab Duo使用代码任务/refactor将选定的代码重构为函数。

  • Chat还可以解释特定编程语言的关键字和函数,或C#编译器错误。

    能否用实际例子解释C#中的async和await
    解释错误CS0122:由于保护级别,“Program”无法访问
  • 使用/tests代码任务生成测试。

下一个问题是在C#解决方案中将生成的测试放在哪里。作为初学者,您可能不知道应用程序和测试项目必须位于同一解决方案级别,以避免导入问题。

  • GitLab Duo Chat可以通过提问和完善提示词来帮助您:

    在C#和VS Code中,如何从测试项目添加对另一个项目的引用?提供我可以添加到C# .csproj文件的XML配置,以便在现有解决方案中引用另一个项目?
  • 有时,您必须完善提示词以获得更好的结果。提示词/refactor into the public class会生成一段代码提案,该代码以后可以从测试项目中访问。

    /refactor into the public class
  • 您也可以使用/refactor代码任务向Chat询问如何在.gitlab-ci.yml文件中执行测试。

    /refactor 添加一个运行测试(测试项目)的作业

资源:

改进C++应用


#### 重构一个使用SQLite的C++应用

在这个示例中,现有的源代码包含一个单独的main函数。它重复了代码,并且无法进行测试。

<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
观看[GitLab Duo咖啡聊天:C++、SQLite和CMake](https://www.youtube.com/watch?v=zGOo1jzQ5zM)
<!-- 视频发布于2024-01-10 -->

要将源代码重构为可复用且可测试的函数:

1. 打开启用了GitLab Duo的VS Code或Web IDE。
1. 选择源代码,并使用精炼的提示让GitLab Duo Chat将其重构为函数:

   ```markdown
   /refactor into functions

这个重构步骤可能不会对整个选定的源代码有效。

  1. 将重构策略拆分为功能块。 例如,迭代数据库中的所有插入、更新和删除操作。

  2. 要为新创建的函数生成测试,再次选择源代码并使用代码任务/tests。包含针对测试框架的具体提示说明:

    /tests using the CTest test framework
  3. 如果您的应用程序使用Boost.Test框架,请优化提示:

    /tests using the Boost.Test framework

资源:

将C++函数重构为面向对象的代码

在这个示例中,现有源代码已被封装到函数中。 为了将来支持更多数据库类型,代码必须重构为类和对象继承。

GitLab Duo咖啡聊天:将C++函数重构为OOP中观看这些步骤的演示

开始处理类
  • 要求GitLab Duo Chat解释如何实现基类数据库类的面向对象模式,并在SQLite类中继承它:

    解释使用基类实现的通用数据库实现,以及使用C++的SQLite特定类。提供源码示例和后续步骤。
  • 学习曲线包括询问GitLab Duo Chat关于纯虚函数以及在实现类中进行虚函数重写的知识。

    什么是纯虚函数,继承该类的开发人员需要做什么?
  • 代码任务可以帮助重构代码。选择C++头文件中的函数,并使用精炼的提示:

    /refactor into class with public functions, and private path/db attributes. Inherit from the base class DB
    
    /refactor into a base class with pure virtual functions called DB. Remove the SQLite specific parts.
  • GitLab Duo Chat还会指导构造函数重载、对象初始化以及使用共享指针优化内存管理。

    如何向cpp文件中的类添加函数实现?
    
    如何通过类构造函数调用传递值给类属性?
寻找更好的答案
  • 以下问题未提供足够上下文。

    我应该使用virtual override而不是just override吗?
  • 相反,尝试添加更多上下文以获得更好的答案。

    在实现继承类的纯虚函数时,我应该使用虚函数重写(virtual override),还是仅使用函数重写(function override)?上下文是C++。
  • 一个相对复杂的问题涉及如何从新创建的类实例化对象并调用特定函数。

    如何在C++中从一个类实例化对象,使用SQLite数据库路径调用构造函数并调用函数。偏好使用指针。
  • 结果可能有帮助,但需要对共享指针和必需的源码头文件进行优化。

    如何在C++中从一个类实例化对象,使用SQLite数据库路径调用构造函数并调用函数。偏好使用共享指针。解释哪些头文件包含是必要的。
  • 代码建议有助于生成std::shared_ptr的正确语法,并提高代码质量。

    // 定义SQLite路径变量,默认值为database.db
    
    // 为SQLite类创建共享指针
    
    // 使用OpenConnection打开数据库连接
    
重构你的代码
  • 重构源代码后,可能会出现编译错误。请Chat解释这些错误。

    解释错误:`db``SQLiteDB` 的私有成员
  • 特定的SQL查询字符串应重构为多行字符串,以便更高效地编辑。

    std::string sql = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL)";
  • 选择源代码,并使用 /refactor 代码任务:

    /refactor into a stringstream with multiple lines
  • 你也可以将实用函数重构为带有静态函数的C++类,然后询问Chat如何调用它们。

    /refactor into a class providing static functions
    
    How to call the static functions in the class?

重构源代码后,构建了更多数据库类型的基础,整体代码质量得到提升。

Resources:

解释、测试并重构一个 Kotlin 应用程序

在此示例中,需分析并改进来自 Kotlin 代码生成提示 的冒险应用程序,通过重构和测试提升其质量。

当前源代码如下:

package org.example

// 创建文字冒险游戏
// 寻找金色乐高砖块
// 添加视觉辅助功能
// 使用随机计时器陷阱触发游戏结束
// 创建文字冒险游戏
fun createTextAdventure() {
    println("欢迎来到金色乐高砖块冒险!")
    println("你发现自己身处一间光线昏暗的房间。你会怎么做?")

    var gameOver = false
    while (!gameOver) {
        println("1. 寻找金色乐高砖块")
        println("2. 检查房间")
        println("3. 退出")

        val choice = readLine()?.toIntOrNull() ?: 0
        when (choice) {
            1 -> searchForBrick()
            2 -> examineRoom()
            3 -> {
                println("再见!")
                gameOver = true
            }
            else -> println("无效选择。请重试。")
        }
    }
}

fun searchForBrick() {
    println("你仔细搜索房间,寻找金色乐高砖块的踪迹。")
    if (Math.random() < 0.2) {
        println("恭喜!你找到了金色乐高砖块!")
    } else {
        println("你的搜索一无所获。你必须再试一次。")
    }
}

fun examineRoom() {
    println("你环顾房间,观察细节。")
    println("房间光线昏暗,角落有阴影。")
    println("北面有一扇门,房间中央有一张桌子。")
}

fun main() {
    createTextAdventure()
}
  1. 在 IDE 中选择源代码,然后右键点击以使用 GitLab Duo Chat 解释代码。

  2. 优化提示词以了解更多关于 bug、优化技巧或漏洞的信息:

    /explain focus on bugs and improvements
    
    提供的代码是一个用 Kotlin 编写的简单文字冒险游戏。它允许用户寻找金色乐高砖块或检查房间。虽然代码能正常运行,但仍存在一些潜在的 bug 和可改进之处:
    
    1. 潜在 Bug:
    
    searchForBrick() 函数使用 Math.random() 来确定玩家是否找到金色乐高砖块。然而,该函数未处理玩家找到砖块的情况。即使玩家已找到砖块,游戏仍会无限继续。
    
    2. 改进建议:
    
    游戏结束条件:当玩家找到金色乐高砖块时,游戏应具备适当的游戏结束条件。这可以通过引入布尔标志或单独的游戏状态来跟踪砖块是否已被找到来实现。
  3. 使用 /tests 命令让 Chat 为选定的代码生成测试:

    /tests
    
    要测试代码,我们可以使用 Kotlin 的 JUnit。以下是一些你可以编写的测试:
    
      import org.junit.jupiter.api.Test
      import java.io.ByteArrayInputStream
      import java.io.ByteArrayOutputStream
      import java.io.PrintStream
    
      class TextAdventureTest {
    
          private val standardOut = System.out
          private val standardIn = System.`in`
    
          @Test
          fun `test searchForBrick success`() {
              val outContent = ByteArrayOutputStream()
              System.setOut(PrintStream(outContent))
    
              searchForBrick()
    
              val output = outContent.toString().trim()
              assert(output.contains("恭喜!你找到了金色乐高砖块!"))
    
              System.setOut(standardOut)
          }
    
       ...
      }

确保一切经过测试后,请求 Chat 重构选定代码:

/refactor fix bugs, improve UX

...

改进建议:

- 将菜单打印逻辑提取到独立的 printMenu 函数中,以提高代码组织和可读性
- 使用 Random.nextDouble() 替代 Math.random(),以更好地兼容 Kotlin 标准库
- 打印菜单后添加用户输入选择的提示
- 移除了不必要的 gameOver 变量初始化(已在 createTextAdventure 函数中赋值)
- 在 searchForBrick 函数中添加注释,提醒你可能需要添加额外逻辑或游戏结束条件

这些更改应能提高代码的可读性、可维护性和用户体验。

重构后的源代码可能如下所示:

package org.example

import kotlin.random.Random

// 创建文字冒险游戏
// 寻找金色乐高砖块
// 添加视觉辅助功能
// 使用随机计时器陷阱触发游戏结束
// 创建文字冒险游戏
fun createTextAdventure() {
    println("欢迎来到金色乐高砖块冒险!")
    println("你发现自己身处一间光线昏暗的房间。你会怎么做?")

    var gameOver = false
    while (!gameOver) {
        printMenu()
        val choice = readLine()?.toIntOrNull()
when (选择) {
    1 -> 搜索乐高积木()
    2 -> 检查房间()
    3 -> {
        println("再见!")
        游戏结束 = true
    }
    否则 -> println("无效的选择。请重试。")
}
}

fun 打印菜单() {
    println("1. 搜索金色的乐高积木")
    println("2. 检查房间")
    println("3. 退出")
    print("输入你的选择:")
}

fun 搜索乐高积木() {
    println("你仔细地搜查房间,寻找任何金色彩色积木的迹象。")
    if (Random.nextDouble() < 0.2) {
        println("恭喜!你找到了金色的乐高积木!")
        // 在此处添加额外的逻辑或游戏结束条件
    } else {
        println("你的搜索一无所获。你必须再试一次。")
    }
}

fun 检查房间() {
    println("你环顾房间四周,留意细节。")
    println("房间光线昏暗,角落有阴影。")
    println("北面有一扇门,房间中央有一张桌子。")
}

fun 主函数() {
    创建文字冒险()
}

开始使用 PowerShell

PowerShell 支持是实验性的.

  1. 使用 GitLab Duo Chat 询问如何开始编写一个打印当前目录文件大小的 PowerShell 脚本。

    How to get started with a PowerShell script that prints the file size of the current directory?

    或者,您可以使用 Code Suggestions 生成源代码。

  2. 创建一个新的脚本 get-file-sizes.ps1,内容如下:

    # 收集目录中的文件并打印其大小
  3. 等待 Code Suggestions 完成提示,然后添加以下提示以尝试不同的输出格式:

    # 收集目录中的文件并打印其大小
    
    $directory = Read-Host -Prompt "输入获取文件大小的目录路径"
    $files = Get-ChildItem -Path $directory -File
    foreach ($file in $files) {
        $fileSize = [Math]::Round(($file.Length / 1KB), 2)
        Write-Host "$($file.Name) - $fileSize KB"
    }
    
    # 重复上述代码,但将结果存储到 CSV 文件中
  4. 使用不同导出格式的提示重复上述步骤,或使用 Code Suggestions 自动补全。例如:


# 收集目录中的文件并打印其大小

$directory = Read-Host -Prompt "输入获取文件大小的目录路径"
$files = Get-ChildItem -Path $directory -File
foreach ($file in $files) {
    $fileSize = [Math]::Round(($file.Length / 1KB), 2)
    Write-Host "$($file.Name) - $fileSize KB"
}

# 重复上述代码,但将结果存储到 CSV 文件中
$csvFile = "$directory\file-sizes.csv"
$fileData = foreach ($file in $files) {
    [PSCustomObject]@{
        FileName = $file.Name
        FileSize = [Math]::Round(($file.Length / 1KB), 2)
    }
}
$fileData | Export-Csv -Path $csvFile -NoTypeInformation
Write-Host "文件大小已保存到 $csvFile"

# 重复上述代码,但将结果存储到 JSON 文件中
$jsonFile = "$directory\file-sizes.json"
$fileData | ConvertTo-Json | Out-File -FilePath $jsonFile
Write-Host "文件大小已保存到 $jsonFile"

# 重复上述代码,但将结果存储到 XML 文件中
$xmlFile = "$directory\file-sizes.xml"
$fileData | ConvertTo-Xml -NoTypeInformation | Out-File -FilePath $xmlFile
Write-Host "文件大小已保存到 $xmlFile"

# 重复上述代码,但将结果存储到 HTML 文件中
$htmlFile = "$directory\file-sizes.html"
$fileData | ConvertTo-Html -Property FileName, FileSize | Out-File -FilePath $htmlFile
Write-Host "文件大小已保存到 $htmlFile"

# 重复上述代码,但将结果存储到 TXT 文件中
$txtFile = "$directory\file-sizes.txt"
$fileData | Out-File -FilePath $txtFile
Write-Host "文件大小已保存到 $txtFile"

解释并解决漏洞

C代码中的漏洞

在此示例中,检测到的C语言安全漏洞应借助GitLab Duo进行修复。

观看这些步骤的演示:GitLab Duo咖啡聊天:漏洞解决挑战 #1

此源代码片段 引入了一个由缓冲区溢出导致的安全漏洞:

    strcpy(region, "Hello GitLab Duo Vulnerability Resolution challenge");

    printf("Contents of region: %s\n", region);

SAST安全扫描器 可以检测并报告该问题。使用Vulnerability Explanation 了解问题。 漏洞解决有助于生成合并请求(MR)。 如果建议的更改不符合要求或可能导致问题,您可以使用代码建议和聊天功能来优化。例如:

  1. 打开VS Code或启用GitLab Duo的Web IDE,并添加带有指令的注释:

        // 避免潜在的缓冲区溢出
    
        // 可能的AI生成的代码如下
        strncpy(region, "Hello GitLab Duo Vulnerability Resolution challenge", pagesize);
        region[pagesize-1] = '{content}';
        printf("Contents of region: %s\n", region);
  2. 删除建议的代码,改用其他注释采用替代方法。

        // 使用snprintf()避免潜在缓冲区溢出
    
        // 可能的AI生成的代码如下
        snprintf(region, pagesize, "Hello GitLab Duo Vulnerability Resolution challenge");
    
        printf("Contents of region: %s\n", region);
  3. 使用GitLab Duo Chat提问。/refactor 代码任务可生成不同建议。 若偏好特定算法或函数,细化提示:

    /refactor using snprintf

资源:

回答关于GitLab的问题

在此示例中,挑战是通过GitLab Duo Chat解决问题。

观看这些步骤的演示:GitLab Duo咖啡聊天:使用GitLab Duo Chat解决问题挑战

  • 您可以使用GitLab Duo Chat解释CI/CD错误。

    解释此CI/CD错误:build.sh: 第14行:go命令未找到
  • 当您不耐烦时,仅输入一两个词会发生什么?

    labels
    
    issue labels

    GitLab Duo Chat会要求更多上下文。

  • 将问题优化为完整句子,描述问题并寻求解决方案。

    解释GitLab中的标签。提供一个高效使用的示例。

资源:

根因分析用例

使用根因分析确定CI/CD作业失败的根本原因。以下示例说明常见错误,并鼓励您分叉实践以查找和修复根本原因。

更多信息请参阅博客文章:开发GitLab Duo:结合AI与根因分析修复CI/CD管道

分析缺失的Go运行时

CI/CD作业可以在从贡献的image属性生成的容器中执行。若容器未提供编程语言运行时,引用go二进制的script部分会失败。例如,需理解和修复错误消息/bin/sh: eval: line 149: go: not found。若容器运行时环境中找不到go命令,可能由以下原因导致:

  • 作业使用了类似alpine的精简容器镜像,且未安装Go语言运行时;
  • 作业使用了CI/CD配置中指定的错误默认容器镜像,或使用了default关键字;
  • 作业使用了Shell执行器而非容器镜像。宿主操作系统损坏、未安装Go语言运行时或未正确配置。

该项目挑战:根因分析 - Go GitLab发布获取器提供了一个练习,用于分析和修复包含Go Tanuki应用的CI/CD问题。在该练习中,builddocker-build作业失败。修复问题后,CI/CD流水线成功,且build作业会打印输出。solution/目录提供了两种可能的解决方案。

使用GitLab Duo为GitLab做贡献

GitLab Duo的使用聚焦于为GitLab代码库做贡献,以及客户如何更高效地参与贡献。

GitLab代码库体量庞大,有时需要理解复杂算法或特定应用实现。

为前端做贡献:个人资料设置

本例中,挑战是更新GitLab个人资料页面并优化社交网络设置。

观看录制视频:GitLab Duo咖啡聊天:用代码建议和聊天为GitLab做贡献

你可使用GitLab Duo聊天解释和重构代码、生成测试。代码建议能辅助完成现有代码,还可生成Ruby、Go或VueJS的新函数与算法。

  1. /explain代码任务解释选定代码片段,学习HAML模板工作原理;
  2. 可细化代码任务提示,改问/explain how HAML rendering works

也可直接在聊天框输入,例如:

如何在haml中填充select

重构示例如下:

  1. /refactor into a HAML dropdown
  2. 检查现有UI表单代码后,将提示细化为/refactor into a HAML dropdown with a form select

GitLab Duo聊天助力错误调试,会在错误消息前添加前缀:

解释此错误:undefined method `icon' for

代码生成提示

以下示例提供了代码生成提示,对应GitLab Duo中支持的语言。可通过多行注释细化代码生成提示。

这些示例存放在GitLab Duo提示项目中,由开发者关系团队维护。示例经测试有效,你应结合自身环境审阅并适配。

C代码生成提示

创建一个Linux统计工具,收集I/O、性能、磁盘使用及TCP延迟,并打印结果。完整示例见博客文章高效AI驱动代码建议与GitLab Duo的最佳实践

// 创建Linux统计工具
// 收集IO、性能、磁盘使用、TCP延迟
// 打印摘要

// 导入所需头文件
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <sys/statfs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>

int main() {
    struct stat statbuf;

    if (stat("/etc", &statbuf) != 0) {
        perror("stat");
        return 1;
    }

    printf("IO块大小: %ld\n", statbuf.st_blksize);

    // TODO: 添加CPU使用率、磁盘使用、网络延迟测量

AI生成的源码示例可在GitLab Duo提示项目的c目录找到。

C++代码生成提示

创建一个充当HTTP客户端的CLI应用程序。

// 创建一个作为HTTP客户端的CLI应用
// 创建主函数
// 包含所有头文件
// 读取程序选项:URL、API端点、基本认证

#include <iostream>
#include <curl/curl.h>
#include <string>

int main(int argc, char** argv) {
  std::string url;
  std::string endpoint;
  std::string username;
  std::string password;

  // 解析命令行选项
  // ...

  CURL* curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

    // 设置基本认证
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_easy_setopt(curl, CURLOPT_USERPWD, (username + ":" + password).c_str());

    CURLcode res = curl_easy_perform(curl);

    if(res != CURLE_OK) {
      std::cerr << "请求失败:" << curl_easy_strerror(res) << std::endl;
    }

    curl_easy_cleanup(curl);
  }

  return 0;
}

创建一个用于管理分布式文件节点的应用程序。

// 创建一个用于管理分布式文件节点的应用程序
// 提供节点健康状态的概览
// 使用面向对象模式定义基础文件节点
// 添加继承自基础文件的特定文件系统

class FileNode {
public:
    std::string name;
    std::string ipAddress;
    int port;
    HealthState healthState;

    FileNode(std::string name, std::string ipAddress, int port)
        : name(name), ipAddress(ipAddress), port(port), healthState(HealthState::Healthy) {}

    void setHealthState(HealthState state) {
        healthState = state;
    }
};

class LocalFileNode : public FileNode {
public:
    std::string mountPoint;

    LocalFileNode(std::string name, std::string mountPoint)
        : FileNode(name, "127.0.0.1", 0), mountPoint(mountPoint) {}
};

class NetworkFileNode : public FileNode {
public:
    std::string user;
    std::string password;

    NetworkFileNode(std::string name, std::string ipAddress, int port, std::string user, std::string password)
        : FileNode(name, ipAddress, port), user(user), password(password) {}
};

int main(){

}

创建一个附加到XDP内核事件的eBPF程序以测量网络流量。 仅适用于Linux内核。

// 创建一个附加到XDP内核事件的eBPF程序
// 按IP地址统计所有数据包
// 打印摘要
// 包含必要的头文件

#include <bpf/bpf.h>

struct data {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __type(key, uint32_t);
    __type(value, uint64_t);
};

BPF_TABLE("array", int, long, counts, 1024);

int xdp_prog(struct xdp_md *ctx) {
    void* data_end = (void*)(long)ctx->data_end;
    void* data = (void*)(long)ctx->data;
    struct ethhdr *eth = data;

    if ((void*)eth + sizeof(*eth) <= data_end) {
        struct iphdr *ip = data + sizeof(*eth);
        if ((void*)ip + sizeof(*ip) <= data_end) {
            counts.increment(ip->saddr);
        }
    }

    return XDP_PASS;
}

AI生成的源码示例可在GitLab Duo Prompts项目的c++目录中获取。

C#代码生成提示

创建一个医疗分析器应用,从不同传感器收集数据并存储到MSSQL中。

// 创建一个医疗分析器应用
// 从不同传感器收集数据
// 将数据存储在MSSQL中
// 提供访问传感器数据的方法

using System.Data.SqlClient;

namespace MedicalAnalyzer
{
    public class SensorDataStore
    {
        private SqlConnection connection;

        public SensorDataStore()
        {
            // 创建SQL Server连接
            connection = new SqlConnection("connection string here");
        }

        public void StoreSensorData(SensorData data)
        {
            // 打开连接
            connection.Open();

            // 向数据库插入传感器数据
            var command = connection.CreateCommand();
            command.CommandText = "INSERT INTO SensorData (Timestamp, DeviceId, Value) " +
                                  "VALUES (@timestamp, @deviceId, @value)";
            command.Parameters.AddWithValue("@timestamp", data.Timestamp);
            command.Parameters.AddWithValue("@deviceId", data.DeviceId);
            command.Parameters.AddWithValue("@value", data.Value);
            command.ExecuteNonQuery();

            // 关闭连接
            connection.Close();
        }

        public SensorData[] GetSensorData(DateTime startTime, DateTime endTime)
        {
            // 查询数据库并返回结果
        }
    }
}

AI生成的源码示例可在GitLab Duo Prompts项目的c#目录中获取。

CSS代码生成提示

/* 创建用于彩虹动画的CSS类 */

@keyframes rainbow {
    0% {
        background-position: 0% 50%;
    }
    50% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0% 50%;
    }
}

.rainbow {
    background: linear-gradient(to right, #ff0000, #ff7700, #ffff00, #00ff00, #0000ff, #8b00ff);
    background-size: 600% 600%;
    animation: rainbow 30s ease infinite;
}

AI生成的源码示例可在GitLab Duo Prompts项目的css目录中找到。

Go代码生成提示

创建一个用于Kubernetes的可观测性应用,该应用读取并打印集群中容器、Pod和服务的状态。

// 为Kubernetes可观测性创建客户端
// 创建一个函数
// 从KUBECONFIG环境变量读取Kubernetes配置文件
// 创建Kubernetes上下文,默认命名空间
// 检查容器、Pod、服务状态并打印概览
// 导入必要的包
// 创建主程序包

package main

import (
  "context"
  "fmt"
  "os"

  "k8s.io/client-go/kubernetes"
  "k8s.io/client-go/tools/clientcmd"

  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func main() {

  clientset := getClientset()
  namespace := "default"

  printPods(clientset, namespace)
  printServices(clientset, namespace)
  printContainers(clientset, namespace)

}

func getClientset() *kubernetes.Clientset {

  kubeconfig := os.Getenv("KUBECONFIG")

  config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
  if err != nil {
    panic(err)
  }

  clientset, err := kubernetes.NewForConfig(config)
  if err != nil {
    panic(err)
  }

  return clientset
}

func printPods(clientset *kubernetes.Clientset, namespace string) {

  pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
  if err != nil {
    panic(err)
  }

  fmt.Printf("在%s命名空间中有%d个Pod\n", namespace, len(pods.Items))

}

func printServices(clientset *kubernetes.Clientset, namespace string) {

  services, err := clientset.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
  if err != nil {
    panic(err)
  }

  fmt.Printf("在%s命名空间中有%d个服务\n", namespace, len(services.Items))

}

// 创建一个打印容器的函数
// 收集并打印数量

func printContainers(clientset *kubernetes.Clientset, namespace string) {

    pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        panic(err)
    }

    var totalContainers int
    for _, pod := range pods.Items {
        totalContainers += len(pod.Spec.Containers)
    }

    fmt.Printf("在%s命名空间中有%d个容器\n", namespace, totalContainers)

}

观看录制视频:GitLab Duo咖啡聊天:使用Go和Kubernetes可观测性的代码生成挑战

创建一个内存中的键值存储,类似于Redis。完整教程请参阅博客文章:高效利用AI驱动的代码建议与GitLab Duo的技巧

// 创建一个内存中的键值存储,类似于Redis
// 提供方法来
// 设置/删除键
// 更新值
// 列出/打印(带过滤条件)
// 使用BoltDB作为外部库

AI生成的源码示例可在GitLab Duo Prompts项目的go目录中找到。

Java代码生成提示

创建一个数据分析应用,支持不同数据源的指标。 提供数据查询和聚合的API。

// 创建一个数据分析应用
// 解析不同的输入源及其值
// 将指标以列式格式存储
// 提供API进行数据查询和聚合

AI生成的源码示例可在GitLab Duo Prompts项目的java目录中找到。

JavaScript代码生成提示

为员工创建一个基于ReactJS的带薪休假应用程序,包含日期时间选择器。

// 为用户创建带薪休假应用
// 在ReactJS中创建日期时间选择器
// 提供开始和结束选项
// 根据所选国家显示公共假期
// 将请求发送到服务器API

AI生成的源码示例可在GitLab Duo Prompts项目的javascript目录中找到。

HTML代码生成提示

<!-- 创建一个AI知识库。
描述AI如何在高效的DevSecOps工作流程中提供帮助。
添加一个包含一个Dev、一个Ops和一个Sec示例的表格。
-->

<table>
  <tr>
    <th>Dev</th>
    <th>Ops</th>
    <th>Sec</th>
  </tr>
  <tr>
    <td>自动化测试和持续集成</td>
    <td>基础设施即代码与自动化配置</td>
    <td>静态代码分析与漏洞扫描</td>
  </tr>
</table>

AI生成的源码示例可在GitLab Duo Prompts项目的html目录中找到。

Kotlin代码生成提示

生成一个文字冒险游戏并寻找宝藏。添加视觉辅助工具,使用随机计时陷阱来结束游戏。

package org.example

// 创建文字冒险游戏
// 寻找金色乐高积木
// 添加视觉辅助工具
// 使用随机计时陷阱结束游戏
// 创建文字冒险游戏
fun createTextAdventure() {
    println("欢迎来到金色乐高积木冒险!")
    println("你身处在一个光线昏暗的房间。你会怎么做?")

    var gameOver = false
    while (!gameOver) {
        println("1. 寻找金色乐高积木")
        println("2. 检查房间")
        println("3. 退出")

        val choice = readLine()?.toIntOrNull() ?: 0
        when (choice) {
            1 -> searchForBrick()
            2 -> examineRoom()
            3 -> {
                println("再见!")
                gameOver = true
            }
            else -> println("无效选择。请重试。")
        }
    }
}

fun searchForBrick() {
    println("你仔细搜索房间,寻找金色乐高积木的踪迹。")
    if (Math.random() < 0.2) {
        println("恭喜!你找到了金色乐高积木!")
    } else {
        println("你的搜索一无所获。你得再试试。")
    }
}

fun examineRoom() {
    println("你环顾房间,观察细节。")
    println("房间光线昏暗,角落有阴影。")
    println("北边有一扇门,中央有一张桌子。")
}

fun main() {
    createTextAdventure()
}

AI生成的源码示例可在GitLab Duo Prompts项目的kotlin目录中找到。

PHP代码生成提示

为GitLab发布创建一个RSS feed获取器,允许按标题过滤。

// 创建一个网页表单展示GitLab发布信息
// 从https://about.gitlab.com/atom.xml获取RSS feed
// 提供标题过滤选项

$feedUrl = 'https://about.gitlab.com/atom.xml';

$xml = simplexml_load_file($feedUrl);

$titleFilter = $_GET['titleFilter'];

echo '<h1>GitLab发布</h1>';
echo '<ul>';
foreach ($xml->entry as $entry) {
    $title = $entry->title;
    if (empty($titleFilter) || strpos($title, $titleFilter) !== false) {
        echo '<li>' . $title . '</li>';
    }
}
echo '</ul>';

AI生成的源码示例可在GitLab Duo Prompts项目的php目录中找到。

PowerShell代码生成提示

创建一个脚本,收集目录中的所有文件并打印其大小。优化提示以将结果存储在CSV或JSON文件中。


# 收集目录中的文件并打印其大小

$directory = Read-Host -Prompt "输入要获取文件大小的目录路径"
$files = Get-ChildItem -Path $directory -File
foreach ($file in $files) {
    $fileSize = [Math]::Round(($file.Length / 1KB), 2)
    Write-Host "$($file.Name) - $fileSize KB"
}

# 重复上述代码,但将结果存储在CSV文件中

$csvFile = "$directory\file-sizes.csv"
$fileData = foreach ($file in $files) {
    [PSCustomObject]@{
        FileName = $file.Name
        FileSize = [Math]::Round(($file.Length / 1KB), 2)
    }
}
$fileData | Export-Csv -Path $csvFile -NoTypeInformation
Write-Host "文件大小已保存至 $csvFile"

重复上面的代码,但将结果存储在JSON文件中

$jsonFile = "$directory\file-sizes.json"
$fileData | ConvertTo-Json | Out-File -FilePath $jsonFile
Write-Host "File sizes saved to $jsonFile"

AI生成的源代码示例可在GitLab Duo Prompts项目的powershell目录中找到。

Python代码生成提示

使用Flask创建一个Web服务器来通过REST API管理用户,并将它们存储在SQLite中。

# Create a Flask webserver

# Add REST API entrypoints to manage users by ID

# Implement create, update, delete functions

# User data needs to be stored in SQlite, create table if not exists

# Run the server on port 8080, support TLS

# Print required packages for requirements.txt in a comment.

# Use Python 3.10 as default

# Potential AI-generated code below
import flask
from flask import request
import sqlite3

app = flask.Flask(__name__)

# Create SQLite database and users table if not exists
conn = sqlite3.connect('users.db')
conn.execute('''CREATE TABLE IF NOT EXISTS users
         (id INTEGER PRIMARY KEY, name TEXT, email TEXT)''')

@app.route('/users', methods=['POST'])
def create_user():
  # Get user data from request
  name = request.form['name']
  email = request.form['email']

  # Insert user into database
  conn.execute('INSERT INTO users (name, email) VALUES (?, ?)', (name, email))

  return 'User created successfully'

@app.route('/users/<int:id>', methods=['PUT'])
def update_user(id):
  # Get user data from request
  name = request.form['name']
  email = request.form['email']

  # Update user in database
  conn.execute('UPDATE users SET name = ?, email = ? WHERE id = ?', (name, email, id))

  return 'User updated successfully'

@app.route('/users/<int:id>', methods=['DELETE'])
def delete_user(id):
  # Delete user from database
  conn.execute('DELETE FROM users WHERE id = ?', (id,))

  return 'User deleted successfully'

if __name__ == '__main__':
  # Required packages - flask, sqlite3
  app.run(host='0.0.0.0', port=8080, ssl_context='adhoc')

AI生成的源代码示例可在GitLab Duo Prompts项目的python目录中找到。

Ruby代码生成提示

创建一个日志解析应用程序,将日志数据存储到Elasticsearch中。

# Create a Ruby app as log parser

# Provide hooks to replace sensitive strings in log lines

# Format the logs and store them in Elasticsearch

# Potential AI-generated code below
require 'logger'
require 'elasticsearch'

class LogParser
  attr_reader :logger

  def initialize
    @logger = Logger.new(STDOUT)
    @elasticsearch = Elasticsearch::Client.new
  end

  def parse_and_store(logs)
    sanitized_logs = sanitize_logs(logs)
    formatted_logs = format_logs(sanitized_logs)
    store_in_elasticsearch(formatted_logs)
  end

  private

  def sanitize_logs(logs)
    logs.map { |line| sanitize_line(line) }
  end

  def sanitize_line(line)
    # replace sensitive data
    line.gsub(/\d{16}/, '[REDACTED]')
  end

  def format_logs(logs)
    logs.map { |line| "#{Time.now}: #{line}" }
  end

  def store_in_elasticsearch(logs)
    logs.each { |log| @elasticsearch.index(index: 'app-logs', document: log) }
  end
end

创建一个支持syslog格式的日志客户端工具类,包含严重性级别、应用程序名称和消息字符串。

# Create Logging utility class

# Define default log level as attribute

# Add method for logging, inputs: level, app, message

# Print the data with formatted date and time in syslog format

# Potential AI-generated code below
class Logging
  attr_accessor :log_level

  def log(level, app, message)
    time = Time.now.strftime("%b %d %H:%M:%S")
    puts "#{time} #{app}[#{Process.pid}]: #{level} - #{message}"
  end
end

# Instantiate class and test the log method

# Potential AI-generated code below
logger = Logging.new
logger.log_level = :debug

logger.log(:info, 'MyApp', 'Application started - info')
logger.log(:debug, 'MyApp', 'Application started - debug')
logger.log(:error, 'MyApp', 'Application started - error')
logger.log(:fatal, 'MyApp', 'Application started - fatal')
logger.log(:warn, 'MyApp', 'Application started - warn')

AI生成的源代码示例可在GitLab Duo Prompts项目的ruby目录中找到。

Rust代码生成提示

// 查询GitLab REST API
// 获取gitlab-org/gitlab的所有开放合并请求

use serde_json::Value;

fn main() {

    let client = reqwest::blocking::Client::new();
    let url = "https://gitlab.com/api/v4/projects/278964/merge_requests?state=opened";
    let response = client.get(url).send().unwrap().text().unwrap();
    let json: Value = serde_json::from_str(&response).unwrap();

    // 待办事项:分页,默认获取结果数:20
    // 读取响应头以访问下一页

    println!("{}", json.to_string());

    for mr in json.as_array().unwrap() {
        println!("{} - URL: {}", mr["title"], mr["web_url"]);
    }
}

创建一个RSS源阅读器应用,示例来自博客文章通过AI的帮助学习高级Rust编程

    // 创建一个函数,遍历源数组
    // 并使用HTTP从RSS源项中获取数据。
    // 将结果存储在新的哈希映射中。
    // 在终端打印哈希映射。

AI生成的源代码示例可在GitLab Duo Prompts项目的rust目录中找到。

Scala代码生成提示

// 实现牛顿法
// 创建一个带有main函数的对象
// 添加实现牛顿法的函数用于求解方程
// 添加驱动函数来测试已实现的函数
object NewtonsMethod {
  def solveEquation(f: Double => Double, df: Double => Double, x0: Double, tolerance: Double): Double = {
    var x = x0
    var error = Double.PositiveInfinity
    while (math.abs(error) > tolerance) {
      error = f(x) / df(x)
      x -= error
    }
    x
  }

  def main(args: Array[String]): Unit = {
    val f: Double => Double = x => x * x - 4
    val df: Double => Double = x => 2 * x
    val x0 = 3.0
    val tolerance = 1e-6
    val root = solveEquation(f, df, x0, tolerance)
    println(s"The root is: $root")
  }
}

AI生成的源代码示例可在GitLab Duo Prompts项目的scala目录中找到。

Shell脚本代码生成提示

创建一个名为mytop.sh的脚本,显示按CPU、内存和磁盘I/O使用率排序的前10个进程。 从第一个代码注释开始,让Code Suggestions生成其余内容。

#!/bin/bash

# 获取按CPU使用率排序的前10个进程
top -b -n 1 | head -n 11 | awk '{print $1, $2, $3, $9}' | column -t

# 获取按内存使用率排序的前10个进程
top -b -n 1 | head -n 11 | awk '{print $1, $2, $4, $6}' | column -t

# 获取按磁盘I/O使用率排序的前10个进程
top -b -n 1 | head -n 11 | awk '{print $1, $2, $7, $8}' | column -t

# 获取按网络I/O使用率排序的前10个进程
top -b -n 1 | head -n 11 | awk '{print $1, $2, $10, $11}' | column -t

AI生成的源代码示例可在GitLab Duo Prompts项目的shell目录中找到。

TypeScript代码生成提示

创建一个用于解析IPv6和IPv4地址格式的工具函数。

"use strict";
// 生成一个解析IPv6和IPv4地址格式的TypeScript函数
// 使用正则表达式
function parseAddress(address) {
    const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
    const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    if (ipv6Regex.test(address)) {
        return {
            ipVersion: 6,
            address
        };
    }
    else if (ipv4Regex.test(address)) {
        return {
            ipVersion: 4,
            address
        };
    }
    else {
        throw new Error('Invalid IP address');
    }
}
// 用随机输入测试该函数
const testInputs = [
    '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
    '192.168.0.1',
    'not-an-ip'
];
for (const input of testInputs) {
    try {
        const result = parseAddress(input);
        console.log(result);
    }
    catch (error) {
        console.error(`Invalid address: ${input}`);
    }
}

AI生成的源码示例可在GitLab Duo Prompts项目中的typescript目录中找到。

资源

许多用例都有对应的实操录像,可在GitLab Duo咖啡聊天YouTube播放列表中查看。

博客资源

以下博客文章提供了这些用例的教程:

代码建议教程博客文章适用于以下语言: