]> gitweb.factorcode.org Git - factor.git/commitdiff
Added a simple GUI interface for openai (#2787)
authorDave Carlton <davec@mac.com>
Sun, 30 Jul 2023 20:36:28 +0000 (15:36 -0500)
committerGitHub <noreply@github.com>
Sun, 30 Jul 2023 20:36:28 +0000 (13:36 -0700)
* Added a simple GUI interface for openai

* Change >B to use .s

Redo sloppy code

* Renamed openai-gui to gui

* Added logging to a listener window for debugging when walker is not available.

* Ignore git-id file created by save-git-id in mason.build

.gitignore
basis/ui/tools/listener/log/authors.txt [new file with mode: 0644]
basis/ui/tools/listener/log/log.factor [new file with mode: 0644]
extra/openai/gui/authors.txt [new file with mode: 0644]
extra/openai/gui/gui-docs.factor [new file with mode: 0644]
extra/openai/gui/gui.factor [new file with mode: 0644]

index c89b3eaba889a00ef3ff7aa02a8e856e6aa7b039..362eba8504f89946fadb7643320e65cc3a4e2b4f 100644 (file)
@@ -34,3 +34,5 @@ checksums.txt
 factor.com
 factor.image.fresh
 xcuserdata
+bin
+git-id
diff --git a/basis/ui/tools/listener/log/authors.txt b/basis/ui/tools/listener/log/authors.txt
new file mode 100644 (file)
index 0000000..0c9e056
--- /dev/null
@@ -0,0 +1 @@
+Dave Carlton
diff --git a/basis/ui/tools/listener/log/log.factor b/basis/ui/tools/listener/log/log.factor
new file mode 100644 (file)
index 0000000..8d516d6
--- /dev/null
@@ -0,0 +1,42 @@
+! Copyright (C) 2023 Dave Carlton.
+! See https://factorcode.org/license.txt for BSD license.
+USING: accessors io kernel lexer namespaces prettyprint sequences
+strings.parser ui.tools.listener words ;
+IN: ui.tools.listener.log
+
+: L.s* ( listener -- )
+    input>> output>> 
+    [ "---" print .s ]
+    with-output-stream*  ;
+
+: L.s ( -- ) 
+    get-listener L.s* ; 
+   
+: (lcompose) ( string -- quot )
+    [ nl print ] curry ; 
+
+SYMBOL: LPRINT
+
+: Lprint* ( string listener -- )
+    swap LPRINT set 
+    input>> output>> 
+    [ LPRINT get print ]  
+    with-output-stream*  ; 
+
+: Lprint ( string -- )
+    get-listener Lprint* ; 
+
+: +colon-space ( string -- string' )  ": " append ;
+: +space ( string -- string' )   " " append ; 
+
+: (.here) ( name -- )  +colon-space Lprint ;
+: (here.) ( obj name -- )  [ unparse ] dip +colon-space prepend  Lprint ;
+: (here.s) ( name -- )  +colon-space Lprint L.s ;
+
+SYNTAX: .HERE last-word name>> suffix!  \ (.here) suffix! ;
+SYNTAX: HERE. last-word name>> suffix!  \ (here.) suffix! ;
+SYNTAX: HERE.S last-word name>> suffix!  \ (here.s) suffix! ;
+SYNTAX: HERE" last-word name>> +colon-space  ! "for the editors sake
+    lexer get skip-blank parse-string append suffix!
+    \ Lprint suffix! ;
+
diff --git a/extra/openai/gui/authors.txt b/extra/openai/gui/authors.txt
new file mode 100644 (file)
index 0000000..0c9e056
--- /dev/null
@@ -0,0 +1 @@
+Dave Carlton
diff --git a/extra/openai/gui/gui-docs.factor b/extra/openai/gui/gui-docs.factor
new file mode 100644 (file)
index 0000000..ebf8c1e
--- /dev/null
@@ -0,0 +1,84 @@
+! Copyright (C) 2023 Dave Carlton.
+! See https://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax kernel strings openai ui.commands ;
+IN: openai.openai-gui
+
+HELP: <ask>
+{ $values
+    { "gpt-gadget" object }
+}
+{ $description "Creates the ask entry field for the prompt to the API" } ;
+
+HELP: <gpt-gadget>
+{ $values
+    { "gadget" object }
+}
+{ $description "Creates the gadget for the UI" } ;
+
+HELP: <response>
+{ $values
+    { "gpt-gadget" object }
+}
+{ $description "Creates a scrolling pane for the response" } ;
+
+HELP: >q
+{ $values
+    { "question" object }
+}
+{ $description "Sends the question to OpenAI API. Intended for simple questions using the listener." } ;
+
+HELP: com-cancel
+{ $values
+    { "window" object }
+}
+{ $description "" } ;
+
+HELP: com-send
+{ $values
+    { "window" object }
+}
+{ $description "" } ;
+
+HELP: gpt-gadget
+{ $class-description "Definition of a track gadget containing an ask and response element." } ;
+
+HELP: gpt-new
+{ $description "Opens a new window for asking a question using openai." } ;
+
+HELP: init-api-key
+{ $description
+  "Initialize the API key which MUST be located in the path set in "
+  { $link OPENAI-KEY-PATH }
+} ;
+
+HELP: OPENAI-KEY-PATH
+{ $description "Holds the path to the users API key file." }
+    ;
+
+HELP: openai-doc
+{ $description "Opens a URL to the OpenAI web site documentation." } ;
+
+HELP: openai-test
+{ $description "Simple code to test connection to OpenAI API." } ;
+
+HELP: wrap-result
+{ $values
+    { "string" string } { "maxwidth" object }
+    { "string'" string }
+}
+{ $description "Takes a long string from the response and wraps it according to the repsonse pane width." } ;
+
+ARTICLE: "openai.openai-gui" "A GUI interface for OpenAI API"
+"This is intended to serve as a simple implementation to interface to the OpenAI API\n"
+"It can also be opened using words:"
+
+{ $subsections
+    gpt-new
+}
+
+{ $command-map gpt-gadget "toolbar" }
+
+{ $vocab-link "openai" }
+;
+
+ABOUT: "openai.openai-gui"
diff --git a/extra/openai/gui/gui.factor b/extra/openai/gui/gui.factor
new file mode 100644 (file)
index 0000000..0165189
--- /dev/null
@@ -0,0 +1,100 @@
+! Copyright (C) 2023 Dave Carlton.
+! See https://factorcode.org/license.txt for BSD license.
+USING: accessors assocs colors fonts io io.encodings.utf8 io.files
+kernel math namespaces openai sequences ui ui.commands ui.gadgets
+ui.gadgets.borders ui.gadgets.editors ui.gadgets.labels
+ui.gadgets.scrollers ui.gadgets.toolbar ui.gadgets.tracks ui.gestures
+ui.pens.solid ui.text ui.tools.common ui.tools.listener urls
+webbrowser wrap.strings ;
+
+IN: openai.openai-gui
+
+INITIALIZED-SYMBOL: OPENAI-KEY-PATH [ "~/.config/configstore/openai-key" ]
+
+: init-api-key ( -- )
+    openai-api-key get-global [
+        OPENAI-KEY-PATH get-global dup
+        file-exists? [
+            utf8 file-lines
+            first openai-api-key set-global
+        ]
+        [ drop
+          "Missing API key in OPENAI-KEY-PATH" print
+        ]
+        if
+    ] unless ; 
+
+: >B ( -- ) ! "
+    get-listener input>> output>> 
+    [ nl "---" print .s ]
+    with-output-stream*  ;
+
+: wrap-result ( string maxwidth -- string' )
+    monospace-font " " text-width >integer /  wrap-string ;
+
+: openai-doc ( -- )
+    URL" https://platform.openai.com/docs/models/overview" open-url ;
+
+: openai-test ( -- )
+    init-api-key
+    "text-davinci-003"
+    "what is the factor programming language"
+    <completion> 100 >>max_tokens create-completion
+    "choices" of first "text" of print ;
+
+
+: >q ( question -- )
+    init-api-key
+    "text-davinci-003"
+    swap <completion> 1000 >>max_tokens create-completion
+    "choices" of first "text" of
+    listener-gadget get-tool-dim first 
+    wrap-string print ; 
+
+TUPLE: gpt-gadget < track ask response ;
+
+: com-send ( window -- )
+    completion new  1000 >>max_tokens  "text-davinci-003" >>model
+    over ask>> editor-string  >>prompt
+    create-completion
+    "choices" of first "text" of
+    over dim>> first wrap-result
+    over response>> set-editor-string
+    drop ;
+
+: com-cancel ( window -- )
+    close-window ;
+
+: <ask> ( gpt-gadget -- gpt-gadget )
+    ask>> "Ask: " label-on-left ;
+
+: <response> ( gpt-gadget -- gpt-gadget )
+    response>> <scroller> COLOR: gray <solid> >>boundary ;
+
+M: gpt-gadget history-value
+    ask>> editor-string 1 2array ;
+
+M: gpt-gadget set-history-value
+    [ first ] dip ask>> set-editor-string ; 
+
+gpt-gadget "toolbar" f {
+    { T{ key-down f f "RET" } com-send }
+    { f com-cancel }
+} define-command-map
+
+: <gpt-gadget> ( -- gadget )
+    vertical gpt-gadget new-track
+    1 >>fill  { 10 10 } >>gap
+    <editor> dup "hello world" swap set-editor-string   >>ask
+    <multiline-editor>  10 >>min-rows  80 >>min-cols  >>response
+    dup <ask> f track-add
+    dup <response> 1 track-add
+    dup <toolbar> f track-add ;
+
+: gpt-new ( -- )
+    init-api-key
+    <gpt-gadget>
+    { 5 5 } <border>  { 1 1 } >>fill
+    "GPT" open-window ; 
+
+