artificial_core/
schema_util.rs

1//! Helpers for turning Rust type information into JSON Schema that can be
2//! shipped alongside a prompt. The JSON is produced with [`schemars`] and
3//! can be forwarded to providers that support structured / function-calling
4//! responses (e.g. OpenAI’s *response_format = json_schema*).
5//!
6//! The abstraction is intentionally **very small**: if you need a more
7//! sophisticated setup (e.g. inline- vs. $ref-based schemas, custom
8//! serialization logic) you can always bypass this helper and build the
9//! schema manually.
10
11use schemars::{r#gen::SchemaSettings, JsonSchema, SchemaGenerator};
12use serde_json::{self, Value};
13
14/// Generate a JSON Schema for the given `T` **inline**, i.e. without
15/// `$ref` pointers to external definitions.
16///
17/// This is sufficient for most LLM providers, which currently expect the
18/// entire schema object inside a single request.
19///
20/// # Panics
21///
22/// This function panics only if the resulting [`RootSchema`] cannot be
23/// serialized into valid JSON – which should never happen as long as
24/// [`schemars`] works correctly.
25///
26/// # Example
27///
28/// ```
29/// use artificial_core::schema_util::derive_response_schema;
30/// use schemars::JsonSchema;
31///
32/// #[derive(JsonSchema)]
33/// struct Foo { bar: String }
34///
35/// let schema = derive_response_schema::<Foo>();
36/// println!("{}", serde_json::to_string_pretty(&schema).unwrap());
37/// ```
38pub fn derive_response_schema<T>() -> Value
39where
40    T: JsonSchema + 'static,
41{
42    // We want the schema fully inlined to avoid `$ref`s that some providers
43    // may not resolve correctly.
44    let mut settings = SchemaSettings::draft07();
45    settings.inline_subschemas = true;
46
47    let generator = SchemaGenerator::new(settings);
48    let root = generator.into_root_schema_for::<T>();
49
50    serde_json::to_value(root).expect("generated schema should be serialisable")
51}