82 lines
3.8 KiB
Org Mode
82 lines
3.8 KiB
Org Mode
#+PROPERTY: header-args:lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
:PROPERTIES:
|
|
:ID: llm-gateway-spec
|
|
:CREATED: [2026-04-10 Thu]
|
|
:END:
|
|
#+TITLE: Skill: LLM Gateway
|
|
#+STARTUP: content
|
|
#+FILETAGS: :skill:llm:gateway:
|
|
|
|
* Overview
|
|
The *LLM Gateway* skill provides a unified interface for interacting with multiple Large Language Model providers.
|
|
|
|
* Implementation
|
|
|
|
** Package Context
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(in-package :opencortex)
|
|
#+end_src
|
|
|
|
** Skill Metadata
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(defparameter *skill-llm-gateway*
|
|
'(:name "llm-gateway"
|
|
:description "Unified provider-agnostic LLM interface."
|
|
:capabilities (:ask-llm :get-embedding)
|
|
:type :probabilistic)
|
|
"Skill metadata for the LLM Gateway.")
|
|
#+end_src
|
|
|
|
** Request Execution
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(defun execute-llm-request (&key prompt system-prompt provider model)
|
|
"Generic executor for all LLM providers."
|
|
(let* ((active-provider (or provider :ollama))
|
|
(api-key (uiop:getenv (format nil "~:@(~a_API_KEY~)" active-provider)))
|
|
(full-prompt (if system-prompt (format nil "~a~%~%~a" system-prompt prompt) prompt)))
|
|
(case active-provider
|
|
(:ollama
|
|
(let* ((host (or (uiop:getenv "OLLAMA_HOST") "localhost:11434"))
|
|
(url (format nil "http://~a/api/generate" host))
|
|
(body (cl-json:encode-json-to-string `((model . ,(or model "llama3")) (prompt . ,full-prompt) (stream . :false)))))
|
|
(handler-case
|
|
(let* ((response (dex:post url :headers '(("Content-Type" . "application/json")) :content body))
|
|
(json (cl-json:decode-json-from-string response)))
|
|
(list :status :success :content (cdr (assoc :response json))))
|
|
(error (c) (list :status :error :message (format nil "Ollama Failure: ~a" c))))))
|
|
(t (list :status :error :message "Provider not implemented")))))
|
|
#+end_src
|
|
|
|
** Cognitive Tools
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(def-cognitive-tool :get-ollama-embedding (text)
|
|
(let* ((host (or (uiop:getenv "OLLAMA_HOST") "localhost:11434"))
|
|
(url (format nil "http://~a/api/embeddings" host))
|
|
(body (cl-json:encode-json-to-string `((model . "nomic-embed-text") (prompt . ,text)))))
|
|
(handler-case
|
|
(let* ((response (dex:post url :headers '(("Content-Type" . "application/json")) :content body))
|
|
(json (cl-json:decode-json-from-string response)))
|
|
(cdr (assoc :embedding json)))
|
|
(error (c) (harness-log "OLLAMA EMBED ERROR: ~a" c) nil))))
|
|
#+end_src
|
|
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(def-cognitive-tool :ask-llm (prompt system-prompt provider model)
|
|
(execute-llm-request :prompt prompt
|
|
:system-prompt system-prompt
|
|
:provider provider
|
|
:model model))
|
|
#+end_src
|
|
|
|
** Skill Registration
|
|
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
|
(defskill :skill-llm-gateway
|
|
:priority 50
|
|
:trigger (lambda (ctx) (declare (ignore ctx)) t)
|
|
:probabilistic (lambda (ctx)
|
|
(let ((input (getf ctx :user-input)))
|
|
(when input
|
|
(execute-llm-request :prompt input))))
|
|
:deterministic (lambda (action ctx) (declare (ignore ctx)) action))
|
|
#+end_src
|