debug.scm 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. ;;; guile-openai --- An OpenAI API client for Guile
  2. ;;; Copyright © 2023 Andrew Whatson <whatson@tailcall.au>
  3. ;;;
  4. ;;; This file is part of guile-openai.
  5. ;;;
  6. ;;; guile-openai is free software: you can redistribute it and/or modify
  7. ;;; it under the terms of the GNU Affero General Public License as
  8. ;;; published by the Free Software Foundation, either version 3 of the
  9. ;;; License, or (at your option) any later version.
  10. ;;;
  11. ;;; guile-openai is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;; Affero General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU Affero General Public
  17. ;;; License along with guile-openai. If not, see
  18. ;;; <https://www.gnu.org/licenses/>.
  19. (define-module (openai debug)
  20. #:use-module (openai utils event-stream)
  21. #:use-module (openai utils json)
  22. #:use-module (openai utils multipart)
  23. #:use-module (ice-9 match)
  24. #:use-module (ice-9 textual-ports)
  25. #:use-module (rnrs bytevectors)
  26. #:use-module (rnrs bytevectors gnu)
  27. #:use-module (srfi srfi-9)
  28. #:use-module (srfi srfi-41)
  29. #:use-module (web request)
  30. #:use-module (web response)
  31. #:export (openai-last-api-call
  32. openai-last-request
  33. openai-last-request-body
  34. openai-last-response
  35. openai-last-response-body
  36. openai-print-last-request
  37. openai-print-last-response
  38. openai-write-last-request
  39. openai-write-last-response))
  40. (define-record-type <openai-api-call>
  41. (%make-api-call request request-body response response-body)
  42. openai-api-call?
  43. (request api-call-request)
  44. (request-body api-call-request-body)
  45. (response api-call-response)
  46. (response-body api-call-response-body))
  47. (define openai-last-api-call
  48. (make-parameter #f (match-lambda
  49. (#f
  50. (%make-api-call #f #f #f #f))
  51. ((request request-body response response-body)
  52. (%make-api-call request request-body
  53. response response-body)))))
  54. (define (openai-last-request)
  55. (api-call-request (openai-last-api-call)))
  56. (define (openai-last-request-body)
  57. (api-call-request-body (openai-last-api-call)))
  58. (define (openai-last-response)
  59. (api-call-response (openai-last-api-call)))
  60. (define (openai-last-response-body)
  61. (api-call-response-body (openai-last-api-call)))
  62. (define* (openai-print-last-request #:optional (port (current-output-port)))
  63. "Print a pretty representation of the last API request."
  64. (let* ((call (openai-last-api-call))
  65. (request (api-call-request call))
  66. (body (api-call-request-body call)))
  67. (cond ((not request)
  68. (display ";; No request\n" port))
  69. (else
  70. (write-request request port)
  71. (cond ((string? body)
  72. (write-pretty-json body port))
  73. ((pair? body)
  74. (multipart-tree-visit
  75. (lambda (str)
  76. (put-string port str))
  77. (lambda (bv)
  78. ;; TODO a hexdump would be nice
  79. (if (> (bytevector-length bv) 256)
  80. (format port "~a\n;; ... truncated from ~a bytes\n"
  81. (bytevector-slice bv 0 256)
  82. (bytevector-length bv))
  83. (format port "~a\n" bv)))
  84. body)
  85. (newline port)))))
  86. *unspecified*))
  87. (define* (openai-print-last-response #:optional (port (current-output-port)))
  88. "Print a pretty representation of the last API response."
  89. (let* ((call (openai-last-api-call))
  90. (response (api-call-response call))
  91. (body (api-call-response-body call)))
  92. (cond ((not response)
  93. (display ";; No response\n" port))
  94. (else
  95. (write-response response port)
  96. (cond ((string? body)
  97. (write-pretty-json body port))
  98. ((stream? body)
  99. ;; TODO truncate b64 data in image responses
  100. (stream-for-each (lambda (chunk)
  101. (write-pretty-json chunk port))
  102. (line-stream->event-stream body))))))
  103. *unspecified*))
  104. (define* (openai-write-last-request #:optional (port (current-output-port)))
  105. "Write the raw HTTP request of the last API call to PORT."
  106. (let* ((call (openai-last-api-call))
  107. (request (api-call-request call))
  108. (body (api-call-request-body call)))
  109. (when request
  110. (write-request request port)
  111. (when body
  112. (write-multipart-tree body port)))
  113. *unspecified*))
  114. (define* (openai-write-last-response #:optional (port (current-output-port)))
  115. "Write the raw HTTP response of the last API call to PORT."
  116. (let* ((call (openai-last-api-call))
  117. (response (api-call-response call))
  118. (body (api-call-response-body call)))
  119. (when response
  120. (write-response response port)
  121. (cond ((string? body)
  122. (put-string port body))
  123. ((stream? body)
  124. (stream-for-each (lambda (chunk)
  125. (put-string port chunk))
  126. body))))
  127. *unspecified*))