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_provider_openai/convert_prompt.ml.html
Source file convert_prompt.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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197open Melange_json.Primitives (* --- Typed JSON records for serialization --- *) type text_content_part = { type_ : string; [@json.key "type"] text : string; } [@@deriving to_json] type image_url_detail = { url : string } [@@deriving to_json] type image_url_content_part = { type_ : string; [@json.key "type"] image_url : image_url_detail; } [@@deriving to_json] type function_call_json = { name : string; arguments : string; } [@@deriving to_json] type tool_call_json = { id : string; type_ : string; [@json.key "type"] function_ : function_call_json; [@json.key "function"] } [@@deriving to_json] type role_content_msg = { role : string; content : string; } [@@deriving to_json] type role_parts_msg = { role : string; content : Melange_json.t list; } [@@deriving to_json] type assistant_msg_with_tools_json = { role : string; content : string option; [@json.option] [@json.drop_default] tool_calls : tool_call_json list; } [@@deriving to_json] type assistant_msg_text_json = { role : string; content : string option; [@json.option] [@json.drop_default] } [@@deriving to_json] type tool_msg_json = { role : string; tool_call_id : string; content : string; } [@@deriving to_json] (* --- Domain types --- *) type openai_content_part = | O_text of { text : string } | O_image_url of { url : string } type openai_function_call = { name : string; arguments : string; } type openai_tool_call = { id : string; type_ : string; function_ : openai_function_call; } type openai_message = | System_msg of { content : string } | Developer_msg of { content : string } | User_msg of { content : openai_content_part list } | Assistant_msg of { content : string option; tool_calls : openai_tool_call list; } | Tool_msg of { tool_call_id : string; content : string; } (* --- Conversion logic --- *) let file_data_to_url ~media_type (data : Ai_provider.Prompt.file_data) = match data with | Bytes b -> let encoded = Base64.encode_string (Bytes.to_string b) in Printf.sprintf "data:%s;base64,%s" media_type encoded | Base64 s -> Printf.sprintf "data:%s;base64,%s" media_type s | Url u -> u let convert_user_part (part : Ai_provider.Prompt.user_part) : openai_content_part = match part with | Text { text; _ } -> O_text { text } | File { data; media_type; _ } -> if String.starts_with ~prefix:"image/" media_type then O_image_url { url = file_data_to_url ~media_type data } else O_text { text = Printf.sprintf "[file: %s]" media_type } let convert_assistant_parts (parts : Ai_provider.Prompt.assistant_part list) : string option * openai_tool_call list = let text_buf = Buffer.create 256 in let tool_calls = List.fold_left (fun acc (part : Ai_provider.Prompt.assistant_part) -> match part with | Text { text; _ } -> Buffer.add_string text_buf text; acc | File _ | Reasoning _ -> acc | Tool_call { id; name; args; _ } -> { id; type_ = "function"; function_ = { name; arguments = Yojson.Basic.to_string args } } :: acc) [] parts |> List.rev in let content = if Buffer.length text_buf > 0 then Some (Buffer.contents text_buf) else None in content, tool_calls let convert_tool_result (tr : Ai_provider.Prompt.tool_result) : openai_message = let content = match tr.content with | [] -> (match tr.result with | `String s -> s | json -> Yojson.Basic.to_string json) | parts -> let texts = List.map (fun (c : Ai_provider.Prompt.tool_result_content) -> match c with | Result_text s -> s | Result_image { data; media_type } -> Printf.sprintf "[image: %s, %d bytes]" media_type (String.length data)) parts in String.concat "\n" texts in Tool_msg { tool_call_id = tr.tool_call_id; content } let convert_messages ~system_message_mode messages = let warnings = ref [] in let result = List.concat_map (fun (msg : Ai_provider.Prompt.message) -> match msg with | System { content } -> (match (system_message_mode : Model_catalog.system_message_mode) with | System -> [ System_msg { content } ] | Developer -> [ Developer_msg { content } ] | Remove -> warnings := Ai_provider.Warning.Unsupported_feature { feature = "system-messages"; details = Some "System messages are removed for this model" } :: !warnings; []) | User { content } -> [ User_msg { content = List.map convert_user_part content } ] | Assistant { content } -> let text, tool_calls = convert_assistant_parts content in [ Assistant_msg { content = text; tool_calls } ] | Tool { content } -> List.map convert_tool_result content) messages in result, List.rev !warnings (* --- JSON serialization via derivers --- *) let content_part_to_json = function | O_text { text } -> text_content_part_to_json { type_ = "text"; text } | O_image_url { url } -> image_url_content_part_to_json { type_ = "image_url"; image_url = { url } } let domain_tool_call_to_json_record (tc : openai_tool_call) : tool_call_json = { id = tc.id; type_ = tc.type_; function_ = { name = tc.function_.name; arguments = tc.function_.arguments } } let openai_message_to_json = function | System_msg { content } -> role_content_msg_to_json { role = "system"; content } | Developer_msg { content } -> role_content_msg_to_json { role = "developer"; content } | User_msg { content } -> (match content with | [ O_text { text } ] -> role_content_msg_to_json { role = "user"; content = text } | parts -> role_parts_msg_to_json { role = "user"; content = List.map content_part_to_json parts }) | Assistant_msg { content; tool_calls } -> (match tool_calls with | [] -> assistant_msg_text_json_to_json { role = "assistant"; content } | calls -> assistant_msg_with_tools_json_to_json { role = "assistant"; content; tool_calls = List.map domain_tool_call_to_json_record calls }) | Tool_msg { tool_call_id; content } -> tool_msg_json_to_json { role = "tool"; tool_call_id; content }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>