package ocaml-ai-sdk

  1. Overview
  2. Docs
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/core_tool.ml.html

Source file core_tool.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
type t = {
  description : string option;
  parameters : Yojson.Basic.t;
  execute : (Yojson.Basic.t -> Yojson.Basic.t Lwt.t) option;
  needs_approval : (Yojson.Basic.t -> bool Lwt.t) option;
  provider_options : Ai_provider.Provider_options.t;
}

let create ?description ?needs_approval ?(provider_options = Ai_provider.Provider_options.empty) ~parameters ~execute ()
    =
  { description; parameters; execute = Some execute; needs_approval; provider_options }

let create_with_approval ?description ?(provider_options = Ai_provider.Provider_options.empty) ~parameters ~execute () =
  {
    description;
    parameters;
    execute = Some execute;
    needs_approval = Some (fun _ -> Lwt.return_true);
    provider_options;
  }

let create_client_tool ?description ?(provider_options = Ai_provider.Provider_options.empty) ~parameters () =
  { description; parameters; execute = None; needs_approval = None; provider_options }

let safe_parse_json_args s =
  match s with
  | "" -> `Assoc []
  | _ -> try Yojson.Basic.from_string s with Yojson.Json_error _ -> `String s

let denied_result = `Assoc [ "type", `String "execution-denied" ]

let execute_tool ~tools ~tool_call_id ~tool_name ~args =
  match List.assoc_opt tool_name tools with
  | None ->
    Lwt.return
      {
        Generate_text_result.tool_call_id;
        tool_name;
        result = `String (Printf.sprintf "Tool '%s' not found" tool_name);
        is_error = true;
        provider_metadata = None;
      }
  | Some { execute = None; _ } ->
    Lwt.return
      {
        Generate_text_result.tool_call_id;
        tool_name;
        result = `String "Client-side tool — no server execute";
        is_error = true;
        provider_metadata = None;
      }
  | Some { execute = Some exec; _ } ->
  try%lwt
    let%lwt result = exec args in
    Lwt.return { Generate_text_result.tool_call_id; tool_name; result; is_error = false; provider_metadata = None }
  with exn ->
    Lwt.return
      {
        Generate_text_result.tool_call_id;
        tool_name;
        result = `String (Printexc.to_string exn);
        is_error = true;
        provider_metadata = None;
      }

(** Partition tool calls into (blocked, executable).
    Blocked = needs approval OR client-only (no server execute).
    Executable = has execute and doesn't need approval. *)
let evaluate_approvals ~tools tool_calls =
  let%lwt results =
    Lwt_list.map_s
      (fun (tc : Generate_text_result.tool_call) ->
        let%lwt can_execute =
          match List.assoc_opt tc.tool_name tools with
          | Some { execute = None; _ } -> Lwt.return_false
          | Some { needs_approval = Some check; _ } ->
            let%lwt needs = check tc.args in
            Lwt.return (not needs)
          | Some { execute = Some _; needs_approval = None; _ } -> Lwt.return_true
          | None -> Lwt.return_false
        in
        Lwt.return (tc, can_execute))
      tool_calls
  in
  let blocked, executable =
    List.partition_map
      (fun (tc, can_execute) ->
        match can_execute with
        | true -> Right tc
        | false -> Left tc)
      results
  in
  Lwt.return (blocked, executable)