Code maken uit natuurlijke taal

Voltooid

Een van de mogelijkheden van Azure OpenAI-modellen is het genereren van code op basis van prompts in natuurlijke taal. Taken kunnen variëren van een eenvoudige één regelopdracht tot een volledige toepassing. De AI-modellen kunnen ook verstrekte code of eerdere antwoorden bewerken en bijwerken om de aangevraagde taak te voltooien.

De voorbeelden in deze les gebruiken gpt-35-turbo.

Schrijffuncties

Azure OpenAI-modellen kunnen functies en apps in verschillende talen maken door alleen maar te beschrijven wat u wilt. Als u bijvoorbeeld de prompt write a function for binary search in pythonkrijgt, ontvangt u waarschijnlijk een antwoord met de functie en een uitleg van de code.

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.

De aanvraag kan verder gaan dan functies en een reeks functies of een hele app aanvragen. Het antwoord biedt een goed beginpunt voor de taak die u probeert te bereiken.

Codetaal wijzigen

Als u code in één taal hebt, maar deze in een andere taal nodig hebt, kan Azure OpenAI dat voor u vertalen. Stel dat u deze print_squares functie hebt in Python.

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

Als u die code opgeeft, samen met de prompt convert this code to C#, krijgt u waarschijnlijk iets vergelijkbaars met de volgende functie.

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

U ziet dat het model de verschillen begrijpt tussen de manier waarop for lussen en functies worden gedefinieerd in de verschillende talen (inclusief toegangsmodifiers in C#) en de code op de juiste manier hebt gewijzigd.

Onbekende code begrijpen

Azure OpenAI-modellen zijn handig voor het begrijpen van code die niet zinvol is, of in een taal die u niet kent. Stel dat u de volgende functie hebt gekregen (in een fictieve coderingstaal!) en u niet wist hoe u deze moet begrijpen.

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));
    }
}

Wanneer u aan het model wordt verstrekt, samen met de prompt could you explain what this code is doing?, krijgt u een antwoord dat er ongeveer als volgt uitziet:

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.

Door de uitleg en vertaling te combineren in een taal waarmee u bekend bent, is deze functionaliteit nog nuttiger.

Code voltooien en het ontwikkelingsproces ondersteunen

Azure OpenAI kan ontwikkelaars helpen bij algemene softwareontwikkelingstaken, zoals het schrijven van eenheidstests, het voltooien van gedeeltelijke code, het toevoegen van commentaarcode en het genereren van documentatie. Door AI-hulp te gebruiken, kunnen ontwikkelaars meer tijd besteden aan complexe programmeer- en probleemoplossingstaken.

Azure OpenAI-modellen kunnen code genereren op basis van opmerkingen, functienamen en gedeeltelijk geschreven code. Hoe meer context u het model kunt bieden, hoe nauwkeuriger het antwoord waarschijnlijk is.

Wanneer u bijvoorbeeld de volgende prompt krijgt:

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

Het model neemt de opmerkingen en het begin van de functiedefinitie en voltooit het vanuit de context die het heeft.

Vergelijkbare functionaliteit kan worden gezien door gedeeltelijke code aan het model te verstrekken, zonder opmerkingen. Neem bijvoorbeeld de volgende prompt.

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

Het AI-model doet het beste om de functie te voltooien met de meest waarschijnlijke voltooiing van de functie.

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);  
    }  
}

Het antwoord bevat waarschijnlijk ook een uitleg in natuurlijke taal van wat die functie doet. In dit geval reageerde het met een recursieve implementatie van de factoriële functie.

Eenheidstests schrijven

Azure OpenAI-modellen kunnen eenheidstests genereren voor functies die u schrijft om uw code robuuster te maken. Neem bijvoorbeeld de binaire zoekfunctie.

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;
}

Geef deze functie op samen met de prompt write three unit tests for this functionen u krijgt een antwoord dat lijkt op het volgende.

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);  
}  

Deze functionaliteit is nog nuttiger als u de aanvragen opgeeft die u wilt opnemen in uw prompt, waardoor u minder tijd nodig hebt om eenheidstests voor uw code te schrijven.

Opmerkingen toevoegen en documentatie genereren

Om uw code verder te verbeteren, kunnen AI-modellen opmerkingen en documentatie voor u toevoegen. Neem de volgende functie als voorbeeld. Dit kan een beetje moeilijk te begrijpen zijn wanneer u deze voor het eerst leest zonder codeopmerkingen.

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;  
    }  
}  

Geef die functie op voor het model, samen met een prompt waarin wordt gevraagd om opmerkingen toe te voegen aan de code en u krijgt een antwoord dat lijkt op het volgende.

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;  
    }  
}  

Als u nog een stap verder gaat en documentatie aanvraagt, voegt OpenAI een beschrijving toe, inclusief invoer en uitvoer.

Fouten oplossen en uw code verbeteren

Ontwikkelaars kunnen soms code schrijven die voornamelijk werkt, maar kunnen worden verbeterd door fouten, syntaxis, prestaties of modulariteit op te lossen. Azure OpenAI-modellen kunnen helpen bij het identificeren van manieren om betere code te verbeteren en suggesties te geven.

Fouten in uw code oplossen

Azure OpenAI-modellen kunnen helpen bij het oplossen van fouten in code door de code te analyseren en wijzigingen voor te stellen die het probleem mogelijk kunnen oplossen. Dit kan ontwikkelaars helpen fouten sneller en efficiënter te identificeren en op te lossen.

Stel dat u de volgende functie hebt die niet voor u werkt.

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;
}

Geef deze functie op voor het model, samen met de prompt Fix the bugs in this function, en u krijgt een antwoord met de vaste code en een uitleg van wat er is opgelost.

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.

De prestaties verbeteren

Hoewel codeontwikkelaars mogelijk werken, is er mogelijk een efficiëntere manier om de taak uit te voeren. Hier volgt een voorbeeld van een functie waarmee de som van de eerste n positieve gehele getallen wordt berekend, mogelijk niet efficiënt:

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;  
}  

Deze versie werkt correct, maar de tijdcomplexiteit is O(n). Wanneer dit is opgegeven aan het model, is dit het antwoord:

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;  
}  

Deze versie retourneert nog steeds het juiste resultaat, maar de tijdcomplexiteit is nu O(1), waardoor het veel efficiënter wordt.

Inefficiënte code herstructureren

Betere code is minder gevoelig voor bugs en is eenvoudiger te onderhouden en de Azure OpenAI-modellen kunnen ontwikkelaars helpen bij het herstructureren van hun code.

Houd rekening met de volgende functie.

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;
    }
}

Met deze code wordt de totale prijs van een bepaald item berekend op basis van de naam en hoeveelheid. De code is echter niet modulair en kan moeilijk te onderhouden zijn. Wanneer het aan het model is verstrekt met de aanvraag om het te herstructureren, is dit het antwoord:

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;  
}  

Samen met de code biedt het model een uitleg van de herstructurering.

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.