|
5 | 5 | [hato.middleware :as hm]
|
6 | 6 | [clojure.core.async :as a]
|
7 | 7 | [clojure.string :as string]
|
8 |
| - [cheshire.core :as json] |
9 |
| - [clojure.core.async.impl.protocols :as impl]) |
10 |
| - (:import (java.io InputStream) |
11 |
| - (clojure.lang Counted) |
12 |
| - (java.util LinkedList))) |
| 8 | + [cheshire.core :as json]) |
| 9 | + (:import (java.io InputStream))) |
13 | 10 |
|
14 | 11 | (def event-mask (re-pattern (str "(?s).+?\n\n")))
|
15 | 12 |
|
|
31 | 28 | (-> (subs raw-event data-idx)
|
32 | 29 | (json/parse-string true)))))
|
33 | 30 |
|
34 |
| -(deftype InfiniteBuffer [^LinkedList buf] |
35 |
| - impl/UnblockingBuffer |
36 |
| - impl/Buffer |
37 |
| - (full? [_this] |
38 |
| - false) |
39 |
| - (remove! [_this] |
40 |
| - (.removeLast buf)) |
41 |
| - (add!* [this itm] |
42 |
| - (.addFirst buf itm) |
43 |
| - this) |
44 |
| - (close-buf! [_this]) |
45 |
| - Counted |
46 |
| - (count [_this] |
47 |
| - (.size buf))) |
48 |
| - |
49 |
| -(defn infinite-buffer [] |
50 |
| - (InfiniteBuffer. (LinkedList.))) |
| 31 | +; Per this discussion: https://community.openai.com/t/clarification-for-max-tokens/19576 |
| 32 | +; if the max_tokens is not provided, the response will try to use all the available |
| 33 | +; tokens to generate response, hence DEFAULT_BUFFER_SIZE should be large enough |
| 34 | +(def ^:private DEFAULT_BUFFER_SIZE 100000) |
51 | 35 |
|
52 | 36 | (defn calc-buffer-size
|
53 |
| - "- Use stream_buffer_len if provided. |
54 |
| - - Otherwise, buffer size should be at least equal to max_tokens |
55 |
| - plus the [DONE] terminator if it is provided. |
56 |
| - - Else fallbacks on ##Inf and use an infinite-buffer instead" |
57 |
| - [{:keys [stream_buffer_len max_tokens]}] |
58 |
| - (or stream_buffer_len |
59 |
| - (when max_tokens (inc max_tokens)) |
60 |
| - ##Inf)) |
61 |
| - |
62 |
| -(defn make-buffer [params] |
63 |
| - (let [size (calc-buffer-size params)] |
64 |
| - (if (= size ##Inf) |
65 |
| - (infinite-buffer) |
66 |
| - (a/sliding-buffer size)))) |
| 37 | + "Buffer size should be at least equal to max_tokens |
| 38 | + plus the [DONE] terminator" |
| 39 | + [{:keys [max_tokens] |
| 40 | + :or {max_tokens DEFAULT_BUFFER_SIZE}}] |
| 41 | + (inc max_tokens)) |
67 | 42 |
|
68 | 43 | (defn sse-events
|
69 | 44 | "Returns a core.async channel with events as clojure data structures.
|
|
72 | 47 | (let [event-stream ^InputStream (:body (http/request (merge request
|
73 | 48 | params
|
74 | 49 | {:as :stream})))
|
75 |
| - events (a/chan (make-buffer params) (map parse-event))] |
| 50 | + buffer-size (calc-buffer-size params) |
| 51 | + events (a/chan (a/buffer buffer-size) (map parse-event))] |
76 | 52 | (a/thread
|
77 | 53 | (loop [byte-coll []]
|
78 | 54 | (let [byte-arr (byte-array (max 1 (.available event-stream)))
|
|
181 | 157 | (assoc ctx :response (if (:stream params)
|
182 | 158 | (sse-request ctx')
|
183 | 159 | (http/request request'))))))})
|
| 160 | + |
0 commit comments