package ocaml-ai-sdk
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
OCaml AI SDK - Provider abstraction for AI models
Install
dune-project
Dependency
Authors
Maintainers
Sources
ocaml-ai-sdk-0.6.1.tbz
sha256=cb3b82428abcda76c02ec92f8103a4db28edf3f42795794a37135e9a3c40af96
sha512=11be8889ee25bee67b2be00553c42a4692bc73e5ce23985e8bb87f8a07e9d8f556b5a63b219fe5fe30366c8b0d4edae494afa80ccfbfcb112f1fa1e458de55bf
doc/src/ocaml-ai-sdk.ai_core/smooth_stream.ml.html
Source file smooth_stream.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124type chunking = | Word | Line | Regex of Re2.t | Segmenter | Custom of (string -> string option) type active = | Active_text of string | Active_reasoning of string let word_re = Re2.create_exn {|\S+\s+|} let line_re = Re2.create_exn {|\n+|} let detect_chunk_re2 re buffer = match Re2.first_match re buffer with | Ok m -> let pos, len = Re2.Match.get_pos_exn ~sub:(`Index 0) m in Some (String.sub buffer 0 (pos + len)) | Error _ -> None let detect_chunk_segmenter buffer = if String.length buffer = 0 then None else ( let first = ref None in (try Uuseg_string.fold_utf_8 `Word (fun () seg -> if String.length seg > 0 then ( first := Some seg; raise_notrace Exit)) () buffer with Exit -> ()); !first) let make_detector = function | Word -> detect_chunk_re2 word_re | Line -> detect_chunk_re2 line_re | Regex re -> detect_chunk_re2 re | Segmenter -> detect_chunk_segmenter | Custom f -> f let create ?(delay_ms = 10) ?(chunking = Word) ?(sleep = Lwt_unix.sleep) () input_stream = let detect_chunk = make_detector chunking in let delay = match delay_ms with | 0 -> fun () -> Lwt.return_unit | ms -> let secs = Float.of_int ms /. 1000.0 in fun () -> sleep secs in let output_stream, push = Lwt_stream.create () in let buffer = Buffer.create 256 in let current : active option ref = ref None in let emit_delta active text = match active with | Active_text id -> push (Some (Text_stream_part.Text_delta { id; text })) | Active_reasoning id -> push (Some (Text_stream_part.Reasoning_delta { id; text; provider_metadata = None })) in let flush_buffer () = if Buffer.length buffer > 0 then ( match !current with | None -> () | Some active -> emit_delta active (Buffer.contents buffer); Buffer.clear buffer) in let process_smoothable ~active ~text = let same = match !current, active with | Some (Active_text a), Active_text b -> String.equal a b | Some (Active_reasoning a), Active_reasoning b -> String.equal a b | Some (Active_text _), Active_reasoning _ | Some (Active_reasoning _), Active_text _ | None, (Active_text _ | Active_reasoning _) -> false in if not same then ( flush_buffer (); current := Some active); Buffer.add_string buffer text; let rec drain () = match detect_chunk (Buffer.contents buffer) with | None -> Lwt.return_unit | Some chunk -> emit_delta active chunk; let chunk_len = String.length chunk in let remaining = Buffer.contents buffer in Buffer.clear buffer; Buffer.add_string buffer (String.sub remaining chunk_len (String.length remaining - chunk_len)); let%lwt () = delay () in drain () in drain () in Lwt.async (fun () -> try%lwt let%lwt () = Lwt_stream.iter_s (fun (part : Text_stream_part.t) -> match part with | Text_delta { id; text } -> process_smoothable ~active:(Active_text id) ~text | Reasoning_delta { id; text; provider_metadata = None } -> process_smoothable ~active:(Active_reasoning id) ~text | Reasoning_delta { id; text; provider_metadata = Some provider_metadata } -> flush_buffer (); current := None; push (Some (Text_stream_part.Reasoning_delta { id; text; provider_metadata = Some provider_metadata })); Lwt.return_unit | other -> flush_buffer (); current := None; push (Some other); Lwt.return_unit) input_stream in flush_buffer (); push None; Lwt.return_unit with exn -> push (Some (Text_stream_part.Error { error = Printexc.to_string exn })); push None; Lwt.return_unit); output_stream
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>