diff options
Diffstat (limited to 'llm-chat-claude.el')
| -rw-r--r-- | llm-chat-claude.el | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/llm-chat-claude.el b/llm-chat-claude.el new file mode 100644 index 0000000..4807fa9 --- /dev/null +++ b/llm-chat-claude.el @@ -0,0 +1,77 @@ +;;; llm-chat-claude.el --- Implements claude llm intergration -*- lexical-binding: t; -*- + +;; This file is not part of GNU Emacs. + +;;; License: + +;; llm-chat-claude.el is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; llm-chat-claude.el is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Code: + +(require 'llm-chat-api) + +(defvar llm-chat-claude-models '("claude-3-7-sonnet-latest" "claude-3-5-haiku-latest" "claude-3-5-sonnet-latest" "claude-3-sonnet-20240229" "claude-3-haiku-20240307")) + +(cl-defgeneric llm-chat-resolve-model-backend ((backend (eql 'claude)) + model) + (if (member model llm-chat-claude-models) + t)) + +(defun llm-chat-claude-get-model () + (if (member (llm-chat-get-model) llm-chat-claude-models) + (llm-chat-get-model) + "claude-3-haiku-20240307")) + +(defun llm-chat-make-claude-backend () + (make-llm-chat-backend + :api-endpoint "https://api.anthropic.com/v1/messages" + :api-key (auth-source-pick-first-password :host "api.anthropic.com") + :headers-fn #'llm-chat-claude-headers + :json-fn #'llm-chat-claude-json + :filter-fn #'llm-chat-claude-filter)) + +(defun llm-chat-claude-json () + (let ((json-object `((model . ,(llm-chat-claude-get-model)) + (system . ,(llm-chat-get-system-prompt)) + (messages . ,(cdr (llm-chat-get-history))) + (temperature . ,(llm-chat-get-temperature)) + (max_tokens . 4096) + (stream . ,(llm-chat-get-stream?))))) + (json-encode json-object))) + +(defun llm-chat-claude-headers (backend) + (list "-H" "anthropic-version: 2023-06-01" + "-H" (concat "x-api-key: " (llm-chat-backend-api-key backend)))) + +(defun llm-chat-claude-filter (proc string) + (llm-chat-data-filter proc string + #'llm-chat-claude-finished-p + #'llm-chat-claude-parse-content)) + +(defun llm-chat-claude-finished-p (string) + (let* ((json-object (json-read-from-string string)) + (type (alist-get 'type json-object))) + (string-equal type "message_stop"))) + +(defun llm-chat-claude-parse-content (string) + (when-let* ((json-object (json-read-from-string string)) + (type (alist-get 'type json-object)) + (delta (alist-get 'delta json-object)) + (text (alist-get 'text delta))) + (when (string-equal type "content_block_delta") + text))) + +(provide 'llm-chat-claude) + +;;; llm-chat-claude.el ends here |