// @generated by update_schema.py
// checksum<<9e3a8f9389cd89b981fa654e4bf6ebc544f1696f9cac84818d60424143426f30>>
// clang-format off

#pragma once

#include <optional>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>

#include <nlohmann/json.hpp>

#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann {
#endif

#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END }
#endif

// https://github.com/nlohmann/json/pull/2117
NLOHMANN_JSON_NAMESPACE_BEGIN
template <typename T>
struct adl_serializer<std::optional<T>> {
  static void to_json(json& j, const std::optional<T>& opt) {
    if (opt == std::nullopt) {
      j = nullptr;
    } else {
      j = *opt; // this will call adl_serializer<T>::to_json which will
                // find the free function to_json in T's namespace!
    }
  }

  static void from_json(const json& j, std::optional<T>& opt) {
    if (j.is_null()) {
      opt = std::nullopt;
    } else {
      opt = j.template get<T>(); // same as above, but with
                                 // adl_serializer<T>::from_json
    }
  }
};
NLOHMANN_JSON_NAMESPACE_END

namespace torch {
namespace _export {

template <typename T>
class ForwardRef {
  static_assert(!std::is_reference_v<T>, "ForwardRef cannot be a reference type");

 public:
  ForwardRef(): ptr_(std::make_unique<T>()) {}
  ForwardRef(ForwardRef<T>&&) = default;
  ForwardRef(const ForwardRef<T>& other): ptr_(std::make_unique<T>(*other.ptr_)) {}
  ForwardRef<T>& operator=(ForwardRef<T>&&) = default;
  ForwardRef<T>& operator=(const ForwardRef<T>& other) {
    ptr_ = std::make_unique<T>(*other.ptr_);
  }
  const T& operator*() const {
    return *ptr_;
  }

  const T* operator->() const {
    return ptr_.get();
  }

  void emplace(T&& t) {
    ptr_ = std::make_unique<T>(std::move(t));
  }

 private:
  std::unique_ptr<T> ptr_;
};

template <typename T>
void to_json(nlohmann::json& j, const ForwardRef<T>& p) {
  j = *p;
}

template <typename T>
void from_json(const nlohmann::json& j, ForwardRef<T>& p) {
  p.emplace(j.template get<T>());
}

class Argument;
class BufferMutationSpec;
class ConstantValue;
class CustomObjArgument;
class Device;
class ExportedProgram;
class GradientToParameterSpec;
class GradientToUserInputSpec;
class Graph;
class GraphArgument;
class GraphModule;
class GraphSignature;
class InputSpec;
class InputToBufferSpec;
class InputToConstantInputSpec;
class InputToCustomObjSpec;
class InputToParameterSpec;
class InputToTensorConstantSpec;
class InputTokenSpec;
class LossOutputSpec;
class ModuleCallEntry;
class ModuleCallSignature;
class NamedArgument;
class Node;
class OptionalTensorArgument;
class OutputSpec;
class OutputTokenSpec;
class RangeConstraint;
class SchemaVersion;
class SymBool;
class SymBoolArgument;
class SymExpr;
class SymExprHint;
class SymFloat;
class SymFloatArgument;
class SymInt;
class SymIntArgument;
class TensorArgument;
class TensorMeta;
class TokenArgument;
class UserInputMutationSpec;
class UserInputSpec;
class UserOutputSpec;

enum class Layout {
  Unknown = 0,
  SparseCoo = 1,
  SparseCsr = 2,
  SparseCsc = 3,
  SparseBsr = 4,
  SparseBsc = 5,
  _mkldnn = 6,
  Strided = 7,
};

enum class MemoryFormat {
  Unknown = 0,
  ContiguousFormat = 1,
  ChannelsLast = 2,
  ChannelsLast3d = 3,
  PreserveFormat = 4,
};

enum class ScalarType {
  UNKNOWN = 0,
  BYTE = 1,
  CHAR = 2,
  SHORT = 3,
  INT = 4,
  LONG = 5,
  HALF = 6,
  FLOAT = 7,
  DOUBLE = 8,
  COMPLEXHALF = 9,
  COMPLEXFLOAT = 10,
  COMPLEXDOUBLE = 11,
  BOOL = 12,
  BFLOAT16 = 13,
  UINT16 = 28,
};


class Device {
 private:
  std::string type;
  std::optional<int64_t> index = std::nullopt;

 public:

  const std::string& get_type() const {
    return type;
  }

  const std::optional<int64_t>& get_index() const {
    return index;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const Device& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, Device& nlohmann_json_t);
};

class SymExprHint {
  struct Void {};

 public:
  enum class Tag {
    AS_INT, AS_BOOL, AS_FLOAT
  };

 private:
  std::variant<Void, int64_t, bool, double> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const int64_t& get_as_int() const {
    return std::get<1>(variant_);
  }

  const bool& get_as_bool() const {
    return std::get<2>(variant_);
  }

  const double& get_as_float() const {
    return std::get<3>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymExprHint& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_INT) {
      nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOL) {
      nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) {
      nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymExprHint& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_int")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_int").template get<int64_t>());
      nlohmann_json_t.tag_ = Tag::AS_INT;
      return;
    }
    if (nlohmann_json_j.contains("as_bool")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_BOOL;
      return;
    }
    if (nlohmann_json_j.contains("as_float")) {
      nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_float").template get<double>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

class SymExpr {
 private:
  std::string expr_str;
  std::optional<SymExprHint> hint = std::nullopt;

 public:

  const std::string& get_expr_str() const {
    return expr_str;
  }

  const std::optional<SymExprHint>& get_hint() const {
    return hint;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymExpr& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, SymExpr& nlohmann_json_t);
};

class SymInt {
  struct Void {};

 public:
  enum class Tag {
    AS_EXPR, AS_INT
  };

 private:
  std::variant<Void, SymExpr, int64_t> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const SymExpr& get_as_expr() const {
    return std::get<1>(variant_);
  }

  const int64_t& get_as_int() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymInt& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_EXPR) {
      nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INT) {
      nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymInt& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_expr")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get<SymExpr>());
      nlohmann_json_t.tag_ = Tag::AS_EXPR;
      return;
    }
    if (nlohmann_json_j.contains("as_int")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get<int64_t>());
      nlohmann_json_t.tag_ = Tag::AS_INT;
      return;
    }
  }
};

class SymFloat {
  struct Void {};

 public:
  enum class Tag {
    AS_EXPR, AS_FLOAT
  };

 private:
  std::variant<Void, SymExpr, double> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const SymExpr& get_as_expr() const {
    return std::get<1>(variant_);
  }

  const double& get_as_float() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymFloat& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_EXPR) {
      nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) {
      nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymFloat& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_expr")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get<SymExpr>());
      nlohmann_json_t.tag_ = Tag::AS_EXPR;
      return;
    }
    if (nlohmann_json_j.contains("as_float")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_float").template get<double>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

class SymBool {
  struct Void {};

 public:
  enum class Tag {
    AS_EXPR, AS_BOOL
  };

 private:
  std::variant<Void, SymExpr, bool> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const SymExpr& get_as_expr() const {
    return std::get<1>(variant_);
  }

  const bool& get_as_bool() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymBool& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_EXPR) {
      nlohmann_json_j["as_expr"] = nlohmann_json_t.get_as_expr();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOL) {
      nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymBool& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_expr")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_expr").template get<SymExpr>());
      nlohmann_json_t.tag_ = Tag::AS_EXPR;
      return;
    }
    if (nlohmann_json_j.contains("as_bool")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_BOOL;
      return;
    }
  }
};

class TensorMeta {
 private:
  int64_t dtype;
  std::vector<SymInt> sizes;
  bool requires_grad;
  Device device;
  std::vector<SymInt> strides;
  SymInt storage_offset;
  int64_t layout;

 public:

  ScalarType get_dtype() const {
    return static_cast<ScalarType>(dtype);
  }

  const std::vector<SymInt>& get_sizes() const {
    return sizes;
  }

  const bool& get_requires_grad() const {
    return requires_grad;
  }

  const Device& get_device() const {
    return device;
  }

  const std::vector<SymInt>& get_strides() const {
    return strides;
  }

  const SymInt& get_storage_offset() const {
    return storage_offset;
  }

  Layout get_layout() const {
    return static_cast<Layout>(layout);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const TensorMeta& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, TensorMeta& nlohmann_json_t);
};

class SymIntArgument {
  struct Void {};

 public:
  enum class Tag {
    AS_NAME, AS_INT
  };

 private:
  std::variant<Void, std::string, int64_t> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const std::string& get_as_name() const {
    return std::get<1>(variant_);
  }

  const int64_t& get_as_int() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymIntArgument& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_NAME) {
      nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INT) {
      nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymIntArgument& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_name")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_NAME;
      return;
    }
    if (nlohmann_json_j.contains("as_int")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get<int64_t>());
      nlohmann_json_t.tag_ = Tag::AS_INT;
      return;
    }
  }
};

class SymFloatArgument {
  struct Void {};

 public:
  enum class Tag {
    AS_NAME, AS_FLOAT
  };

 private:
  std::variant<Void, std::string, double> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const std::string& get_as_name() const {
    return std::get<1>(variant_);
  }

  const double& get_as_float() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymFloatArgument& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_NAME) {
      nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) {
      nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymFloatArgument& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_name")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_NAME;
      return;
    }
    if (nlohmann_json_j.contains("as_float")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_float").template get<double>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

class SymBoolArgument {
  struct Void {};

 public:
  enum class Tag {
    AS_NAME, AS_BOOL
  };

 private:
  std::variant<Void, std::string, bool> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const std::string& get_as_name() const {
    return std::get<1>(variant_);
  }

  const bool& get_as_bool() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SymBoolArgument& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_NAME) {
      nlohmann_json_j["as_name"] = nlohmann_json_t.get_as_name();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOL) {
      nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, SymBoolArgument& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_name")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_name").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_NAME;
      return;
    }
    if (nlohmann_json_j.contains("as_bool")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_bool").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_BOOL;
      return;
    }
  }
};

class TensorArgument {
 private:
  std::string name;

 public:

  const std::string& get_name() const {
    return name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const TensorArgument& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, TensorArgument& nlohmann_json_t);
};

class TokenArgument {
 private:
  std::string name;

 public:

  const std::string& get_name() const {
    return name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const TokenArgument& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, TokenArgument& nlohmann_json_t);
};

class OptionalTensorArgument {
  struct Void {};

 public:
  enum class Tag {
    AS_TENSOR, AS_NONE
  };

 private:
  std::variant<Void, TensorArgument, bool> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const TensorArgument& get_as_tensor() const {
    return std::get<1>(variant_);
  }

  const bool& get_as_none() const {
    return std::get<2>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const OptionalTensorArgument& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_TENSOR) {
      nlohmann_json_j["as_tensor"] = nlohmann_json_t.get_as_tensor();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_NONE) {
      nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, OptionalTensorArgument& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_tensor")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_tensor").template get<TensorArgument>());
      nlohmann_json_t.tag_ = Tag::AS_TENSOR;
      return;
    }
    if (nlohmann_json_j.contains("as_none")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_none").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_NONE;
      return;
    }
  }
};

class GraphArgument {
 private:
  std::string name;
  ForwardRef<Graph> graph;

 public:

  const std::string& get_name() const {
    return name;
  }

  const ForwardRef<Graph>& get_graph() const {
    return graph;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const GraphArgument& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, GraphArgument& nlohmann_json_t);
};

class CustomObjArgument {
 private:
  std::string name;
  std::string class_fqn;

 public:

  const std::string& get_name() const {
    return name;
  }

  const std::string& get_class_fqn() const {
    return class_fqn;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const CustomObjArgument& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, CustomObjArgument& nlohmann_json_t);
};

class Argument {
  struct Void {};

 public:
  enum class Tag {
    AS_NONE, AS_TENSOR, AS_TENSORS, AS_INT, AS_INTS, AS_FLOAT, AS_FLOATS, AS_STRING, AS_STRINGS, AS_SYM_INT, AS_SYM_INTS, AS_SCALAR_TYPE, AS_MEMORY_FORMAT, AS_LAYOUT, AS_DEVICE, AS_BOOL, AS_BOOLS, AS_SYM_BOOL, AS_SYM_BOOLS, AS_GRAPH, AS_OPTIONAL_TENSORS, AS_CUSTOM_OBJ, AS_OPERATOR, AS_SYM_FLOAT, AS_SYM_FLOATS
  };

 private:
  std::variant<Void, bool, TensorArgument, std::vector<TensorArgument>, int64_t, std::vector<int64_t>, double, std::vector<double>, std::string, std::vector<std::string>, SymIntArgument, std::vector<SymIntArgument>, ScalarType, MemoryFormat, Layout, Device, bool, std::vector<bool>, SymBoolArgument, std::vector<SymBoolArgument>, GraphArgument, std::vector<OptionalTensorArgument>, CustomObjArgument, std::string, SymFloatArgument, std::vector<SymFloatArgument>> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const bool& get_as_none() const {
    return std::get<1>(variant_);
  }

  const TensorArgument& get_as_tensor() const {
    return std::get<2>(variant_);
  }

  const std::vector<TensorArgument>& get_as_tensors() const {
    return std::get<3>(variant_);
  }

  const int64_t& get_as_int() const {
    return std::get<4>(variant_);
  }

  const std::vector<int64_t>& get_as_ints() const {
    return std::get<5>(variant_);
  }

  const double& get_as_float() const {
    return std::get<6>(variant_);
  }

  const std::vector<double>& get_as_floats() const {
    return std::get<7>(variant_);
  }

  const std::string& get_as_string() const {
    return std::get<8>(variant_);
  }

  const std::vector<std::string>& get_as_strings() const {
    return std::get<9>(variant_);
  }

  const SymIntArgument& get_as_sym_int() const {
    return std::get<10>(variant_);
  }

  const std::vector<SymIntArgument>& get_as_sym_ints() const {
    return std::get<11>(variant_);
  }

  const ScalarType& get_as_scalar_type() const {
    return std::get<12>(variant_);
  }

  const MemoryFormat& get_as_memory_format() const {
    return std::get<13>(variant_);
  }

  const Layout& get_as_layout() const {
    return std::get<14>(variant_);
  }

  const Device& get_as_device() const {
    return std::get<15>(variant_);
  }

  const bool& get_as_bool() const {
    return std::get<16>(variant_);
  }

  const std::vector<bool>& get_as_bools() const {
    return std::get<17>(variant_);
  }

  const SymBoolArgument& get_as_sym_bool() const {
    return std::get<18>(variant_);
  }

  const std::vector<SymBoolArgument>& get_as_sym_bools() const {
    return std::get<19>(variant_);
  }

  const GraphArgument& get_as_graph() const {
    return std::get<20>(variant_);
  }

  const std::vector<OptionalTensorArgument>& get_as_optional_tensors() const {
    return std::get<21>(variant_);
  }

  const CustomObjArgument& get_as_custom_obj() const {
    return std::get<22>(variant_);
  }

  const std::string& get_as_operator() const {
    return std::get<23>(variant_);
  }

  const SymFloatArgument& get_as_sym_float() const {
    return std::get<24>(variant_);
  }

  const std::vector<SymFloatArgument>& get_as_sym_floats() const {
    return std::get<25>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const Argument& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_NONE) {
      nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_TENSOR) {
      nlohmann_json_j["as_tensor"] = nlohmann_json_t.get_as_tensor();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_TENSORS) {
      nlohmann_json_j["as_tensors"] = nlohmann_json_t.get_as_tensors();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INT) {
      nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INTS) {
      nlohmann_json_j["as_ints"] = nlohmann_json_t.get_as_ints();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) {
      nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOATS) {
      nlohmann_json_j["as_floats"] = nlohmann_json_t.get_as_floats();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_STRING) {
      nlohmann_json_j["as_string"] = nlohmann_json_t.get_as_string();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_STRINGS) {
      nlohmann_json_j["as_strings"] = nlohmann_json_t.get_as_strings();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_INT) {
      nlohmann_json_j["as_sym_int"] = nlohmann_json_t.get_as_sym_int();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_INTS) {
      nlohmann_json_j["as_sym_ints"] = nlohmann_json_t.get_as_sym_ints();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SCALAR_TYPE) {
      nlohmann_json_j["as_scalar_type"] = nlohmann_json_t.get_as_scalar_type();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_MEMORY_FORMAT) {
      nlohmann_json_j["as_memory_format"] = nlohmann_json_t.get_as_memory_format();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_LAYOUT) {
      nlohmann_json_j["as_layout"] = nlohmann_json_t.get_as_layout();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_DEVICE) {
      nlohmann_json_j["as_device"] = nlohmann_json_t.get_as_device();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOL) {
      nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOLS) {
      nlohmann_json_j["as_bools"] = nlohmann_json_t.get_as_bools();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_BOOL) {
      nlohmann_json_j["as_sym_bool"] = nlohmann_json_t.get_as_sym_bool();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_BOOLS) {
      nlohmann_json_j["as_sym_bools"] = nlohmann_json_t.get_as_sym_bools();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_GRAPH) {
      nlohmann_json_j["as_graph"] = nlohmann_json_t.get_as_graph();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_OPTIONAL_TENSORS) {
      nlohmann_json_j["as_optional_tensors"] = nlohmann_json_t.get_as_optional_tensors();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_CUSTOM_OBJ) {
      nlohmann_json_j["as_custom_obj"] = nlohmann_json_t.get_as_custom_obj();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_OPERATOR) {
      nlohmann_json_j["as_operator"] = nlohmann_json_t.get_as_operator();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_FLOAT) {
      nlohmann_json_j["as_sym_float"] = nlohmann_json_t.get_as_sym_float();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_SYM_FLOATS) {
      nlohmann_json_j["as_sym_floats"] = nlohmann_json_t.get_as_sym_floats();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, Argument& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_none")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_none").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_NONE;
      return;
    }
    if (nlohmann_json_j.contains("as_tensor")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_tensor").template get<TensorArgument>());
      nlohmann_json_t.tag_ = Tag::AS_TENSOR;
      return;
    }
    if (nlohmann_json_j.contains("as_tensors")) {
      nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_tensors").template get<std::vector<TensorArgument>>());
      nlohmann_json_t.tag_ = Tag::AS_TENSORS;
      return;
    }
    if (nlohmann_json_j.contains("as_int")) {
      nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("as_int").template get<int64_t>());
      nlohmann_json_t.tag_ = Tag::AS_INT;
      return;
    }
    if (nlohmann_json_j.contains("as_ints")) {
      nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("as_ints").template get<std::vector<int64_t>>());
      nlohmann_json_t.tag_ = Tag::AS_INTS;
      return;
    }
    if (nlohmann_json_j.contains("as_float")) {
      nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("as_float").template get<double>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
    if (nlohmann_json_j.contains("as_floats")) {
      nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("as_floats").template get<std::vector<double>>());
      nlohmann_json_t.tag_ = Tag::AS_FLOATS;
      return;
    }
    if (nlohmann_json_j.contains("as_string")) {
      nlohmann_json_t.variant_.emplace<8>(nlohmann_json_j.at("as_string").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_STRING;
      return;
    }
    if (nlohmann_json_j.contains("as_strings")) {
      nlohmann_json_t.variant_.emplace<9>(nlohmann_json_j.at("as_strings").template get<std::vector<std::string>>());
      nlohmann_json_t.tag_ = Tag::AS_STRINGS;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_int")) {
      nlohmann_json_t.variant_.emplace<10>(nlohmann_json_j.at("as_sym_int").template get<SymIntArgument>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_INT;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_ints")) {
      nlohmann_json_t.variant_.emplace<11>(nlohmann_json_j.at("as_sym_ints").template get<std::vector<SymIntArgument>>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_INTS;
      return;
    }
    if (nlohmann_json_j.contains("as_scalar_type")) {
      nlohmann_json_t.variant_.emplace<12>(nlohmann_json_j.at("as_scalar_type").template get<ScalarType>());
      nlohmann_json_t.tag_ = Tag::AS_SCALAR_TYPE;
      return;
    }
    if (nlohmann_json_j.contains("as_memory_format")) {
      nlohmann_json_t.variant_.emplace<13>(nlohmann_json_j.at("as_memory_format").template get<MemoryFormat>());
      nlohmann_json_t.tag_ = Tag::AS_MEMORY_FORMAT;
      return;
    }
    if (nlohmann_json_j.contains("as_layout")) {
      nlohmann_json_t.variant_.emplace<14>(nlohmann_json_j.at("as_layout").template get<Layout>());
      nlohmann_json_t.tag_ = Tag::AS_LAYOUT;
      return;
    }
    if (nlohmann_json_j.contains("as_device")) {
      nlohmann_json_t.variant_.emplace<15>(nlohmann_json_j.at("as_device").template get<Device>());
      nlohmann_json_t.tag_ = Tag::AS_DEVICE;
      return;
    }
    if (nlohmann_json_j.contains("as_bool")) {
      nlohmann_json_t.variant_.emplace<16>(nlohmann_json_j.at("as_bool").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_BOOL;
      return;
    }
    if (nlohmann_json_j.contains("as_bools")) {
      nlohmann_json_t.variant_.emplace<17>(nlohmann_json_j.at("as_bools").template get<std::vector<bool>>());
      nlohmann_json_t.tag_ = Tag::AS_BOOLS;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_bool")) {
      nlohmann_json_t.variant_.emplace<18>(nlohmann_json_j.at("as_sym_bool").template get<SymBoolArgument>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_BOOL;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_bools")) {
      nlohmann_json_t.variant_.emplace<19>(nlohmann_json_j.at("as_sym_bools").template get<std::vector<SymBoolArgument>>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_BOOLS;
      return;
    }
    if (nlohmann_json_j.contains("as_graph")) {
      nlohmann_json_t.variant_.emplace<20>(nlohmann_json_j.at("as_graph").template get<GraphArgument>());
      nlohmann_json_t.tag_ = Tag::AS_GRAPH;
      return;
    }
    if (nlohmann_json_j.contains("as_optional_tensors")) {
      nlohmann_json_t.variant_.emplace<21>(nlohmann_json_j.at("as_optional_tensors").template get<std::vector<OptionalTensorArgument>>());
      nlohmann_json_t.tag_ = Tag::AS_OPTIONAL_TENSORS;
      return;
    }
    if (nlohmann_json_j.contains("as_custom_obj")) {
      nlohmann_json_t.variant_.emplace<22>(nlohmann_json_j.at("as_custom_obj").template get<CustomObjArgument>());
      nlohmann_json_t.tag_ = Tag::AS_CUSTOM_OBJ;
      return;
    }
    if (nlohmann_json_j.contains("as_operator")) {
      nlohmann_json_t.variant_.emplace<23>(nlohmann_json_j.at("as_operator").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_OPERATOR;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_float")) {
      nlohmann_json_t.variant_.emplace<24>(nlohmann_json_j.at("as_sym_float").template get<SymFloatArgument>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_FLOAT;
      return;
    }
    if (nlohmann_json_j.contains("as_sym_floats")) {
      nlohmann_json_t.variant_.emplace<25>(nlohmann_json_j.at("as_sym_floats").template get<std::vector<SymFloatArgument>>());
      nlohmann_json_t.tag_ = Tag::AS_SYM_FLOATS;
      return;
    }
  }
};

class NamedArgument {
 private:
  std::string name;
  Argument arg;

 public:

  const std::string& get_name() const {
    return name;
  }

  const Argument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const NamedArgument& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, NamedArgument& nlohmann_json_t);
};

class Node {
 private:
  std::string target;
  std::vector<NamedArgument> inputs;
  std::vector<Argument> outputs;
  std::unordered_map<std::string, std::string> metadata;

 public:

  const std::string& get_target() const {
    return target;
  }

  const std::vector<NamedArgument>& get_inputs() const {
    return inputs;
  }

  const std::vector<Argument>& get_outputs() const {
    return outputs;
  }

  const std::unordered_map<std::string, std::string>& get_metadata() const {
    return metadata;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const Node& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, Node& nlohmann_json_t);
};

class Graph {
 private:
  std::vector<Argument> inputs;
  std::vector<Argument> outputs;
  std::vector<Node> nodes;
  std::unordered_map<std::string, TensorMeta> tensor_values;
  std::unordered_map<std::string, SymInt> sym_int_values;
  std::unordered_map<std::string, SymBool> sym_bool_values;
  bool is_single_tensor_return = false;
  std::unordered_map<std::string, CustomObjArgument> custom_obj_values = {};
  std::unordered_map<std::string, SymFloat> sym_float_values = {};

 public:

  const std::vector<Argument>& get_inputs() const {
    return inputs;
  }

  const std::vector<Argument>& get_outputs() const {
    return outputs;
  }

  const std::vector<Node>& get_nodes() const {
    return nodes;
  }

  const std::unordered_map<std::string, TensorMeta>& get_tensor_values() const {
    return tensor_values;
  }

  const std::unordered_map<std::string, SymInt>& get_sym_int_values() const {
    return sym_int_values;
  }

  const std::unordered_map<std::string, SymBool>& get_sym_bool_values() const {
    return sym_bool_values;
  }

  const bool& get_is_single_tensor_return() const {
    return is_single_tensor_return;
  }

  const std::unordered_map<std::string, CustomObjArgument>& get_custom_obj_values() const {
    return custom_obj_values;
  }

  const std::unordered_map<std::string, SymFloat>& get_sym_float_values() const {
    return sym_float_values;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const Graph& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, Graph& nlohmann_json_t);
};

class UserInputSpec {
 private:
  Argument arg;

 public:

  const Argument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const UserInputSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, UserInputSpec& nlohmann_json_t);
};

class ConstantValue {
  struct Void {};

 public:
  enum class Tag {
    AS_NONE, AS_INT, AS_FLOAT, AS_STRING, AS_BOOL
  };

 private:
  std::variant<Void, bool, int64_t, double, std::string, bool> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const bool& get_as_none() const {
    return std::get<1>(variant_);
  }

  const int64_t& get_as_int() const {
    return std::get<2>(variant_);
  }

  const double& get_as_float() const {
    return std::get<3>(variant_);
  }

  const std::string& get_as_string() const {
    return std::get<4>(variant_);
  }

  const bool& get_as_bool() const {
    return std::get<5>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const ConstantValue& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::AS_NONE) {
      nlohmann_json_j["as_none"] = nlohmann_json_t.get_as_none();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INT) {
      nlohmann_json_j["as_int"] = nlohmann_json_t.get_as_int();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_FLOAT) {
      nlohmann_json_j["as_float"] = nlohmann_json_t.get_as_float();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_STRING) {
      nlohmann_json_j["as_string"] = nlohmann_json_t.get_as_string();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_BOOL) {
      nlohmann_json_j["as_bool"] = nlohmann_json_t.get_as_bool();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, ConstantValue& nlohmann_json_t) {

    if (nlohmann_json_j.contains("as_none")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("as_none").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_NONE;
      return;
    }
    if (nlohmann_json_j.contains("as_int")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("as_int").template get<int64_t>());
      nlohmann_json_t.tag_ = Tag::AS_INT;
      return;
    }
    if (nlohmann_json_j.contains("as_float")) {
      nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("as_float").template get<double>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
    if (nlohmann_json_j.contains("as_string")) {
      nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("as_string").template get<std::string>());
      nlohmann_json_t.tag_ = Tag::AS_STRING;
      return;
    }
    if (nlohmann_json_j.contains("as_bool")) {
      nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("as_bool").template get<bool>());
      nlohmann_json_t.tag_ = Tag::AS_BOOL;
      return;
    }
  }
};

class InputToConstantInputSpec {
 private:
  std::string name;
  ConstantValue value;

 public:

  const std::string& get_name() const {
    return name;
  }

  const ConstantValue& get_value() const {
    return value;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputToConstantInputSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputToConstantInputSpec& nlohmann_json_t);
};

class InputToParameterSpec {
 private:
  TensorArgument arg;
  std::string parameter_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_parameter_name() const {
    return parameter_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputToParameterSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputToParameterSpec& nlohmann_json_t);
};

class InputToBufferSpec {
 private:
  TensorArgument arg;
  std::string buffer_name;
  bool persistent;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_buffer_name() const {
    return buffer_name;
  }

  const bool& get_persistent() const {
    return persistent;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputToBufferSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputToBufferSpec& nlohmann_json_t);
};

class InputToTensorConstantSpec {
 private:
  TensorArgument arg;
  std::string tensor_constant_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_tensor_constant_name() const {
    return tensor_constant_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputToTensorConstantSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputToTensorConstantSpec& nlohmann_json_t);
};

class InputToCustomObjSpec {
 private:
  CustomObjArgument arg;
  std::string custom_obj_name;

 public:

  const CustomObjArgument& get_arg() const {
    return arg;
  }

  const std::string& get_custom_obj_name() const {
    return custom_obj_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputToCustomObjSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputToCustomObjSpec& nlohmann_json_t);
};

class InputTokenSpec {
 private:
  TokenArgument arg;

 public:

  const TokenArgument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputTokenSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, InputTokenSpec& nlohmann_json_t);
};

class InputSpec {
  struct Void {};

 public:
  enum class Tag {
    USER_INPUT, PARAMETER, BUFFER, TENSOR_CONSTANT, CUSTOM_OBJ, TOKEN, CONSTANT_INPUT
  };

 private:
  std::variant<Void, UserInputSpec, InputToParameterSpec, InputToBufferSpec, InputToTensorConstantSpec, InputToCustomObjSpec, InputTokenSpec, InputToConstantInputSpec> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const UserInputSpec& get_user_input() const {
    return std::get<1>(variant_);
  }

  const InputToParameterSpec& get_parameter() const {
    return std::get<2>(variant_);
  }

  const InputToBufferSpec& get_buffer() const {
    return std::get<3>(variant_);
  }

  const InputToTensorConstantSpec& get_tensor_constant() const {
    return std::get<4>(variant_);
  }

  const InputToCustomObjSpec& get_custom_obj() const {
    return std::get<5>(variant_);
  }

  const InputTokenSpec& get_token() const {
    return std::get<6>(variant_);
  }

  const InputToConstantInputSpec& get_constant_input() const {
    return std::get<7>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const InputSpec& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::USER_INPUT) {
      nlohmann_json_j["user_input"] = nlohmann_json_t.get_user_input();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::PARAMETER) {
      nlohmann_json_j["parameter"] = nlohmann_json_t.get_parameter();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::BUFFER) {
      nlohmann_json_j["buffer"] = nlohmann_json_t.get_buffer();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::TENSOR_CONSTANT) {
      nlohmann_json_j["tensor_constant"] = nlohmann_json_t.get_tensor_constant();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::CUSTOM_OBJ) {
      nlohmann_json_j["custom_obj"] = nlohmann_json_t.get_custom_obj();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::TOKEN) {
      nlohmann_json_j["token"] = nlohmann_json_t.get_token();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::CONSTANT_INPUT) {
      nlohmann_json_j["constant_input"] = nlohmann_json_t.get_constant_input();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, InputSpec& nlohmann_json_t) {

    if (nlohmann_json_j.contains("user_input")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("user_input").template get<UserInputSpec>());
      nlohmann_json_t.tag_ = Tag::USER_INPUT;
      return;
    }
    if (nlohmann_json_j.contains("parameter")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("parameter").template get<InputToParameterSpec>());
      nlohmann_json_t.tag_ = Tag::PARAMETER;
      return;
    }
    if (nlohmann_json_j.contains("buffer")) {
      nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("buffer").template get<InputToBufferSpec>());
      nlohmann_json_t.tag_ = Tag::BUFFER;
      return;
    }
    if (nlohmann_json_j.contains("tensor_constant")) {
      nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("tensor_constant").template get<InputToTensorConstantSpec>());
      nlohmann_json_t.tag_ = Tag::TENSOR_CONSTANT;
      return;
    }
    if (nlohmann_json_j.contains("custom_obj")) {
      nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("custom_obj").template get<InputToCustomObjSpec>());
      nlohmann_json_t.tag_ = Tag::CUSTOM_OBJ;
      return;
    }
    if (nlohmann_json_j.contains("token")) {
      nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("token").template get<InputTokenSpec>());
      nlohmann_json_t.tag_ = Tag::TOKEN;
      return;
    }
    if (nlohmann_json_j.contains("constant_input")) {
      nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("constant_input").template get<InputToConstantInputSpec>());
      nlohmann_json_t.tag_ = Tag::CONSTANT_INPUT;
      return;
    }
  }
};

class UserOutputSpec {
 private:
  Argument arg;

 public:

  const Argument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const UserOutputSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, UserOutputSpec& nlohmann_json_t);
};

class LossOutputSpec {
 private:
  TensorArgument arg;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const LossOutputSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, LossOutputSpec& nlohmann_json_t);
};

class BufferMutationSpec {
 private:
  TensorArgument arg;
  std::string buffer_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_buffer_name() const {
    return buffer_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const BufferMutationSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, BufferMutationSpec& nlohmann_json_t);
};

class GradientToParameterSpec {
 private:
  TensorArgument arg;
  std::string parameter_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_parameter_name() const {
    return parameter_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const GradientToParameterSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, GradientToParameterSpec& nlohmann_json_t);
};

class GradientToUserInputSpec {
 private:
  TensorArgument arg;
  std::string user_input_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_user_input_name() const {
    return user_input_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const GradientToUserInputSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, GradientToUserInputSpec& nlohmann_json_t);
};

class UserInputMutationSpec {
 private:
  TensorArgument arg;
  std::string user_input_name;

 public:

  const TensorArgument& get_arg() const {
    return arg;
  }

  const std::string& get_user_input_name() const {
    return user_input_name;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const UserInputMutationSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, UserInputMutationSpec& nlohmann_json_t);
};

class OutputTokenSpec {
 private:
  TokenArgument arg;

 public:

  const TokenArgument& get_arg() const {
    return arg;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const OutputTokenSpec& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, OutputTokenSpec& nlohmann_json_t);
};

class OutputSpec {
  struct Void {};

 public:
  enum class Tag {
    USER_OUTPUT, LOSS_OUTPUT, BUFFER_MUTATION, GRADIENT_TO_PARAMETER, GRADIENT_TO_USER_INPUT, USER_INPUT_MUTATION, TOKEN
  };

 private:
  std::variant<Void, UserOutputSpec, LossOutputSpec, BufferMutationSpec, GradientToParameterSpec, GradientToUserInputSpec, UserInputMutationSpec, OutputTokenSpec> variant_;
  Tag tag_;

 public:
  Tag tag() const {
    return tag_;
  }

  const UserOutputSpec& get_user_output() const {
    return std::get<1>(variant_);
  }

  const LossOutputSpec& get_loss_output() const {
    return std::get<2>(variant_);
  }

  const BufferMutationSpec& get_buffer_mutation() const {
    return std::get<3>(variant_);
  }

  const GradientToParameterSpec& get_gradient_to_parameter() const {
    return std::get<4>(variant_);
  }

  const GradientToUserInputSpec& get_gradient_to_user_input() const {
    return std::get<5>(variant_);
  }

  const UserInputMutationSpec& get_user_input_mutation() const {
    return std::get<6>(variant_);
  }

  const OutputTokenSpec& get_token() const {
    return std::get<7>(variant_);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const OutputSpec& nlohmann_json_t) {

    if (nlohmann_json_t.tag_ == Tag::USER_OUTPUT) {
      nlohmann_json_j["user_output"] = nlohmann_json_t.get_user_output();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::LOSS_OUTPUT) {
      nlohmann_json_j["loss_output"] = nlohmann_json_t.get_loss_output();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::BUFFER_MUTATION) {
      nlohmann_json_j["buffer_mutation"] = nlohmann_json_t.get_buffer_mutation();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::GRADIENT_TO_PARAMETER) {
      nlohmann_json_j["gradient_to_parameter"] = nlohmann_json_t.get_gradient_to_parameter();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::GRADIENT_TO_USER_INPUT) {
      nlohmann_json_j["gradient_to_user_input"] = nlohmann_json_t.get_gradient_to_user_input();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::USER_INPUT_MUTATION) {
      nlohmann_json_j["user_input_mutation"] = nlohmann_json_t.get_user_input_mutation();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::TOKEN) {
      nlohmann_json_j["token"] = nlohmann_json_t.get_token();
      return;
    }
  }

  friend void from_json(const nlohmann::json& nlohmann_json_j, OutputSpec& nlohmann_json_t) {

    if (nlohmann_json_j.contains("user_output")) {
      nlohmann_json_t.variant_.emplace<1>(nlohmann_json_j.at("user_output").template get<UserOutputSpec>());
      nlohmann_json_t.tag_ = Tag::USER_OUTPUT;
      return;
    }
    if (nlohmann_json_j.contains("loss_output")) {
      nlohmann_json_t.variant_.emplace<2>(nlohmann_json_j.at("loss_output").template get<LossOutputSpec>());
      nlohmann_json_t.tag_ = Tag::LOSS_OUTPUT;
      return;
    }
    if (nlohmann_json_j.contains("buffer_mutation")) {
      nlohmann_json_t.variant_.emplace<3>(nlohmann_json_j.at("buffer_mutation").template get<BufferMutationSpec>());
      nlohmann_json_t.tag_ = Tag::BUFFER_MUTATION;
      return;
    }
    if (nlohmann_json_j.contains("gradient_to_parameter")) {
      nlohmann_json_t.variant_.emplace<4>(nlohmann_json_j.at("gradient_to_parameter").template get<GradientToParameterSpec>());
      nlohmann_json_t.tag_ = Tag::GRADIENT_TO_PARAMETER;
      return;
    }
    if (nlohmann_json_j.contains("gradient_to_user_input")) {
      nlohmann_json_t.variant_.emplace<5>(nlohmann_json_j.at("gradient_to_user_input").template get<GradientToUserInputSpec>());
      nlohmann_json_t.tag_ = Tag::GRADIENT_TO_USER_INPUT;
      return;
    }
    if (nlohmann_json_j.contains("user_input_mutation")) {
      nlohmann_json_t.variant_.emplace<6>(nlohmann_json_j.at("user_input_mutation").template get<UserInputMutationSpec>());
      nlohmann_json_t.tag_ = Tag::USER_INPUT_MUTATION;
      return;
    }
    if (nlohmann_json_j.contains("token")) {
      nlohmann_json_t.variant_.emplace<7>(nlohmann_json_j.at("token").template get<OutputTokenSpec>());
      nlohmann_json_t.tag_ = Tag::TOKEN;
      return;
    }
  }
};

class GraphSignature {
 private:
  std::vector<InputSpec> input_specs;
  std::vector<OutputSpec> output_specs;

 public:

  const std::vector<InputSpec>& get_input_specs() const {
    return input_specs;
  }

  const std::vector<OutputSpec>& get_output_specs() const {
    return output_specs;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const GraphSignature& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, GraphSignature& nlohmann_json_t);
};

class RangeConstraint {
 private:
  std::optional<int64_t> min_val;
  std::optional<int64_t> max_val;

 public:

  const std::optional<int64_t>& get_min_val() const {
    return min_val;
  }

  const std::optional<int64_t>& get_max_val() const {
    return max_val;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const RangeConstraint& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, RangeConstraint& nlohmann_json_t);
};

class ModuleCallSignature {
 private:
  std::vector<Argument> inputs;
  std::vector<Argument> outputs;
  std::string in_spec;
  std::string out_spec;
  std::optional<std::vector<std::string>> forward_arg_names = std::nullopt;

 public:

  const std::vector<Argument>& get_inputs() const {
    return inputs;
  }

  const std::vector<Argument>& get_outputs() const {
    return outputs;
  }

  const std::string& get_in_spec() const {
    return in_spec;
  }

  const std::string& get_out_spec() const {
    return out_spec;
  }

  const std::optional<std::vector<std::string>>& get_forward_arg_names() const {
    return forward_arg_names;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallSignature& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallSignature& nlohmann_json_t);
};

class ModuleCallEntry {
 private:
  std::string fqn;
  std::optional<ModuleCallSignature> signature = std::nullopt;

 public:

  const std::string& get_fqn() const {
    return fqn;
  }

  const std::optional<ModuleCallSignature>& get_signature() const {
    return signature;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallEntry& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallEntry& nlohmann_json_t);
};

class GraphModule {
 private:
  Graph graph;
  GraphSignature signature;
  std::vector<ModuleCallEntry> module_call_graph;
  std::unordered_map<std::string, std::string> metadata = {};

 public:

  const Graph& get_graph() const {
    return graph;
  }

  const GraphSignature& get_signature() const {
    return signature;
  }

  const std::vector<ModuleCallEntry>& get_module_call_graph() const {
    return module_call_graph;
  }

  const std::unordered_map<std::string, std::string>& get_metadata() const {
    return metadata;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const GraphModule& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, GraphModule& nlohmann_json_t);
};

class SchemaVersion {
 private:
  int64_t major;
  int64_t minor;

 public:

  const int64_t& get_major() const {
    return major;
  }

  const int64_t& get_minor() const {
    return minor;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const SchemaVersion& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, SchemaVersion& nlohmann_json_t);
};

class ExportedProgram {
 private:
  GraphModule graph_module;
  std::unordered_map<std::string, int64_t> opset_version;
  std::unordered_map<std::string, RangeConstraint> range_constraints;
  SchemaVersion schema_version;
  std::vector<std::string> verifiers = {};
  std::string torch_version = "<=2.4";

 public:

  const GraphModule& get_graph_module() const {
    return graph_module;
  }

  const std::unordered_map<std::string, int64_t>& get_opset_version() const {
    return opset_version;
  }

  const std::unordered_map<std::string, RangeConstraint>& get_range_constraints() const {
    return range_constraints;
  }

  const SchemaVersion& get_schema_version() const {
    return schema_version;
  }

  const std::vector<std::string>& get_verifiers() const {
    return verifiers;
  }

  const std::string& get_torch_version() const {
    return torch_version;
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const ExportedProgram& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, ExportedProgram& nlohmann_json_t);
};

inline void to_json(nlohmann::json& nlohmann_json_j, const BufferMutationSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["buffer_name"] = nlohmann_json_t.buffer_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, BufferMutationSpec& nlohmann_json_t) {
  BufferMutationSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.buffer_name = nlohmann_json_j.value("buffer_name", nlohmann_json_default_obj.buffer_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const CustomObjArgument& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
  nlohmann_json_j["class_fqn"] = nlohmann_json_t.class_fqn;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, CustomObjArgument& nlohmann_json_t) {
  CustomObjArgument nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
  nlohmann_json_t.class_fqn = nlohmann_json_j.value("class_fqn", nlohmann_json_default_obj.class_fqn);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const Device& nlohmann_json_t) {
  nlohmann_json_j["type"] = nlohmann_json_t.type;
  nlohmann_json_j["index"] = nlohmann_json_t.index;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, Device& nlohmann_json_t) {
  Device nlohmann_json_default_obj;
  nlohmann_json_t.type = nlohmann_json_j.value("type", nlohmann_json_default_obj.type);
  nlohmann_json_t.index = nlohmann_json_j.value("index", nlohmann_json_default_obj.index);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const ExportedProgram& nlohmann_json_t) {
  nlohmann_json_j["graph_module"] = nlohmann_json_t.graph_module;
  nlohmann_json_j["opset_version"] = nlohmann_json_t.opset_version;
  nlohmann_json_j["range_constraints"] = nlohmann_json_t.range_constraints;
  nlohmann_json_j["schema_version"] = nlohmann_json_t.schema_version;
  nlohmann_json_j["verifiers"] = nlohmann_json_t.verifiers;
  nlohmann_json_j["torch_version"] = nlohmann_json_t.torch_version;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, ExportedProgram& nlohmann_json_t) {
  ExportedProgram nlohmann_json_default_obj;
  nlohmann_json_t.graph_module = nlohmann_json_j.value("graph_module", nlohmann_json_default_obj.graph_module);
  nlohmann_json_t.opset_version = nlohmann_json_j.value("opset_version", nlohmann_json_default_obj.opset_version);
  nlohmann_json_t.range_constraints = nlohmann_json_j.value("range_constraints", nlohmann_json_default_obj.range_constraints);
  nlohmann_json_t.schema_version = nlohmann_json_j.value("schema_version", nlohmann_json_default_obj.schema_version);
  nlohmann_json_t.verifiers = nlohmann_json_j.value("verifiers", nlohmann_json_default_obj.verifiers);
  nlohmann_json_t.torch_version = nlohmann_json_j.value("torch_version", nlohmann_json_default_obj.torch_version);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const GradientToParameterSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["parameter_name"] = nlohmann_json_t.parameter_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, GradientToParameterSpec& nlohmann_json_t) {
  GradientToParameterSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.parameter_name = nlohmann_json_j.value("parameter_name", nlohmann_json_default_obj.parameter_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const GradientToUserInputSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["user_input_name"] = nlohmann_json_t.user_input_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, GradientToUserInputSpec& nlohmann_json_t) {
  GradientToUserInputSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.user_input_name = nlohmann_json_j.value("user_input_name", nlohmann_json_default_obj.user_input_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const Graph& nlohmann_json_t) {
  nlohmann_json_j["inputs"] = nlohmann_json_t.inputs;
  nlohmann_json_j["outputs"] = nlohmann_json_t.outputs;
  nlohmann_json_j["nodes"] = nlohmann_json_t.nodes;
  nlohmann_json_j["tensor_values"] = nlohmann_json_t.tensor_values;
  nlohmann_json_j["sym_int_values"] = nlohmann_json_t.sym_int_values;
  nlohmann_json_j["sym_bool_values"] = nlohmann_json_t.sym_bool_values;
  nlohmann_json_j["is_single_tensor_return"] = nlohmann_json_t.is_single_tensor_return;
  nlohmann_json_j["custom_obj_values"] = nlohmann_json_t.custom_obj_values;
  nlohmann_json_j["sym_float_values"] = nlohmann_json_t.sym_float_values;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, Graph& nlohmann_json_t) {
  Graph nlohmann_json_default_obj;
  nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs);
  nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs);
  nlohmann_json_t.nodes = nlohmann_json_j.value("nodes", nlohmann_json_default_obj.nodes);
  nlohmann_json_t.tensor_values = nlohmann_json_j.value("tensor_values", nlohmann_json_default_obj.tensor_values);
  nlohmann_json_t.sym_int_values = nlohmann_json_j.value("sym_int_values", nlohmann_json_default_obj.sym_int_values);
  nlohmann_json_t.sym_bool_values = nlohmann_json_j.value("sym_bool_values", nlohmann_json_default_obj.sym_bool_values);
  nlohmann_json_t.is_single_tensor_return = nlohmann_json_j.value("is_single_tensor_return", nlohmann_json_default_obj.is_single_tensor_return);
  nlohmann_json_t.custom_obj_values = nlohmann_json_j.value("custom_obj_values", nlohmann_json_default_obj.custom_obj_values);
  nlohmann_json_t.sym_float_values = nlohmann_json_j.value("sym_float_values", nlohmann_json_default_obj.sym_float_values);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const GraphArgument& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
  nlohmann_json_j["graph"] = nlohmann_json_t.graph;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, GraphArgument& nlohmann_json_t) {
  GraphArgument nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
  nlohmann_json_t.graph = nlohmann_json_j.value("graph", nlohmann_json_default_obj.graph);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const GraphModule& nlohmann_json_t) {
  nlohmann_json_j["graph"] = nlohmann_json_t.graph;
  nlohmann_json_j["signature"] = nlohmann_json_t.signature;
  nlohmann_json_j["module_call_graph"] = nlohmann_json_t.module_call_graph;
  nlohmann_json_j["metadata"] = nlohmann_json_t.metadata;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, GraphModule& nlohmann_json_t) {
  GraphModule nlohmann_json_default_obj;
  nlohmann_json_t.graph = nlohmann_json_j.value("graph", nlohmann_json_default_obj.graph);
  nlohmann_json_t.signature = nlohmann_json_j.value("signature", nlohmann_json_default_obj.signature);
  nlohmann_json_t.module_call_graph = nlohmann_json_j.value("module_call_graph", nlohmann_json_default_obj.module_call_graph);
  nlohmann_json_t.metadata = nlohmann_json_j.value("metadata", nlohmann_json_default_obj.metadata);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const GraphSignature& nlohmann_json_t) {
  nlohmann_json_j["input_specs"] = nlohmann_json_t.input_specs;
  nlohmann_json_j["output_specs"] = nlohmann_json_t.output_specs;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, GraphSignature& nlohmann_json_t) {
  GraphSignature nlohmann_json_default_obj;
  nlohmann_json_t.input_specs = nlohmann_json_j.value("input_specs", nlohmann_json_default_obj.input_specs);
  nlohmann_json_t.output_specs = nlohmann_json_j.value("output_specs", nlohmann_json_default_obj.output_specs);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputToBufferSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["buffer_name"] = nlohmann_json_t.buffer_name;
  nlohmann_json_j["persistent"] = nlohmann_json_t.persistent;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputToBufferSpec& nlohmann_json_t) {
  InputToBufferSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.buffer_name = nlohmann_json_j.value("buffer_name", nlohmann_json_default_obj.buffer_name);
  nlohmann_json_t.persistent = nlohmann_json_j.value("persistent", nlohmann_json_default_obj.persistent);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputToConstantInputSpec& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
  nlohmann_json_j["value"] = nlohmann_json_t.value;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputToConstantInputSpec& nlohmann_json_t) {
  InputToConstantInputSpec nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
  nlohmann_json_t.value = nlohmann_json_j.value("value", nlohmann_json_default_obj.value);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputToCustomObjSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["custom_obj_name"] = nlohmann_json_t.custom_obj_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputToCustomObjSpec& nlohmann_json_t) {
  InputToCustomObjSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.custom_obj_name = nlohmann_json_j.value("custom_obj_name", nlohmann_json_default_obj.custom_obj_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputToParameterSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["parameter_name"] = nlohmann_json_t.parameter_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputToParameterSpec& nlohmann_json_t) {
  InputToParameterSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.parameter_name = nlohmann_json_j.value("parameter_name", nlohmann_json_default_obj.parameter_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputToTensorConstantSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["tensor_constant_name"] = nlohmann_json_t.tensor_constant_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputToTensorConstantSpec& nlohmann_json_t) {
  InputToTensorConstantSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.tensor_constant_name = nlohmann_json_j.value("tensor_constant_name", nlohmann_json_default_obj.tensor_constant_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const InputTokenSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, InputTokenSpec& nlohmann_json_t) {
  InputTokenSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const LossOutputSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, LossOutputSpec& nlohmann_json_t) {
  LossOutputSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallEntry& nlohmann_json_t) {
  nlohmann_json_j["fqn"] = nlohmann_json_t.fqn;
  nlohmann_json_j["signature"] = nlohmann_json_t.signature;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallEntry& nlohmann_json_t) {
  ModuleCallEntry nlohmann_json_default_obj;
  nlohmann_json_t.fqn = nlohmann_json_j.value("fqn", nlohmann_json_default_obj.fqn);
  nlohmann_json_t.signature = nlohmann_json_j.value("signature", nlohmann_json_default_obj.signature);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const ModuleCallSignature& nlohmann_json_t) {
  nlohmann_json_j["inputs"] = nlohmann_json_t.inputs;
  nlohmann_json_j["outputs"] = nlohmann_json_t.outputs;
  nlohmann_json_j["in_spec"] = nlohmann_json_t.in_spec;
  nlohmann_json_j["out_spec"] = nlohmann_json_t.out_spec;
  nlohmann_json_j["forward_arg_names"] = nlohmann_json_t.forward_arg_names;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, ModuleCallSignature& nlohmann_json_t) {
  ModuleCallSignature nlohmann_json_default_obj;
  nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs);
  nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs);
  nlohmann_json_t.in_spec = nlohmann_json_j.value("in_spec", nlohmann_json_default_obj.in_spec);
  nlohmann_json_t.out_spec = nlohmann_json_j.value("out_spec", nlohmann_json_default_obj.out_spec);
  nlohmann_json_t.forward_arg_names = nlohmann_json_j.value("forward_arg_names", nlohmann_json_default_obj.forward_arg_names);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const NamedArgument& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, NamedArgument& nlohmann_json_t) {
  NamedArgument nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const Node& nlohmann_json_t) {
  nlohmann_json_j["target"] = nlohmann_json_t.target;
  nlohmann_json_j["inputs"] = nlohmann_json_t.inputs;
  nlohmann_json_j["outputs"] = nlohmann_json_t.outputs;
  nlohmann_json_j["metadata"] = nlohmann_json_t.metadata;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, Node& nlohmann_json_t) {
  Node nlohmann_json_default_obj;
  nlohmann_json_t.target = nlohmann_json_j.value("target", nlohmann_json_default_obj.target);
  nlohmann_json_t.inputs = nlohmann_json_j.value("inputs", nlohmann_json_default_obj.inputs);
  nlohmann_json_t.outputs = nlohmann_json_j.value("outputs", nlohmann_json_default_obj.outputs);
  nlohmann_json_t.metadata = nlohmann_json_j.value("metadata", nlohmann_json_default_obj.metadata);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const OutputTokenSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, OutputTokenSpec& nlohmann_json_t) {
  OutputTokenSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const RangeConstraint& nlohmann_json_t) {
  nlohmann_json_j["min_val"] = nlohmann_json_t.min_val;
  nlohmann_json_j["max_val"] = nlohmann_json_t.max_val;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, RangeConstraint& nlohmann_json_t) {
  RangeConstraint nlohmann_json_default_obj;
  nlohmann_json_t.min_val = nlohmann_json_j.value("min_val", nlohmann_json_default_obj.min_val);
  nlohmann_json_t.max_val = nlohmann_json_j.value("max_val", nlohmann_json_default_obj.max_val);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const SchemaVersion& nlohmann_json_t) {
  nlohmann_json_j["major"] = nlohmann_json_t.major;
  nlohmann_json_j["minor"] = nlohmann_json_t.minor;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, SchemaVersion& nlohmann_json_t) {
  SchemaVersion nlohmann_json_default_obj;
  nlohmann_json_t.major = nlohmann_json_j.value("major", nlohmann_json_default_obj.major);
  nlohmann_json_t.minor = nlohmann_json_j.value("minor", nlohmann_json_default_obj.minor);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const SymExpr& nlohmann_json_t) {
  nlohmann_json_j["expr_str"] = nlohmann_json_t.expr_str;
  nlohmann_json_j["hint"] = nlohmann_json_t.hint;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, SymExpr& nlohmann_json_t) {
  SymExpr nlohmann_json_default_obj;
  nlohmann_json_t.expr_str = nlohmann_json_j.value("expr_str", nlohmann_json_default_obj.expr_str);
  nlohmann_json_t.hint = nlohmann_json_j.value("hint", nlohmann_json_default_obj.hint);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const TensorArgument& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, TensorArgument& nlohmann_json_t) {
  TensorArgument nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const TensorMeta& nlohmann_json_t) {
  nlohmann_json_j["dtype"] = nlohmann_json_t.dtype;
  nlohmann_json_j["sizes"] = nlohmann_json_t.sizes;
  nlohmann_json_j["requires_grad"] = nlohmann_json_t.requires_grad;
  nlohmann_json_j["device"] = nlohmann_json_t.device;
  nlohmann_json_j["strides"] = nlohmann_json_t.strides;
  nlohmann_json_j["storage_offset"] = nlohmann_json_t.storage_offset;
  nlohmann_json_j["layout"] = nlohmann_json_t.layout;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, TensorMeta& nlohmann_json_t) {
  TensorMeta nlohmann_json_default_obj;
  nlohmann_json_t.dtype = nlohmann_json_j.value("dtype", nlohmann_json_default_obj.dtype);
  nlohmann_json_t.sizes = nlohmann_json_j.value("sizes", nlohmann_json_default_obj.sizes);
  nlohmann_json_t.requires_grad = nlohmann_json_j.value("requires_grad", nlohmann_json_default_obj.requires_grad);
  nlohmann_json_t.device = nlohmann_json_j.value("device", nlohmann_json_default_obj.device);
  nlohmann_json_t.strides = nlohmann_json_j.value("strides", nlohmann_json_default_obj.strides);
  nlohmann_json_t.storage_offset = nlohmann_json_j.value("storage_offset", nlohmann_json_default_obj.storage_offset);
  nlohmann_json_t.layout = nlohmann_json_j.value("layout", nlohmann_json_default_obj.layout);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const TokenArgument& nlohmann_json_t) {
  nlohmann_json_j["name"] = nlohmann_json_t.name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, TokenArgument& nlohmann_json_t) {
  TokenArgument nlohmann_json_default_obj;
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const UserInputMutationSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
  nlohmann_json_j["user_input_name"] = nlohmann_json_t.user_input_name;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, UserInputMutationSpec& nlohmann_json_t) {
  UserInputMutationSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
  nlohmann_json_t.user_input_name = nlohmann_json_j.value("user_input_name", nlohmann_json_default_obj.user_input_name);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const UserInputSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, UserInputSpec& nlohmann_json_t) {
  UserInputSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

inline void to_json(nlohmann::json& nlohmann_json_j, const UserOutputSpec& nlohmann_json_t) {
  nlohmann_json_j["arg"] = nlohmann_json_t.arg;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, UserOutputSpec& nlohmann_json_t) {
  UserOutputSpec nlohmann_json_default_obj;
  nlohmann_json_t.arg = nlohmann_json_j.value("arg", nlohmann_json_default_obj.arg);
}

} // namespace _export
} // namespace torch

// clang-format on
