Erstellen von Code aus natürlicher Sprache

Abgeschlossen

Eine der Funktionen von Azure OpenAI-Modellen besteht darin, Code aus Eingabeaufforderungen in natürlicher Sprache zu erstellen. Die Aufgaben können von einem einfachen einzeiligen Befehl bis hin zu einer vollständigen Anwendung reichen. Die KI-Modelle können auch bereitgestellten Code oder vorherige Antworten bearbeiten und aktualisieren, um die angeforderte Aufgabe abzuschließen.

Die Beispiele in dieser Lektion verwenden gpt-35-turbo.

Schreibfunktionen

Azure OpenAI-Modelle können Funktionen und Apps in mehreren Sprachen erstellen, indem Sie einfach beschreiben, was Sie möchten. Auf den Prompt write a function for binary search in python erhalten Sie z. B. wahrscheinlich eine Antwort mit der Funktion und einer Erklärung des Codes.

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.

Die Anforderung kann über Funktionen hinausgehen und mehrere Funktionen oder eine ganze App anfordern. Die Antwort bietet einen guten Ausgangspunkt für die Aufgabe, die Sie erledigen möchten.

Ändern der Programmiersprache

Wenn Sie über Code in einer Sprache verfügen, ihn aber in einer anderen benötigen, kann Azure OpenAI den Code für Sie übersetzen. Angenommen, Sie verfügen über diese print_squares-Funktion in Python.

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

Wenn Sie diesen Code zusammen mit der Eingabeaufforderung convert this code to C#angeben, erhalten Sie wahrscheinlich etwas Ähnliches wie die folgende Funktion.

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

Beachten Sie, dass das Modell die Unterschiede zwischen der Definition von for-Schleifen und Funktionen in den verschiedenen Sprachen (einschließlich Zugriffsmodifizierern in C#) verstanden und den Code entsprechend geändert hat.

Verstehen von unbekanntem Code

Azure OpenAI-Modelle sind hilfreich, um Code zu verstehen, der keinen Sinn ergibt oder in einer Sprache vorliegt, mit der Sie nicht vertraut sind. Angenommen, Sie erhielten die folgende Funktion (in einer fiktiven Programmiersprache!) und verstehen sie nicht.

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

Wenn Sie dem Modell die Eingabeaufforderung could you explain what this code is doing? bereitstellen, erhalten Sie eine Antwort ähnlich der folgenden:

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.

Die Kombination von Erklärung und Übersetzung in eine Sprache, mit der Sie vertraut sind, macht diese Funktionalität noch nützlicher.

Vervollständigen von Code und Unterstützen des Entwicklungsprozesses

Azure OpenAI kann Entwickler*innen bei gängigen Softwareentwicklungsaufgaben unterstützen, z. B. beim Schreiben von Komponententests, beim Vervollständigen von Codeteilen, beim Kommentieren von Code und beim Erstellen von Dokumentationen. Dank der KI-Unterstützung können Entwickler*innen mehr Zeit für komplexe Programmier- und Problemlösungsaufgaben aufwenden.

Azure OpenAI-Modelle sind in der Lage, Code basierend auf Kommentaren, Funktionsnamen und teilweise geschriebenem Code zu generieren. Je mehr Kontext Sie dem Modell zur Verfügung stellen können, desto genauer ist die Antwort wahrscheinlich.

Bei der folgenden Eingabeaufforderung geschieht beispielsweise Folgendes:

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

Das Modell übernimmt die Kommentare und den Anfang der Funktionsdefinition und vervollständigt sie aus dem Kontext heraus, den es hat.

Eine ähnliche Funktionalität kann durch die Bereitstellung von Teilcode für das Modell ohne Kommentare erreicht werden. Betrachten wir beispielsweise die folgende Eingabeaufforderung.

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

Das KI-Modell trägt sein Bestes dazu bei, die Funktion mit der wahrscheinlichsten Vervollständigung der Funktion zu ergänzen.

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

Die Antwort enthält wahrscheinlich auch eine Erklärung in natürlicher Sprache, was diese Funktion bewirkt. In diesem Fall reagierte sie mit einer rekursiven Implementierung der Fakultätsfunktion.

Schreiben von Komponententests

Azure OpenAI-Modelle können Komponententests für Funktionen generieren, die Sie schreiben, um Ihren Code robuster zu machen. Nehmen wir beispielsweise die binäre Suchfunktion.

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

Geben Sie diese Funktion zusammen mit der Eingabeaufforderung write three unit tests for this function ein, und Sie erhalten eine Antwort ähnlich der folgenden.

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

Diese Funktion ist noch nützlicher, wenn Sie die Fälle angeben, die Sie in Ihrer Eingabeaufforderung enthalten möchten, wodurch die Zeit reduziert wird, die zum Schreiben von Komponententests für Ihren Code benötigt wird.

Hinzufügen von Kommentaren und Erstellen von Dokumentation

Um Ihren Code weiter zu verbessern, können KI-Modelle Kommentare und Dokumentationen für Sie hinzufügen. Nehmen Sie die folgende Funktion als Beispiel, die beim ersten Lesen ohne Codekommentare etwas schwer zu verstehen sein kann.

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

Stellen Sie diese Funktion für das Modell bereit, zusammen mit einer Aufforderung, Kommentare zum Code hinzuzufügen, und Sie erhalten eine Antwort ähnlich der folgenden.

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

Wenn Sie noch einen Schritt weiter gehen und die Dokumentation anfordern, fügt OpenAI eine Beschreibung einschließlich Eingaben und Ausgaben hinzu.

Beheben von Fehlern und Verbessern des Codes

Entwickler*innen können manchmal Code schreiben, der größtenteils funktioniert, aber durch das Beheben von Fehlern, Syntax, Leistung oder Modularität verbessert werden kann. Azure OpenAI-Modelle können dabei helfen, Möglichkeiten zur Verbesserung zu identifizieren und Vorschläge zum Schreiben von besserem Code machen.

Beheben von Fehlern im Code

Azure OpenAI-Modelle können helfen, Fehler im Code zu beheben, indem sie den Code analysieren und Änderungen vorschlagen, die das Problem möglicherweise beheben können. Dies kann Entwickler*innen helfen, Fehler schneller und effizienter zu erkennen und zu beheben.

Angenommen, Sie verfügen über die folgende Funktion, die nicht wie gewünscht funktioniert.

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

Stellen Sie diese Funktion für das Modell zusammen mit der Eingabeaufforderung Fix the bugs in this function bereit, und Sie erhalten eine Antwort mit dem korrigierten Code und einer Erklärung, was korrigiert wurde.

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.

Verbessern der Leistung

Auch wenn der von den Entwickler*innen geschriebene Code funktioniert, gibt es vielleicht einen effizienteren Weg, um die Aufgabe zu bewältigen. Hier sehen Sie ein Beispiel für eine Funktion, die die Summe der ersten n positiven ganzen Zahlen berechnet, möglicherweise auf ineffiziente Weise:

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

Diese Version funktioniert ordnungsgemäß, aber ihre Zeitkomplexität ist O(n). Wenn sie für das Modell bereitgestellt wird, sehen Sie die folgende Antwort:

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

Diese Version gibt immer noch das richtige Ergebnis zurück, aber ihre Zeitkomplexität ist jetzt O(1), was sie wesentlich effizienter macht.

Umgestalten von ineffizientem Code

Besserer Code ist weniger anfällig für Fehler und einfacher zu verwalten, und die Azure OpenAI-Modelle können Entwickler*innen helfen, ihren Code umzugestalten.

Betrachten Sie die folgende Funktion.

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

Dieser Code errechnet den Gesamtpreis eines bestimmten Artikels auf Grundlage seines Namens und seiner Menge. Der Code ist jedoch nicht modular aufgebaut und kann schwer zu verwalten sein. Wenn sie für das Modell mit der Anforderung zum Umgestalten bereitgestellt wird, lautet die Antwort wie folgt:

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

Zusammen mit dem Code enthält das Modell eine Erläuterung des Refactorings.

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.