Construa código a partir de linguagem natural

Concluído

Um dos recursos dos modelos OpenAI do Azure é gerar código a partir de prompts de linguagem natural. As tarefas podem variar de um simples comando de uma linha a um aplicativo completo. Os modelos de IA também podem editar e atualizar o código fornecido ou respostas anteriores para concluir a tarefa solicitada.

Os exemplos nesta unidade estão usando gpt-35-turbo.

Funções de escrita

Os modelos OpenAI do Azure podem criar funções e aplicativos em vários idiomas apenas descrevendo o que você deseja. Por exemplo, dado o prompt write a function for binary search in python, você provavelmente receberá uma resposta com a função e uma explicação do código.

Sure, here's an example implementation of binary search algorithm in Python:

def binary_search(array, target):  
    low = 0  
    high = len(array) - 1  
  
    while low <= high:  
        mid = (low + high) // 2  
        if array[mid] == target:  
            return mid  
        elif array[mid] < target:  
            low = mid + 1  
        else:  
            high = mid - 1  
  
    return -1  
 
This function takes in two arguments - an array of integers and a target integer that we want to search
for in the array. The function initializes two pointers - low and high - to the first and last indices
of the array, respectively.

Inside the while loop, the function calculates the middle index using integer division (//). If the 
middle element is equal to the target, the function returns the index of the middle element. If the 
middle element is less than the target, we update the low pointer to mid + 1. Otherwise, we update the 
high pointer to mid - 1. We continue these steps until we find the target or the pointers cross each 
other (i.e., low > high).

If the target is not found in the array, the function returns -1.

Note that the binary search algorithm assumes that the input array is sorted in ascending order. If 
the array is not sorted, the algorithm may not return the correct result.

A solicitação pode ir além das funções e solicitar uma série de funções ou um aplicativo inteiro. A resposta fornece um bom ponto de partida para a tarefa que você está tentando alcançar.

Alterar linguagem de codificação

Se você tiver código em um idioma, mas precisar dele em outro, o Azure OpenAI pode traduzir isso para você. Por exemplo, digamos que você tenha essa print_squares função em Python.

def print_squares(n):  
    for i in range(1, n+1):  
        print(i**2)   

Se você fornecer esse código, juntamente com o prompt convert this code to C#, você provavelmente obterá algo semelhante à seguinte função.

public void PrintSquares(int n)  
{  
    for (int i = 1; i <= n; i++)  
    {  
        Console.WriteLine(i * i);  
    }  
}  

Observe que o modelo entendeu as diferenças entre como for loops e funções são definidos nas diferentes linguagens (incluindo modificadores de acesso em C#) e alterou o código apropriadamente.

Compreender código desconhecido

Os modelos do Azure OpenAI são úteis para entender o código que não faz sentido ou pode estar em uma linguagem com a qual você não está familiarizado. Por exemplo, digamos que você recebeu a seguinte função (em uma linguagem de codificação fictícia!) e não soube como entendê-la.

fn qzplv(n: i32, m: i32) -> i32 {
    if n == 0 {
        return m + 1;
    } else if m == 0 {
        return qzplv(n - 1, 1);
    } else {
        return qzplv(n - 1, qzplv(n, m - 1));
    }
}

Quando fornecido ao modelo, juntamente com o prompt could you explain what this code is doing?, você obtém uma resposta semelhante à seguinte:

Sure, I'd be happy to explain what this code is doing!

This code is implementing the Ackermann function, which is a well-known mathematical function that 
grows very quickly in terms of computation time as its inputs increase. The function takes two integer 
arguments (n and m) and returns another integer.

Here's how the function works:
- If n is equal to 0, the function returns m + 1.
- If m is equal to 0, the function calls itself recursively with n - 1 and 1 as arguments.
- Otherwise, the function calls itself recursively with n - 1 and the result of calling itself with n 
and m - 1 as arguments.

The function is implemented in a way that is easy to understand and follow, but it has a very high 
computational complexity. In fact, it grows so quickly that it can't be computed for values of n and m 
greater than about 4 or 5.

Combinar a explicação e a tradução para um idioma com o qual você está familiarizado torna essa funcionalidade ainda mais útil.

Completar o código e auxiliar o processo de desenvolvimento

O Azure OpenAI pode ajudar os desenvolvedores em tarefas comuns de desenvolvimento de software, como escrever testes de unidade, concluir código parcial, comentar código e gerar documentação. O uso da assistência de IA pode permitir que os desenvolvedores gastem mais tempo em tarefas complexas de programação e resolução de problemas.

Os modelos OpenAI do Azure são capazes de gerar código com base em comentários, nomes de funções e código parcialmente escrito. Quanto mais contexto você puder fornecer ao modelo, mais precisa será a resposta.

Por exemplo, quando dado o seguinte prompt:

complete the following function  
"""  
# calculate the average of the numbers in an array, but only if they're even  
def 

O modelo pega os comentários e o início da definição da função e a completa a partir de qualquer contexto que tenha.

Funcionalidade semelhante pode ser vista fornecendo código parcial para o modelo, sem quaisquer comentários. Pegue o seguinte prompt, por exemplo.

complete the following code  
"""  
def func1(n)
  if n==0:
complete the following code  
"""  
public int Func1(int n) {  
    if (n == 0) { 

O modelo de IA faz o seu melhor para completar a função com a conclusão mais provável da função.

def func1(n):  
    if n == 0:  
        return 1  
    else:  
        return n * func1(n-1)  
public int Func1(int n) {  
    if (n == 0) {  
        return 1;  
    } else {  
        return n * Func1(n-1);  
    }  
}

A resposta provavelmente também inclui uma explicação em linguagem natural do que essa função está fazendo. Neste caso, respondeu com uma implementação recursiva da função fatorial.

Escrever testes de unidade

Os modelos OpenAI do Azure podem gerar testes de unidade para funções que você escreve para ajudar a tornar seu código mais robusto. Tomemos como exemplo a função de pesquisa binária.

def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1
public static int BinarySearch(int[] arr, int target)
{
    int left = 0;
    int right = arr.Length - 1;

    while (left <= right)
    {
        int mid = (left + right) / 2;

        if (arr[mid] == target)
        {
            return mid;
        }
        else if (arr[mid] < target)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }

    return -1;
}

Forneça essa função junto com o prompt write three unit tests for this functione você obterá uma resposta semelhante à seguinte.

def test_binary_search():  
    # Test case 1: Target element is in the middle of the array  
    arr1 = [1, 2, 3, 4, 5, 6]  
    target1 = 4  
    assert binary_search(arr1, target1) == 3  

    # Test case 2: Target element is at the beginning of the array  
    arr2 = [1, 2, 3, 4, 5, 6]  
    target2 = 1  
    assert binary_search(arr2, target2) == 0  

    # Test case 3: Target element is not in the array  
    arr3 = [1, 2, 3, 4, 5, 6]  
    target3 = 7  
    assert binary_search(arr3, target3) == -1
[Test]  
public void TestBinarySearch1()  
{  
    int[] arr = { 1, 2, 3, 4, 5 };  
    int target = 3;  
    int expected = 2;  
    int result = BinarySearch(arr, target);  
    Assert.AreEqual(expected, result);  
}  

[Test]  
public void TestBinarySearch2()  
{  
    int[] arr = { 10, 20, 30, 40, 50 };  
    int target = 35;  
    int expected = -1;  
    int result = BinarySearch(arr, target);  
    Assert.AreEqual(expected, result);  
}  

[Test]  
public void TestBinarySearch3()  
{  
    int[] arr = { 3, 6, 9, 12, 15 };  
    int target = 6;  
    int expected = 1;  
    int result = BinarySearch(arr, target);  
    Assert.AreEqual(expected, result);  
}  

Essa funcionalidade é ainda mais útil se você especificar os casos que deseja incluir no prompt, o que reduz o tempo necessário para escrever testes de unidade para seu código.

Adicionar comentários e gerar documentação

Para melhorar ainda mais seu código, os modelos de IA podem adicionar comentários e documentação para você. Tome a seguinte função como exemplo, que pode ser um pouco difícil de entender ao lê-la pela primeira vez sem comentários de código.

def permutations(lst):  
    if len(lst) == 0:  
        return []  
    elif len(lst) == 1:  
        return [lst]  
    else:  
        result = []  
        for i in range(len(lst)):  
            temp = lst[i]  
            remaining = lst[:i] + lst[i+1:]  
            for p in permutations(remaining):  
                result.append([temp] + p)  
        return result  
public static List<List<int>> Permutations(List<int> lst)  
{  
    if (lst.Count == 0)  
    {  
        return new List<List<int>>();  
    }  
    else if (lst.Count == 1)  
    {  
        return new List<List<int>> { lst };  
    }  
    else  
    {  
        List<List<int>> result = new List<List<int>>();  
        for (int i = 0; i < lst.Count; i++)  
        {  
            int temp = lst[i];  
            List<int> remaining = new List<int>(lst);  
            remaining.RemoveAt(i);  
            foreach (List<int> p in Permutations(remaining))  
            {  
                List<int> permutation = new List<int> { temp };  
                permutation.AddRange(p);  
                result.Add(permutation);  
            }  
        }  
        return result;  
    }  
}  

Forneça essa função ao modelo, juntamente com um prompt solicitando que ele adicione comentários ao código, e você obterá uma resposta semelhante à seguinte.

def permutations(lst):  
    # Check if the input list is empty  
    if len(lst) == 0:  
        return []  
    # Check if the input list has only one element  
    elif len(lst) == 1:  
        return [lst]  
    else:  
        # Initialize an empty list to store permutations  
        result = []  
        # Iterate through each element of the input list  
        for i in range(len(lst)):  
            # Remove the current element from the list and store it in a variable  
            temp = lst[i]  
            remaining = lst[:i] + lst[i+1:]  
            # Recursively call the function on the remaining list  
            for p in permutations(remaining):  
                # Append the current element to the beginning of each permutation and add it to the result list  
                result.append([temp] + p)  
        # Return the final list of permutations  
        return result  
public static List<List<int>> Permutations(List<int> lst)  
{  
    // Check if the input list is empty  
    if (lst.Count == 0)  
    {  
        return new List<List<int>>();  
    }  
    // Check if the input list has only one element  
    else if (lst.Count == 1)  
    {  
        return new List<List<int>> { lst };  
    }  
    else  
    {  
        // Initialize an empty list to store permutations  
        List<List<int>> result = new List<List<int>>();  
        // Iterate through each element of the input list  
        for (int i = 0; i < lst.Count; i++)  
        {  
            // Remove the current element from the list and store it in a variable  
            int temp = lst[i];  
            List<int> remaining = new List<int>(lst);  
            remaining.RemoveAt(i);  
            // Recursively call the function on the remaining list  
            foreach (List<int> p in Permutations(remaining))  
            {  
                // Append the current element to the beginning of each permutation and add it to the result list  
                List<int> permutation = new List<int> { temp };  
                permutation.AddRange(p);  
                result.Add(permutation);  
            }  
        }  
        // Return the final list of permutations  
        return result;  
    }  
}  

Se você der um passo adiante e solicitar documentação, a OpenAI adicionará uma descrição incluindo entradas e saídas.

Corrija bugs e melhore o seu código

Às vezes, os desenvolvedores podem escrever código que funciona na maioria das vezes, mas pode ser melhorado corrigindo bugs, sintaxe, desempenho ou modularidade. Os modelos OpenAI do Azure podem ajudar a identificar maneiras de melhorar e fornecer sugestões sobre como escrever um código melhor.

Corrigir bugs no seu código

Os modelos OpenAI do Azure podem ajudar a corrigir bugs no código analisando o código e sugerindo alterações que podem potencialmente corrigir o problema. Isso pode ajudar os desenvolvedores a identificar e resolver bugs de forma mais rápida e eficiente.

Por exemplo, digamos que você tenha a seguinte função que não está funcionando para você.

def calculate_average(numbers):  
    total = 0  
    for i in range(len(numbers)):  
        number = numbers[i]  
        total += number  
    average = total  
    rerun averave  
public double CalculateAverage(int[] numbers)
{
    int total = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
        int number = numbers[i];
        total += number;
    }
    double average = (double)total;
    rerun averave;
}

Forneça essa função para o modelo, juntamente com o prompt Fix the bugs in this function, e você obtém uma resposta com o código fixo e uma explicação do que foi corrigido.

def calculate_average(numbers):  
    total = 0  
    for i in range(len(numbers)):  
        number = numbers[i]  
        total += number  
    average = total / len(numbers)  
    return average  
public double CalculateAverage(int[] numbers)
{
    int total = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
        int number = numbers[i];
        total += number;
    }
    double average = (double)total / numbers.Length;
    return average;
}
There were a few issues with the original code:

1. The variable "average" was assigned the value of "total" instead of the actual average.
2. There was a typo in the last line - "rerun" should be "return".
3. The average was not actually calculated - the corrected code divides the total by the length of 
the "numbers" list to get the average.

Melhorar o desempenho

Embora os desenvolvedores de código escrevam possa funcionar, pode haver uma maneira mais eficiente de realizar a tarefa. Aqui está um exemplo de uma função que calcula a soma dos primeiros n inteiros positivos, possivelmente de forma ineficiente:

def sum_of_n(n):
    result = 0
    for i in range(1, n+1):
        result += i
    return result
public int SumOfN(int n)  
{  
    int result = 0;  
    for (int i = 1; i <= n; i++)  
    {  
        result += i;  
    }  
    return result;  
}  

Esta versão funciona corretamente, mas sua complexidade de tempo é O(n). Quando fornecido ao modelo, aqui está a resposta:

We can improve this function it by using a mathematical formula instead.

Here's the more efficient version:
def sum_of_n(n):
    return n * (n + 1) // 2
public int SumOfN(int n)  
{  
    return n * (n + 1) / 2;  
}  

Esta versão ainda retorna o resultado correto, mas sua complexidade de tempo agora é O(1), o que a torna muito mais eficiente.

Refatorar código ineficiente

Um código melhor é menos propenso a bugs e é mais fácil de manter, e os modelos OpenAI do Azure podem ajudar a orientar os desenvolvedores sobre como refatorar seu código.

Considere a seguinte função.

def calculateTotalPrice(item, quantity):
    if item == 'apple':
        return quantity * 0.5
    elif item == 'banana':
        return quantity * 0.75
    elif item == 'orange':
        return quantity * 0.6
    else:
        return 0
public double CalculateTotalPrice(string item, int quantity)
{
    if (item == "apple")
    {
        return quantity * 0.5;
    }
    else if (item == "banana")
    {
        return quantity * 0.75;
    }
    else if (item == "orange")
    {
        return quantity * 0.6;
    }
    else
    {
        return 0;
    }
}

Este código calcula o preço total de um determinado item com base no seu nome e quantidade. No entanto, o código não é modular e pode ser difícil de manter. Quando fornecido ao modelo com a solicitação para refatorá-lo, aqui está a resposta:

item_prices = {  
    'apple': 0.5,  
    'banana': 0.75,  
    'orange': 0.6  
}  

def calculate_total_price(item, quantity):  
    price = item_prices.get(item, 0)  
    return quantity * price  
static Dictionary<string, double> itemPrices = new Dictionary<string, double>()  
{  
    {"apple", 0.5},  
    {"banana", 0.75},  
    {"orange", 0.6}  
};  

static double CalculateTotalPrice(string item, int quantity)  
{  
    double price;  
    if (!itemPrices.TryGetValue(item, out price))  
    {  
        price = 0;  
    }  
    return quantity * price;  
}  

Junto com o código, o modelo fornece uma explicação da refatoração.

In this refactored code, we've created an object called itemPrices that maps item names to their 
prices. We've also simplified the calculateTotalPrice function by using the itemPrices object to look 
up the price of the item, rather than using a series of if/else statements. This makes the code more 
modular and easier to maintain, and also reduces the risk of introducing bugs in the future.