Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.537 Beiträge
 
Delphi 11 Alexandria
 
#138

AW: Programme bzw. Funktionen von KI schreiben lassen (OpenAI)

  Alt 4. Okt 2023, 01:32
Jetzt, nach einem halben Jahr, muss ich hier noch mal einen ergänzenden Post los werden.

Ich bin echt geflasht, wie sich die Fähigkeiten von ChatGPT entwickelt haben. Ich möchte das mal an einem Beispiel demonstrieren.

Bin gerade dabei ein Text-Verarbeitungsprogramm, dass ich mal vor 30 Jahren für DOS geschrieben habe, in die moderne Windows-Welt (Cross-Plattform) für FMX zu transformieren. Mal abgesehen, dass mir ChatGPT eine Menge zu dem alten DOS-Kram und Turbo-Pascal helfen konnte (dazu mache ich mal ein eigenes Video), ich nutze ChatGPT seit einiger Zeit recht häufig, als besseren Such-Ersatz für Google. Und das ist echt 1000 mal besser.

Aber hin und wieder lasse ich mir auch mal ein paar Code-Schnipsel erstellen. Ich bin echt beeindruckt, das die KI inzwischen an komplexen Beschreibungen versteht und dann auch einen (immer häufiger) sofort funktionierenden Code zurück liefert.

Bei dem folgenden code hat es auf Anhieb funktioniert:

Meine Frage lautete:

Kontext: Delphi, FMX. Ich habe einen Text ( ein Inhaltsverzeichnis), da steht am Anfang jeder Zeile eine Gliederungsnummer (z.B. "1.1.") und am Ende der Zeile (zuvor ein Leerzeichen) die Seitenzahl. Kannst Du mir eine Routine schreiben, die diesen Text in ein TTreeview einliest und dabei die Gliederungsebene in den entsprechenden Levels abbildet? Der Text sieht so aus:

1. Einleitung ......................... 1
1.1. Ein Wort über dieses Handbuch ...... 2
1.2. System-Voraussetzungen ............. 3
1.3. Die Dateien auf der Originaldiskette 3
1.4. Die Installation des Programmes .... 4
1.5. Start des Programmes ............... 5
2. Die Menüs von SKRIPT ............... 9
2.1. Das Menü "Text" .................... 9
2.1.1. Der Befehl "Holen" ................. 9
2.1.2. Der Befehl "Sichern" ............... 11
2.1.3. Der Befehl "Als ... Sichern" ....... 12
2.1.4. Der Befehl "Neuanlage" ............. 12
2.1.5. Der Befehl "Dateiname" ............. 12

Die Antwort (die Erläuterungen habe ich mal wegelassen):

Delphi-Quellcode:
procedure TextToTreeView(const Text: string; TreeView: TTreeView);
var
  Lines: TStringList;
  I: Integer;
  LastItem: array of TTreeViewItem;
  Level, CurLevel: Integer;
  Line, Num, S: string;
  P: Integer;
begin
  Lines := TStringList.Create;
  try
    Lines.Text := Text;
    SetLength(LastItem, 10); // Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
    for I := 0 to Lines.Count - 1 do
    begin
      Line := Lines[I];
      P := Pos('.', Line);
      if P > 0 then
      begin
        // Nummer extrahieren
        Num := Copy(Line, 1, P-1);
        Delete(Line, 1, P);
        Level := 1;
        while (Length(Line) > 1) and (Line[2] = '.') do
        begin
          Delete(Line, 1, 2);
          Inc(Level);
        end;
        // Text extrahieren (ohne führende und endende Leerzeichen)
        S := Trim(Line);

        // Item hinzufügen
        if Level = 1 then
        begin
          LastItem[0] := TTreeViewItem.Create(TreeView);
          LastItem[0].Parent := TreeView;
          LastItem[0].Text := S;
        end
        else if Level <= Length(LastItem) then
        begin
          CurLevel := Level - 1;
          LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
          LastItem[CurLevel].Parent := LastItem[CurLevel-1];
          LastItem[CurLevel].Text := S;
        end;
      end;
    end;
  finally
    Lines.Free;
  end;
end;
Kompiliert im Programm sieht das Ergebnis dann wie in Bild 1 in der Anlage aus.

Nun gefielen mir aber nicht die Punkte und die Seitenzahlen am Ende (sind eher nebensache), aber ich brauch die Seitenzahl auch irgendwo gespeichert, damit ich beim Klick auf einen Eintrag an die entsprechende Stelle im Text springen kann.

Meine Ergänzende Bitte lautete also:

Das funktioniert super! Kannst Du die Funktion noch so abändern, dass der Wert der Seitenzahl in den jeweiligen TTreeviewItems in den Tag-Wert gespeichert wird und die Punkte und die Seitenzahlen aus dem Text entfernt werden?


Die neue Funktion und das Ergebnis im Programm einkompiliert in Bildanlage 2:

Delphi-Quellcode:
procedure TextToTreeView(const Text: string; TreeView: TTreeView);
var
  Lines: TStringList;
  I: Integer;
  LastItem: array of TTreeViewItem;
  Level, CurLevel: Integer;
  Line, Num, S: string;
  P, PPage: Integer;
  PageNum: Integer;
begin
  Lines := TStringList.Create;
  try
    Lines.Text := Text;
    SetLength(LastItem, 10); // Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
    for I := 0 to Lines.Count - 1 do
    begin
      Line := Lines[I];
      P := Pos('.', Line);
      if P > 0 then
      begin
        // Nummer extrahieren
        Num := Copy(Line, 1, P-1);
        Delete(Line, 1, P);
        Level := 1;
        while (Length(Line) > 1) and (Line[2] = '.') do
        begin
          Delete(Line, 1, 2);
          Inc(Level);
        end;
        
        // Seitenzahl extrahieren
        PPage := Length(Line);
        while (PPage > 0) and (Line[PPage] >= '0') and (Line[PPage] <= '9') do
          Dec(PPage);
        // Falls eine Seitenzahl gefunden wurde, extrahiere und lösche sie aus Line
        if PPage < Length(Line) then
        begin
          PageNum := StrToInt(Trim(Copy(Line, PPage+1, MaxInt)));
          SetLength(Line, PPage); // Schneidet den String ab, um die Seitenzahl zu entfernen
        end
        else
          PageNum := -1; // oder wie Sie nicht zugewiesene Werte darstellen möchten

        // Text extrahieren (ohne führende und endende Leerzeichen)
        S := Trim(Line);
        // Punkte aus dem Text entfernen
        S := StringReplace(S, '.', '', [rfReplaceAll]);
        
        // Item hinzufügen
        if Level = 1 then
        begin
          LastItem[0] := TTreeViewItem.Create(TreeView);
          LastItem[0].Parent := TreeView;
          LastItem[0].Text := S;
          LastItem[0].Tag := PageNum;
        end
        else if Level <= Length(LastItem) then
        begin
          CurLevel := Level - 1;
          LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
          LastItem[CurLevel].Parent := LastItem[CurLevel-1];
          LastItem[CurLevel].Text := S;
          LastItem[CurLevel].Tag := PageNum;
        end;
      end;
    end;
  finally
    Lines.Free;
  end;
end;
Bei dieser Variante fehlten aber die Punkte am Anfang und hier wurden teilweise - unpassender Weise - Zahlen wieder gegeben.
Auch mit zwei weiteren Nachfragen hat ChatGPT das aber nicht hinbekommen, so dass ich es selber angepasst habe (siehe Erläuternungen mit // HS:

Delphi-Quellcode:
procedure TextToTreeView(const Text: string; TreeView: TTreeView);
var
  Lines: TStringList;
  I: Integer;
  LastItem: array of TTreeViewItem;
  Level, CurLevel: Integer;
  Line, Num, S: string;
  P, PPage: Integer;
  PageNum: Integer;
begin
  Lines := TStringList.Create;
  try
    Lines.Text := Text;
    SetLength(LastItem, 10); // Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
    for I := 0 to Lines.Count - 1 do
    begin
      Line := Lines[I];
      P := Pos('.', Line);
      if P > 0 then
      begin
        // Nummer extrahieren

        var oldLine:= Line; // HS: Punkte werden noch gebraucht, also merken

        Num := Copy(Line, 1, P-1);
        Delete(Line, 1, P);
        Level := 1;

        while (Length(Line) > 1) and (Line[2] = '.') do
        begin
          Delete(Line, 1, 2);
          Inc(Level);
        end;

        Line := OldLine; // HS: Die alte Line wiederherstellen

        // Seitenzahl extrahieren
        PPage := Length(Line);
        while (PPage > 0) and (Line[PPage] >= '0') and (Line[PPage] <= '9') do
          Dec(PPage);
        // Falls eine Seitenzahl gefunden wurde, extrahiere und lösche sie aus Line
        if PPage < Length(Line) then
        begin
          PageNum := StrToInt(Trim(Copy(Line, PPage+1, MaxInt)));
          SetLength(Line, PPage); // Schneidet den String ab, um die Seitenzahl zu entfernen
        end
        else
          PageNum := -1; // oder wie Sie nicht zugewiesene Werte darstellen möchten

        // Text extrahieren (ohne führende und endende Leerzeichen)
        S := Trim(Line);
        // Punkte aus dem Text entfernen

        var ALeftPart := Copy (S, 1, Pos (' ', S)-1); // HS: Punkte vorne lassen
        var ARightPart := ' ' + Trim (Copy (S, Length (AleftPart)+1, Length (s))); // HS: Rechter Teil

        //S := StringReplace(S, '.', '', [rfReplaceAll]); // HS: Nicht alle Punkte entfernen
        ARightPart := StringReplace(ARightPart, '.', '', [rfReplaceAll]); // HS: Sondern nur im rechten Teile
        s := ALeftPart + ARightPart; // HS

        // Item hinzufügen
        if Level = 1 then
        begin
          LastItem[0] := TTreeViewItem.Create(TreeView);
          LastItem[0].Parent := TreeView;
          LastItem[0].Text := S;
          LastItem[0].Tag := PageNum;
        end
        else if Level <= Length(LastItem) then
        begin
          CurLevel := Level - 1;
          LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
          LastItem[CurLevel].Parent := LastItem[CurLevel-1];
          LastItem[CurLevel].Text := S;
          LastItem[CurLevel].Tag := PageNum;
        end;
      end;
    end;
  finally
    Lines.Free;
  end;
end;
Somit sieht es dann wie im dritten Bild dargestellt aus.
Also auch wenn der Code es nicht 100 Prozentig war, es hat mir eine Menge Zeit eingespart, die kleine Anpassung meinerseits hat nur 10 Minuten gedauert.

Also ich bin echt beindruckt....
Miniaturansicht angehängter Grafiken
result1.jpg   result2.jpg   result3.jpg  
  Mit Zitat antworten Zitat