1 Punkte von GN⁺ 2024-08-04 | 1 Kommentare | Auf WhatsApp teilen
  • ell ist eine in Bash geschriebene Kommandozeilenoberfläche für LLMs, mit der sich LLMs direkt im Terminal befragen lassen, wobei auch der Terminal-Kontext mitgegeben werden kann
  • Es unterstützt Pipe-Eingaben, Dateieingaben und Standardeingaben und lässt sich damit zusammen mit bestehenden Unix-Tool-Workflows nutzen; im interaktiven Modus kann man unter Beibehaltung des Kontexts chatten
  • Über Templates werden Function Calling und anbieterspezifische Funktionen unterstützt; außerdem ist eine Funktion zum Entfernen sensibler Informationen enthalten
  • Für die Nutzung werden Bash 4.1 oder höher, coreutils oder OS-X-Dienstprogramme, jq und curl benötigt; bei Verwendung des Record Mode werden zusätzlich perl und der script-Befehl aus util-linux benötigt
  • Es werden Konfigurationsbeispiele für Google gemini-1.5-flash und OpenAI gpt-4o-mini bereitgestellt; hervorgehoben werden die nahezu reine Bash-Implementierung, das geringe Gewicht sowie die einfache Installation, Erweiterung und Anpassung

Funktionen von ell

  • ell ist eine in Bash geschriebene Kommandozeilenoberfläche für LLMs
  • Man kann LLMs direkt im Terminal befragen, und das Tool ist für die einfache Nutzung mit Pipes ausgelegt
  • Der Kontext des Terminals kann an das LLM übergeben werden, bevor eine Frage gestellt wird
  • Man kann im Terminal mit dem LLM chatten
  • Über Templates werden Function Calling und zusätzliche Funktionen unterstützt
  • Eine Funktion zum Entfernen sensibler Informationen ist enthalten; dazu ist #14 verlinkt

Voraussetzungen und Installation

  • Für die grundlegende Nutzung werden die folgenden Werkzeuge benötigt
    • bash 4.1 oder höher
    • coreutils oder OS-X-Dienstprogramme
    • jq zum Parsen von JSON
    • curl für HTTPS-Anfragen
  • Wenn der Record Mode nicht verwendet wird, sind die folgenden Werkzeuge nicht zwingend erforderlich
    • perl für PCRE
    • der script-Befehl aus util-linux zum Aufzeichnen von Terminal-Ein- und -Ausgaben
  • Die Installation erfolgt, indem das Repository nach ~/.ellrc.d geklont und dieser Pfad zu PATH hinzugefügt wird
git clone --depth 1 https://github.com/simonmysun/ell.git ~/.ellrc.d
echo 'export PATH="${HOME}/.ellrc.d:${PATH}"' >> ~/.bashrc

Konfigurationsweise

  • Die Konfigurationsdokumentation findet sich unter Configuration
  • Für die Verwendung von Google gemini-1.5-flash werden in ~/.ellrc die folgenden Werte gesetzt
ELL_API_STYLE=gemini
ELL_LLM_MODEL=gemini-1.5-flash
ELL_TEMPLATE=default-gemini
ELL_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ELL_API_URL=https://generativelanguage.googleapis.com/v1beta/models/
  • Für die Verwendung von OpenAI gpt-4o-mini wird die folgende Konfiguration genutzt
ELL_API_STYLE=openai
ELL_LLM_MODEL=gpt-4o-mini
ELL_TEMPLATE=default-openai
ELL_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ELL_API_URL=https://api.openai.com/v1/chat/completions

Anwendungsbeispiele

  • Eine einfache Frage wird als Kommandoargument übergeben
ell "What is the capital of France?"
  • Es kann ein Modell angegeben und eine Datei als Eingabe verwendet werden
ell -m gpt-4o -f user_prompt.txt
  • Auch Standardeingaben werden unterstützt
cat somecode.py | ell -f -
  • Zusätzliche Prompts können ad hoc angehängt werden, ohne sie in ein Template einzubauen
(cat somecode.py; echo "Explain this code") | ell -f -
  • Der Record Mode zeichnet Terminal-Ein- und -Ausgaben auf und verwendet sie später als Kontext für Fragen
ell -r

# do random stuff
ell What does the error code mean?
ell How to fix it?
  • Der interaktive Modus wird mit -i gestartet; dabei wird für kontextbasiertes Chatten automatisch der Record Mode aktiviert
ell -i
  • Record Mode und interaktiver Modus können zusammen mit einem Template gestartet werden
ell -r -i -t ctf-gemini
ell -r -i -t ctf-openai

Templates, Styling, Plugins

  • Die Dokumentation zum Erstellen von Templates findet sich unter Templates
  • Die Funktion in ell zur Nutzung der Plugin-Unterstützung von LLM-Anbietern wird über Templates umgesetzt
  • Die Styling-Dokumentation findet sich unter Styling
  • Die Plugin-Dokumentation findet sich unter Plugins
  • Mit Plugin ist hier ein Skript gemeint, das von ell aufgerufen werden kann und zur Erweiterung der Funktionen von ell dient
    • Plugins, die vom LLM-Anbieter unterstützt werden, fallen nicht in diese Kategorie; für diese Funktion sollte die Template-Dokumentation konsultiert werden

Name und Wahl der Implementierung

  • Der Name ell ist eine Kombination aus shell und LLM
  • shellm wurde ebenfalls erwogen, aber verworfen, weil es als she llm missverstanden werden könnte
  • ell wird als kurzer, leicht einzugebender und leicht zu merkender Name vorgestellt, der nicht mit aktiver Software kollidiert
  • Der Grund für die Implementierung in Bash ist, dass Bash auf Unix-artigen Systemen die verbreitetste Shell ist und für diesen Einsatzzweck keine komplexere Sprache benötigt wird
  • Als Unterschied zu ähnlichen Projekten wird genannt, dass ell fast vollständig in Bash geschrieben ist und dadurch leichtgewichtig und einfach zu installieren sowie leicht zu erweitern und anzupassen ist
  • Es ist Pipe-freundlich gestaltet und für die Kombination mit anderen Werkzeugen konzipiert

Verwandte Dokumente und Lizenz

  • Zu berücksichtigende Risiken sind unter Risks Consideration zusammengefasst
  • Beiträge können per Issue oder Pull Request eingereicht werden
  • Die Lizenz ist die MIT License; Details stehen in der Datei LICENSE

1 Kommentare

 
GN⁺ 2024-08-04
Hacker-News-Kommentare
  • Ich frage mich, ob ell als Tool Standard-Input-Pipes annehmen kann.
    Beim Tool https://llm.datasette.io/ nutze ich das häufig etwa so: cat somecode.py | llm -m claude-3.5-sonnet "Explain this code"; außerdem trenne ich die Anweisung als System-Prompt ab und verwende es auch so: cat somecode.py | llm -m claude-3.5-sonnet --system "Explain this code".
    Wenn man Inhalte auf diese Weise in ein LLM pipen kann, werden interessante Anwendungen möglich, etwa eine Webseite zu scrapen und Fragen dazu beantworten zu lassen: https://simonwillison.net/2024/Jun/17/cli-language-models/#f...

    • Ich war lange ein LLM-Skeptiker, aber nachdem ich das Kommandozeilen-Tool llm, Claude 3 Opus Review und das deutlich günstigere 3.5 Sonnet kennengelernt hatte, begann ich, LLMs täglich zu nutzen.
      Die Pipe-Funktion nutze ich wirklich häufig, etwa um die Lesezeit von Webartikeln zu schätzen: curl | llm -m claude-3.5-sonnet -s 'How long does the main content of this article take to read? First count words, then convert using a slow and fast common reading speed.'.
      Die Wortzahl ist überraschend oft falsch, aber die Größenordnung stimmt meistens, und das reicht aus.
      Eines meiner zuletzt am häufigsten verwendeten Shell-Skripte heißt q und enthält llm -s "Answer in as few words as possible. Use a brief style with short replies." -m claude-3.5-sonnet "$*", sodass ich von jedem Terminal aus dumme Fragen stellen kann, ohne mir beobachtet vorzukommen.
      Man kann kurz fragen wie q How do I run Docker with a different entrypoint to that in the container?, oder per Here-Document längere Fragen stellen, etwa was ein Perl-Code tut; gut gefällt mir, dass der Kontext im Terminal erhalten bleibt.
    • Das geht. Zum Beispiel so: cat somecode.py | ell -f -.
      Wenn man spontan noch einen Prompt anhängen möchte, ohne ihn in ein Template zu packen, geht das etwa so: (cat somecode.py; echo "Explain this code") | ell -f -.
      Das hätte ich ins README aufnehmen sollen; und wenn ich llm und die dazugehörigen Artikel vorher gesehen hätte, hätte ich wahrscheinlich deutlich weniger Motivation gehabt, ell zu bauen.
    • Ich weiß nicht, wie man das Modell claude-3.5-sonnet in llm für die lokale Nutzung einrichtet. Auch nach dem Lesen der Plugin-Dokumentation konnte ich es nicht herausfinden.
  • Es gibt auch ein Projekt, das etwas Ähnliches mit der Shell versucht. Ich bin mir nicht sicher, welche Seite besser ist.
    Demo
    Quellcode

    • Sieht deutlich schicker aus.
      Zuerst dachte ich, die Struktur würde Nutzereingaben aus Orten wie .bash_history lesen, aber beim Nachsehen stellte sich heraus, dass Terminal-Ausgaben nicht als Kontext genutzt werden können.
      Trotzdem gefällt mir, dass awk für die Verarbeitung der Antworten verwendet wird, und ich denke, ell könnte ebenfalls awk nutzen, um die Abhängigkeiten von jq und perl zu reduzieren.
      Ich werde es im README im Abschnitt zu verwandten Projekten ergänzen.
    • Schön und funktionsreich – ich frage mich, warum es so wenige GitHub-Sterne hat.
  • Ich habe ein ähnliches Tool gebaut, das ich nicht mehr pflege: https://github.com/llimllib/gpt-bash-cli/
    Als Vorschlag: Konversationen sollten lieber in einer SQLite-Datenbank gespeichert werden, mit der Nutzer Daten leichter handhaben können, statt in Textdateien; und statt ~/.ellrcd sollte man XDG-Verzeichnisse verwenden.
    Außerdem möchte ich nicht jedem ausgeführten Programm Zugriff auf API-Schlüssel geben, daher bevorzuge ich einen System-Secrets-Speicher gegenüber Umgebungsvariablen.

    • Die Bildunterstützung ist cool.
      Man kann wohl nicht voraussetzen, dass alle SQLite haben, aber es sieht so aus, als ließe sich das optional als Plugin anbieten.
      XDG-Verzeichnisse und ein System-Secrets-Speicher wirken deutlich besser als der aktuelle Ansatz; ich will lernen, wie man sie nutzt, und sie integrieren.
    • Ich frage mich, was auf einer Linux-Entwicklungsmaschine der empfohlene Weg für Secret-Speicherung ist.
      Beliebige Skripte und Programme müssen Geheimnisse wie API-Schlüssel zur Laufzeit mit minimalem Aufwand lesen können, und sie sollten nicht im Klartext auf der Festplatte liegen.
      Ich glaube, es wurde keyring empfohlen; ich frage mich aber, ob das der „GNU/Linux-Weg“ ist, oder ob auch die Speicherung in einem verschlüsselten Dateisystem möglich ist, ob FUSE-basiert oder nicht.
      [1]: https://github.com/llimllib/gpt-bash-cli/blob/841682affe2d0e...
    • Ich würde eher hoffen, dass keyring nicht verwendet wird. Es ist lästig und auf manchen Systemen nicht vorhanden.
      LLM-Schlüssel sind nicht so kritisch, und Programme, die man auf dem eigenen System ausführt, muss man ohnehin vertrauen.
      Ich benutze Poetry nicht, weil es Zugriff auf keyring verlangt; dazu gibt es seit Jahren einen offenen Bug, und eigentlich braucht es den Zugriff gar nicht.
    • Ich habe kein SQLite und weiß auch nicht, wie man es benutzt.
      Persönlich finde ich Textdateien viel besser.
  • Als ähnliches Tool habe ich https://autocomplete.sh gebaut
    https://github.com/closedloop-technologies/autocomplete-sh
    Ich wollte, dass sich tabbasierte Autovervollständigung im Terminal einfach so anfühlt, als würde sie funktionieren
    Es war ziemlich schwierig, die LLM-Antworten sauber in das Format zu bringen, das bash_completion erwartet, aber sobald es lief, konnte ich OpenAI, grok, Claude, Ollama und sogar lokale Modelle alle damit kapseln
    Um es schlauer zu machen, habe ich die jüngste History nach Entfernen von Passwörtern, gesetzte Umgebungsvariablen und die --help-Ausgabe relevanter Befehle ebenfalls ins Kontextfenster gepackt
    Habe vor Kurzem angefangen, es im Raum Boston zu bewerben, und die Leute scheinen es zu mögen

    • Das Demo-Video ist sehr gut: https://youtu.be/IAgkjerCvz8
    • Sieht sehr nützlich aus
      Über Autovervollständigung hatte ich auch nachgedacht, aber meine Idee war eher wie Copilot, und die User Experience dieses Skripts wirkt besser
      Der Teil, der die History in den Kontext einbezieht, wäre wirklich hilfreich, wenn man so etwas wie einen History-Modus à la ell hinzufügt
      Das Bereinigen von Passwörtern ist eine gute Idee; ich werde es als Plugin hinzufügen
    • Ich habe autocomplete-sh bei einem Treffen von AI Tinkerers in Cambridge, MA, in Aktion gesehen und fand es beeindruckend
      Es ist sehr gut in die Shell integriert, und die Entscheidung, es direkt in Bash zu schreiben, ist mutig, aber effektiv, um Portabilität zu erhalten
    • Klingt interessant
      Ich frage mich, ob es auch in der Fish-Shell funktioniert und wie Updates oder die Deinstallation laufen
  • Sieht gut aus. Da ich auf mehreren Maschinen arbeite, ziehen mich leichtgewichtige Tools, wie man sie in Shell schreibt, immer an
    Aus Neugier: Kannst du erklären, warum Befehle wie : "${ELL_LOG_LEVEL:=2}"; mit einem Doppelpunkt beginnen? Ich dachte, der Doppelpunkt sei nur als No-op-Befehl nützlich
    [1]: https://github.com/simonmysun/ell/blob/main/ell.sh#L19C1-L19...

    • : sorgt im Grunde dafür, dass bash mit dem Ergebnis dieser Zeile nichts tut
      Daher initialisiert : "${ELL_LOG_LEVEL:=2}"; ELL_LOG_LEVEL auf 2, falls es noch nicht gesetzt ist, ohne Ausgabe zu erzeugen
    • Den Doppelpunkt habe ich hinzugefügt, um sicherzustellen, dass das Ergebnis nicht ausgeführt wird
      Habe ich hier gelernt: https://stackoverflow.com/a/28085062/2485717
  • Der Ansatz, nur reines Bash und Unix-Tools zu verwenden, ist interessant
    Ich habe Plandex[1] mit ähnlichen Zielen gebaut: keine Abhängigkeiten, terminalbasiert, unterstützt Pipe-Eingaben als Kontext, aber ich habe einen völlig anderen Weg gewählt und es in Go geschrieben, damit es zu einem statischen Binary kompiliert wird
    Plandex ist eher höher angesiedelt und aufs Coding fokussiert, während ell wie ein sehr leichtgewichtiges und universelles LLM-Tool wirkt und mich stark an Simon Willisons llm[2] erinnert
    Die Aufnahmefunktion erinnert auch an savvy[3]
    1 - https://github.com/plandex-ai/plandex
    2 - https://github.com/simonw/llm
    3 - https://github.com/getsavvyinc/savvy-cli

    • Plandex gefällt mir auch, und an einen solchen Workflow hatte ich noch nicht gedacht
      Simon Willisons llm-Tool kannte ich nicht, aber ich hätte mir schon gedacht, dass er so eine Software gebaut hat
      llm unterstützt tiefergehende Manipulationen von LLMs; ell fehlen solche Funktionen, versucht dafür aber, nur die gängigste und grundlegendste Schnittstelle zu nutzen und Verbesserungen der User Experience wie Paging oder Syntax-Highlighting möglichst leichtgewichtig zu halten
      Ich sollte im README erwähnen, dass Nutzer, die mehr LLM-Manipulation brauchen, zu simonw/llm gehen sollten
  • Der „Risks“-Link im README ist kaputt
    Was ich gern hätte: ell -r wird automatisch aktiviert, und ein Alias namens fix schlägt Korrekturen inklusive Dateiänderungen vor
    Wenn es zum Beispiel einen Tippfehler in main.cc gibt und man gcc main.cc ausführt und danach fix, dann sollte ell eine Korrektur als diff für die Datei vorschlagen; nach Bestätigung die Änderung anwenden und anschließend anbieten, gcc erneut auszuführen, und es bei Bestätigung ausführen

    • Den „Risks“-Link habe ich repariert
      ell -r kann man in .bashrc hinzufügen, aber ich bin nicht sicher, ob das mit bestehenden Einstellungen der Nutzer kollidiert oder andere Probleme verursacht
      Abgesehen von der Patch-Bestätigung scheint das mit Templates und Plugins möglich zu sein, aber das tatsächliche Anwenden von Änderungen ist sowohl technisch als auch aus Sicht des UI-Designs schwierig
      Ich werde ausloten, was machbar ist
    • Um ell -r automatisch auszuführen, füge es einfach zu .bashrc hinzu
  • Ich werde es ausprobieren; persönlich nutze ich für diesen Zweck aichat[0]
    Es ist interessant zu sagen, dass man für so etwas keine komplexere Sprache als Bash braucht, aber die Tatsache, dass jq/curl/perl nötig sind, spricht doch eher für das Gegenteil, oder?
    [0] https://github.com/sigoden/aichat

    • Stimmt. Deshalb habe ich sie als Einschränkungen aufgeführt
      Die ursprüngliche Idee war, alles mit Bash zu erledigen, aber aus den genannten Gründen war das nicht möglich
      Mit awk könnte man jq und perl vielleicht entfernen, aber das würde stark zulasten der Einfachheit und Lesbarkeit des Codes gehen
      Ich sehe die Implementierung eines Syntax-Highlighters als die untere Grenze dessen, worauf ich bestehen kann, und möchte in Bash nichts Komplexeres bauen
      Solche Funktionen werde ich entweder nicht unterstützen oder nur als externe Plugins anbieten
    • Noch eine Stimme für aichat. Es ist sehr gut
      Unter Linux habe ich mir ein kleines Bash-Skript geschrieben, das das neueste Binary herunterlädt und nach /home/me/bin entpackt
  • Interessant, aber im Demo-Video sieht man einen typischen LLM-Fehler
    Es wird erklärt, dass bei Verwendung von 1<> eine vorhandene Datei überschrieben werden kann, und dass man, um das zu vermeiden, mit der Option -a anhängen solle; anschließend wird als Beispiel bash ls 1<> output.txt gezeigt. Das Beispiel passt aber nicht zur Erklärung und ist falsch.
    Soweit ich weiß, wäre das nächstliegende Verhalten ls >> output.txt.
    Ich bin mir nicht sicher, ob 1<> output.txt in diesem Kontext einen sinnvollen Aufruf darstellt; denkbar wäre allenfalls, es an einen benutzerdefinierten File Descriptor wie 3 zu binden und dann so etwas wie tee --append zu verwenden.

  • Ich mag mods von Charmbracelet sehr.
    Ich nutze es seit ein paar Monaten; es funktioniert gut, lässt sich stark anpassen und die Ausgabe ist sauber.
    https://github.com/charmbracelet/mods

    • mods eignet sich gut für Dialoge, während ell selbst dagegen im Hinblick auf Nutzereingaben und generierte Inhalte zustandslos ist.
      Die interaktive Nutzung von ell beruht darauf, mit script die Terminal-Ausgabe aufzuzeichnen.
      Man könnte die Verwaltung früherer Gespräche über Plugins mit Seiteneffekten unterstützen, aber ob das zur Idee und Philosophie von ell passt, muss man sich überlegen.
      Ich habe nach ähnlichen Projekten gesucht, aber solche leistungsfähigen Praxis-Tools, wie sie HN-Nutzer hier gepostet haben, nicht gefunden.