#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
// @generated by update_schema.py
// checksum<<5b9bcd54d4ce78ce8bf3ec2e2cad62f19889537e14223d9e9adcfba1f2edc82c>>
// clang-format off

#pragma once

#include <optional>
#include <stdexcept>
#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>&&);
  ForwardRef(const ForwardRef<T>& other): ptr_(std::make_unique<T>(*other.ptr_)) {}
  ForwardRef<T>& operator=(ForwardRef<T>&&);
  ForwardRef<T>& operator=(const ForwardRef<T>& other) {
    ptr_ = std::make_unique<T>(*other.ptr_);
    return *this;
  }
  ~ForwardRef();
  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 F64 {
 public:
  double get() const {
    return value_;
  }

  void set(double value) {
    value_ = value;
  }

 private:
  double value_;
};

inline void to_json(nlohmann::json& j, const F64& f) {
  if (std::isinf(f.get())) {
    j = "Infinity";
  } else if (std::isinf(-f.get())) {
    j = "-Infinity";
  } else if (std::isnan(f.get())) {
    j = "NaN";
  } else {
    j = f.get();
  }
}

inline void from_json(const nlohmann::json& j, F64& f) {
  if (j == "Infinity") {
    f.set(std::numeric_limits<double>::infinity());
  } else if (j == "-Infinity") {
    f.set(-std::numeric_limits<double>::infinity());
  } else if (j == "NaN") {
    f.set(std::numeric_limits<double>::quiet_NaN());
  } else {
    f.set(j.get<double>());
  }
}

class AOTInductorModelPickleData;
class Argument;
class BufferMutationSpec;
class ComplexValue;
class ConstantValue;
class CustomObjArgument;
class Device;
class ExportedProgram;
class ExternKernelNode;
class ExternKernelNodes;
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 NamedTupleDef;
class Node;
class OptionalTensorArgument;
class OutputSpec;
class OutputTokenSpec;
class ParameterMutationSpec;
class PayloadConfig;
class PayloadMeta;
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 ArgumentKind {
  UNKNOWN = 0,
  POSITIONAL = 1,
  KEYWORD = 2,
};

inline std::string_view printEnum(const ArgumentKind& e) {
  switch (e) {
    case ArgumentKind::UNKNOWN: return "UNKNOWN";
    case ArgumentKind::POSITIONAL: return "POSITIONAL";
    case ArgumentKind::KEYWORD: return "KEYWORD";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, ArgumentKind& t) {
  if (s == "UNKNOWN") { t = ArgumentKind::UNKNOWN; return; }
  if (s == "POSITIONAL") { t = ArgumentKind::POSITIONAL; return; }
  if (s == "KEYWORD") { t = ArgumentKind::KEYWORD; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}

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

inline std::string_view printEnum(const Layout& e) {
  switch (e) {
    case Layout::Unknown: return "Unknown";
    case Layout::SparseCoo: return "SparseCoo";
    case Layout::SparseCsr: return "SparseCsr";
    case Layout::SparseCsc: return "SparseCsc";
    case Layout::SparseBsr: return "SparseBsr";
    case Layout::SparseBsc: return "SparseBsc";
    case Layout::_mkldnn: return "_mkldnn";
    case Layout::Strided: return "Strided";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, Layout& t) {
  if (s == "Unknown") { t = Layout::Unknown; return; }
  if (s == "SparseCoo") { t = Layout::SparseCoo; return; }
  if (s == "SparseCsr") { t = Layout::SparseCsr; return; }
  if (s == "SparseCsc") { t = Layout::SparseCsc; return; }
  if (s == "SparseBsr") { t = Layout::SparseBsr; return; }
  if (s == "SparseBsc") { t = Layout::SparseBsc; return; }
  if (s == "_mkldnn") { t = Layout::_mkldnn; return; }
  if (s == "Strided") { t = Layout::Strided; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}

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

inline std::string_view printEnum(const MemoryFormat& e) {
  switch (e) {
    case MemoryFormat::Unknown: return "Unknown";
    case MemoryFormat::ContiguousFormat: return "ContiguousFormat";
    case MemoryFormat::ChannelsLast: return "ChannelsLast";
    case MemoryFormat::ChannelsLast3d: return "ChannelsLast3d";
    case MemoryFormat::PreserveFormat: return "PreserveFormat";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, MemoryFormat& t) {
  if (s == "Unknown") { t = MemoryFormat::Unknown; return; }
  if (s == "ContiguousFormat") { t = MemoryFormat::ContiguousFormat; return; }
  if (s == "ChannelsLast") { t = MemoryFormat::ChannelsLast; return; }
  if (s == "ChannelsLast3d") { t = MemoryFormat::ChannelsLast3d; return; }
  if (s == "PreserveFormat") { t = MemoryFormat::PreserveFormat; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}

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,
  FLOAT8E4M3FN = 29,
  FLOAT8E5M2 = 30,
  FLOAT8E4M3FNUZ = 31,
  FLOAT8E5M2FNUZ = 32,
};

inline std::string_view printEnum(const ScalarType& e) {
  switch (e) {
    case ScalarType::UNKNOWN: return "UNKNOWN";
    case ScalarType::BYTE: return "BYTE";
    case ScalarType::CHAR: return "CHAR";
    case ScalarType::SHORT: return "SHORT";
    case ScalarType::INT: return "INT";
    case ScalarType::LONG: return "LONG";
    case ScalarType::HALF: return "HALF";
    case ScalarType::FLOAT: return "FLOAT";
    case ScalarType::DOUBLE: return "DOUBLE";
    case ScalarType::COMPLEXHALF: return "COMPLEXHALF";
    case ScalarType::COMPLEXFLOAT: return "COMPLEXFLOAT";
    case ScalarType::COMPLEXDOUBLE: return "COMPLEXDOUBLE";
    case ScalarType::BOOL: return "BOOL";
    case ScalarType::BFLOAT16: return "BFLOAT16";
    case ScalarType::UINT16: return "UINT16";
    case ScalarType::FLOAT8E4M3FN: return "FLOAT8E4M3FN";
    case ScalarType::FLOAT8E5M2: return "FLOAT8E5M2";
    case ScalarType::FLOAT8E4M3FNUZ: return "FLOAT8E4M3FNUZ";
    case ScalarType::FLOAT8E5M2FNUZ: return "FLOAT8E5M2FNUZ";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, ScalarType& t) {
  if (s == "UNKNOWN") { t = ScalarType::UNKNOWN; return; }
  if (s == "BYTE") { t = ScalarType::BYTE; return; }
  if (s == "CHAR") { t = ScalarType::CHAR; return; }
  if (s == "SHORT") { t = ScalarType::SHORT; return; }
  if (s == "INT") { t = ScalarType::INT; return; }
  if (s == "LONG") { t = ScalarType::LONG; return; }
  if (s == "HALF") { t = ScalarType::HALF; return; }
  if (s == "FLOAT") { t = ScalarType::FLOAT; return; }
  if (s == "DOUBLE") { t = ScalarType::DOUBLE; return; }
  if (s == "COMPLEXHALF") { t = ScalarType::COMPLEXHALF; return; }
  if (s == "COMPLEXFLOAT") { t = ScalarType::COMPLEXFLOAT; return; }
  if (s == "COMPLEXDOUBLE") { t = ScalarType::COMPLEXDOUBLE; return; }
  if (s == "BOOL") { t = ScalarType::BOOL; return; }
  if (s == "BFLOAT16") { t = ScalarType::BFLOAT16; return; }
  if (s == "UINT16") { t = ScalarType::UINT16; return; }
  if (s == "FLOAT8E4M3FN") { t = ScalarType::FLOAT8E4M3FN; return; }
  if (s == "FLOAT8E5M2") { t = ScalarType::FLOAT8E5M2; return; }
  if (s == "FLOAT8E4M3FNUZ") { t = ScalarType::FLOAT8E4M3FNUZ; return; }
  if (s == "FLOAT8E5M2FNUZ") { t = ScalarType::FLOAT8E5M2FNUZ; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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

 public:

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

  void set_type(std::string def) {
    type = std::move(def);
  }

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

  void set_index(std::optional<int64_t> def) {
    index = std::move(def);
  }

  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, F64> variant_;
  Tag tag_;

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

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

  void set_as_int(int64_t def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_INT;
  }

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

  void set_as_bool(bool def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_BOOL;
  }

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

  void set_as_float(F64 def) {
    variant_.emplace<3>(std::move(def));
    tag_ = Tag::AS_FLOAT;
  }

  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<F64>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

inline std::string_view printEnum(const SymExprHint::Tag& e) {
  switch (e) {
    case SymExprHint::Tag::AS_INT: return "AS_INT";
    case SymExprHint::Tag::AS_BOOL: return "AS_BOOL";
    case SymExprHint::Tag::AS_FLOAT: return "AS_FLOAT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymExprHint::Tag& t) {
  if (s == "AS_INT") { t = SymExprHint::Tag::AS_INT; return; }
  if (s == "AS_BOOL") { t = SymExprHint::Tag::AS_BOOL; return; }
  if (s == "AS_FLOAT") { t = SymExprHint::Tag::AS_FLOAT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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

 public:

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

  void set_expr_str(std::string def) {
    expr_str = std::move(def);
  }

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

  void set_hint(std::optional<SymExprHint> def) {
    hint = std::move(def);
  }

  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_);
  }

  void set_as_expr(SymExpr def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_EXPR;
  }

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

  void set_as_int(int64_t def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_INT;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const SymInt::Tag& e) {
  switch (e) {
    case SymInt::Tag::AS_EXPR: return "AS_EXPR";
    case SymInt::Tag::AS_INT: return "AS_INT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymInt::Tag& t) {
  if (s == "AS_EXPR") { t = SymInt::Tag::AS_EXPR; return; }
  if (s == "AS_INT") { t = SymInt::Tag::AS_INT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


class SymFloat {
  struct Void {};

 public:
  enum class Tag {
    AS_EXPR, AS_FLOAT
  };

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

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

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

  void set_as_expr(SymExpr def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_EXPR;
  }

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

  void set_as_float(F64 def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_FLOAT;
  }

  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<F64>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

inline std::string_view printEnum(const SymFloat::Tag& e) {
  switch (e) {
    case SymFloat::Tag::AS_EXPR: return "AS_EXPR";
    case SymFloat::Tag::AS_FLOAT: return "AS_FLOAT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymFloat::Tag& t) {
  if (s == "AS_EXPR") { t = SymFloat::Tag::AS_EXPR; return; }
  if (s == "AS_FLOAT") { t = SymFloat::Tag::AS_FLOAT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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_);
  }

  void set_as_expr(SymExpr def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_EXPR;
  }

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

  void set_as_bool(bool def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_BOOL;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const SymBool::Tag& e) {
  switch (e) {
    case SymBool::Tag::AS_EXPR: return "AS_EXPR";
    case SymBool::Tag::AS_BOOL: return "AS_BOOL";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymBool::Tag& t) {
  if (s == "AS_EXPR") { t = SymBool::Tag::AS_EXPR; return; }
  if (s == "AS_BOOL") { t = SymBool::Tag::AS_BOOL; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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);
  }

  void set_dtype(ScalarType def) {
    dtype = static_cast<int64_t>(def);
  }

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

  void set_sizes(std::vector<SymInt> def) {
    sizes = std::move(def);
  }

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

  void set_requires_grad(bool def) {
    requires_grad = std::move(def);
  }

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

  void set_device(Device def) {
    device = std::move(def);
  }

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

  void set_strides(std::vector<SymInt> def) {
    strides = std::move(def);
  }

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

  void set_storage_offset(SymInt def) {
    storage_offset = std::move(def);
  }

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

  void set_layout(Layout def) {
    layout = static_cast<int64_t>(def);
  }

  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_);
  }

  void set_as_name(std::string def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_NAME;
  }

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

  void set_as_int(int64_t def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_INT;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const SymIntArgument::Tag& e) {
  switch (e) {
    case SymIntArgument::Tag::AS_NAME: return "AS_NAME";
    case SymIntArgument::Tag::AS_INT: return "AS_INT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymIntArgument::Tag& t) {
  if (s == "AS_NAME") { t = SymIntArgument::Tag::AS_NAME; return; }
  if (s == "AS_INT") { t = SymIntArgument::Tag::AS_INT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


class SymFloatArgument {
  struct Void {};

 public:
  enum class Tag {
    AS_NAME, AS_FLOAT
  };

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

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

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

  void set_as_name(std::string def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_NAME;
  }

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

  void set_as_float(F64 def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_FLOAT;
  }

  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<F64>());
      nlohmann_json_t.tag_ = Tag::AS_FLOAT;
      return;
    }
  }
};

inline std::string_view printEnum(const SymFloatArgument::Tag& e) {
  switch (e) {
    case SymFloatArgument::Tag::AS_NAME: return "AS_NAME";
    case SymFloatArgument::Tag::AS_FLOAT: return "AS_FLOAT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymFloatArgument::Tag& t) {
  if (s == "AS_NAME") { t = SymFloatArgument::Tag::AS_NAME; return; }
  if (s == "AS_FLOAT") { t = SymFloatArgument::Tag::AS_FLOAT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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_);
  }

  void set_as_name(std::string def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_NAME;
  }

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

  void set_as_bool(bool def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_BOOL;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const SymBoolArgument::Tag& e) {
  switch (e) {
    case SymBoolArgument::Tag::AS_NAME: return "AS_NAME";
    case SymBoolArgument::Tag::AS_BOOL: return "AS_BOOL";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, SymBoolArgument::Tag& t) {
  if (s == "AS_NAME") { t = SymBoolArgument::Tag::AS_NAME; return; }
  if (s == "AS_BOOL") { t = SymBoolArgument::Tag::AS_BOOL; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


class TensorArgument {
 private:
  std::string name;

 public:

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

  void set_name(std::string def) {
    name = std::move(def);
  }

  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;
  }

  void set_name(std::string def) {
    name = std::move(def);
  }

  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_);
  }

  void set_as_tensor(TensorArgument def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_TENSOR;
  }

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

  void set_as_none(bool def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_NONE;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const OptionalTensorArgument::Tag& e) {
  switch (e) {
    case OptionalTensorArgument::Tag::AS_TENSOR: return "AS_TENSOR";
    case OptionalTensorArgument::Tag::AS_NONE: return "AS_NONE";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, OptionalTensorArgument::Tag& t) {
  if (s == "AS_TENSOR") { t = OptionalTensorArgument::Tag::AS_TENSOR; return; }
  if (s == "AS_NONE") { t = OptionalTensorArgument::Tag::AS_NONE; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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

 public:

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

  void set_name(std::string def) {
    name = std::move(def);
  }

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

  void set_graph(ForwardRef<Graph> def) {
    graph = std::move(def);
  }

  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;
  }

  void set_name(std::string def) {
    name = std::move(def);
  }

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

  void set_class_fqn(std::string def) {
    class_fqn = std::move(def);
  }

  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 ComplexValue {
 private:
  F64 real;
  F64 imag;

 public:

  const F64& get_real() const {
    return real;
  }

  void set_real(F64 def) {
    real = std::move(def);
  }

  const F64& get_imag() const {
    return imag;
  }

  void set_imag(F64 def) {
    imag = std::move(def);
  }

  friend void to_json(nlohmann::json& nlohmann_json_j, const ComplexValue& nlohmann_json_t);
  friend void from_json(const nlohmann::json& nlohmann_json_j, ComplexValue& 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, AS_OPTIONAL_TENSOR, AS_COMPLEX, AS_NESTED_TENSORS, AS_INT_LISTS, AS_STRING_TO_ARGUMENT
  };

 private:
  std::variant<Void, bool, TensorArgument, std::vector<TensorArgument>, int64_t, std::vector<int64_t>, F64, std::vector<F64>, 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>, OptionalTensorArgument, ComplexValue, std::vector<std::vector<TensorArgument>>, std::vector<std::vector<int64_t>>, std::unordered_map<std::string, ForwardRef<Argument>>> variant_;
  Tag tag_;

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

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

  void set_as_none(bool def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_NONE;
  }

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

  void set_as_tensor(TensorArgument def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_TENSOR;
  }

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

  void set_as_tensors(std::vector<TensorArgument> def) {
    variant_.emplace<3>(std::move(def));
    tag_ = Tag::AS_TENSORS;
  }

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

  void set_as_int(int64_t def) {
    variant_.emplace<4>(std::move(def));
    tag_ = Tag::AS_INT;
  }

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

  void set_as_ints(std::vector<int64_t> def) {
    variant_.emplace<5>(std::move(def));
    tag_ = Tag::AS_INTS;
  }

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

  void set_as_float(F64 def) {
    variant_.emplace<6>(std::move(def));
    tag_ = Tag::AS_FLOAT;
  }

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

  void set_as_floats(std::vector<F64> def) {
    variant_.emplace<7>(std::move(def));
    tag_ = Tag::AS_FLOATS;
  }

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

  void set_as_string(std::string def) {
    variant_.emplace<8>(std::move(def));
    tag_ = Tag::AS_STRING;
  }

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

  void set_as_strings(std::vector<std::string> def) {
    variant_.emplace<9>(std::move(def));
    tag_ = Tag::AS_STRINGS;
  }

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

  void set_as_sym_int(SymIntArgument def) {
    variant_.emplace<10>(std::move(def));
    tag_ = Tag::AS_SYM_INT;
  }

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

  void set_as_sym_ints(std::vector<SymIntArgument> def) {
    variant_.emplace<11>(std::move(def));
    tag_ = Tag::AS_SYM_INTS;
  }

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

  void set_as_scalar_type(ScalarType def) {
    variant_.emplace<12>(std::move(def));
    tag_ = Tag::AS_SCALAR_TYPE;
  }

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

  void set_as_memory_format(MemoryFormat def) {
    variant_.emplace<13>(std::move(def));
    tag_ = Tag::AS_MEMORY_FORMAT;
  }

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

  void set_as_layout(Layout def) {
    variant_.emplace<14>(std::move(def));
    tag_ = Tag::AS_LAYOUT;
  }

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

  void set_as_device(Device def) {
    variant_.emplace<15>(std::move(def));
    tag_ = Tag::AS_DEVICE;
  }

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

  void set_as_bool(bool def) {
    variant_.emplace<16>(std::move(def));
    tag_ = Tag::AS_BOOL;
  }

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

  void set_as_bools(std::vector<bool> def) {
    variant_.emplace<17>(std::move(def));
    tag_ = Tag::AS_BOOLS;
  }

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

  void set_as_sym_bool(SymBoolArgument def) {
    variant_.emplace<18>(std::move(def));
    tag_ = Tag::AS_SYM_BOOL;
  }

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

  void set_as_sym_bools(std::vector<SymBoolArgument> def) {
    variant_.emplace<19>(std::move(def));
    tag_ = Tag::AS_SYM_BOOLS;
  }

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

  void set_as_graph(GraphArgument def) {
    variant_.emplace<20>(std::move(def));
    tag_ = Tag::AS_GRAPH;
  }

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

  void set_as_optional_tensors(std::vector<OptionalTensorArgument> def) {
    variant_.emplace<21>(std::move(def));
    tag_ = Tag::AS_OPTIONAL_TENSORS;
  }

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

  void set_as_custom_obj(CustomObjArgument def) {
    variant_.emplace<22>(std::move(def));
    tag_ = Tag::AS_CUSTOM_OBJ;
  }

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

  void set_as_operator(std::string def) {
    variant_.emplace<23>(std::move(def));
    tag_ = Tag::AS_OPERATOR;
  }

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

  void set_as_sym_float(SymFloatArgument def) {
    variant_.emplace<24>(std::move(def));
    tag_ = Tag::AS_SYM_FLOAT;
  }

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

  void set_as_sym_floats(std::vector<SymFloatArgument> def) {
    variant_.emplace<25>(std::move(def));
    tag_ = Tag::AS_SYM_FLOATS;
  }

  const OptionalTensorArgument& get_as_optional_tensor() const {
    return std::get<26>(variant_);
  }

  void set_as_optional_tensor(OptionalTensorArgument def) {
    variant_.emplace<26>(std::move(def));
    tag_ = Tag::AS_OPTIONAL_TENSOR;
  }

  const ComplexValue& get_as_complex() const {
    return std::get<27>(variant_);
  }

  void set_as_complex(ComplexValue def) {
    variant_.emplace<27>(std::move(def));
    tag_ = Tag::AS_COMPLEX;
  }

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

  void set_as_nested_tensors(std::vector<std::vector<TensorArgument>> def) {
    variant_.emplace<28>(std::move(def));
    tag_ = Tag::AS_NESTED_TENSORS;
  }

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

  void set_as_int_lists(std::vector<std::vector<int64_t>> def) {
    variant_.emplace<29>(std::move(def));
    tag_ = Tag::AS_INT_LISTS;
  }

  const std::unordered_map<std::string, ForwardRef<Argument>>& get_as_string_to_argument() const {
    return std::get<30>(variant_);
  }

  void set_as_string_to_argument(std::unordered_map<std::string, ForwardRef<Argument>> def) {
    variant_.emplace<30>(std::move(def));
    tag_ = Tag::AS_STRING_TO_ARGUMENT;
  }

  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;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_OPTIONAL_TENSOR) {
      nlohmann_json_j["as_optional_tensor"] = nlohmann_json_t.get_as_optional_tensor();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_COMPLEX) {
      nlohmann_json_j["as_complex"] = nlohmann_json_t.get_as_complex();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_NESTED_TENSORS) {
      nlohmann_json_j["as_nested_tensors"] = nlohmann_json_t.get_as_nested_tensors();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_INT_LISTS) {
      nlohmann_json_j["as_int_lists"] = nlohmann_json_t.get_as_int_lists();
      return;
    }
    if (nlohmann_json_t.tag_ == Tag::AS_STRING_TO_ARGUMENT) {
      nlohmann_json_j["as_string_to_argument"] = nlohmann_json_t.get_as_string_to_argument();
      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<F64>());
      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<F64>>());
      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;
    }
    if (nlohmann_json_j.contains("as_optional_tensor")) {
      nlohmann_json_t.variant_.emplace<26>(nlohmann_json_j.at("as_optional_tensor").template get<OptionalTensorArgument>());
      nlohmann_json_t.tag_ = Tag::AS_OPTIONAL_TENSOR;
      return;
    }
    if (nlohmann_json_j.contains("as_complex")) {
      nlohmann_json_t.variant_.emplace<27>(nlohmann_json_j.at("as_complex").template get<ComplexValue>());
      nlohmann_json_t.tag_ = Tag::AS_COMPLEX;
      return;
    }
    if (nlohmann_json_j.contains("as_nested_tensors")) {
      nlohmann_json_t.variant_.emplace<28>(nlohmann_json_j.at("as_nested_tensors").template get<std::vector<std::vector<TensorArgument>>>());
      nlohmann_json_t.tag_ = Tag::AS_NESTED_TENSORS;
      return;
    }
    if (nlohmann_json_j.contains("as_int_lists")) {
      nlohmann_json_t.variant_.emplace<29>(nlohmann_json_j.at("as_int_lists").template get<std::vector<std::vector<int64_t>>>());
      nlohmann_json_t.tag_ = Tag::AS_INT_LISTS;
      return;
    }
    if (nlohmann_json_j.contains("as_string_to_argument")) {
      nlohmann_json_t.variant_.emplace<30>(nlohmann_json_j.at("as_string_to_argument").template get<std::unordered_map<std::string, ForwardRef<Argument>>>());
      nlohmann_json_t.tag_ = Tag::AS_STRING_TO_ARGUMENT;
      return;
    }
  }
};

inline std::string_view printEnum(const Argument::Tag& e) {
  switch (e) {
    case Argument::Tag::AS_NONE: return "AS_NONE";
    case Argument::Tag::AS_TENSOR: return "AS_TENSOR";
    case Argument::Tag::AS_TENSORS: return "AS_TENSORS";
    case Argument::Tag::AS_INT: return "AS_INT";
    case Argument::Tag::AS_INTS: return "AS_INTS";
    case Argument::Tag::AS_FLOAT: return "AS_FLOAT";
    case Argument::Tag::AS_FLOATS: return "AS_FLOATS";
    case Argument::Tag::AS_STRING: return "AS_STRING";
    case Argument::Tag::AS_STRINGS: return "AS_STRINGS";
    case Argument::Tag::AS_SYM_INT: return "AS_SYM_INT";
    case Argument::Tag::AS_SYM_INTS: return "AS_SYM_INTS";
    case Argument::Tag::AS_SCALAR_TYPE: return "AS_SCALAR_TYPE";
    case Argument::Tag::AS_MEMORY_FORMAT: return "AS_MEMORY_FORMAT";
    case Argument::Tag::AS_LAYOUT: return "AS_LAYOUT";
    case Argument::Tag::AS_DEVICE: return "AS_DEVICE";
    case Argument::Tag::AS_BOOL: return "AS_BOOL";
    case Argument::Tag::AS_BOOLS: return "AS_BOOLS";
    case Argument::Tag::AS_SYM_BOOL: return "AS_SYM_BOOL";
    case Argument::Tag::AS_SYM_BOOLS: return "AS_SYM_BOOLS";
    case Argument::Tag::AS_GRAPH: return "AS_GRAPH";
    case Argument::Tag::AS_OPTIONAL_TENSORS: return "AS_OPTIONAL_TENSORS";
    case Argument::Tag::AS_CUSTOM_OBJ: return "AS_CUSTOM_OBJ";
    case Argument::Tag::AS_OPERATOR: return "AS_OPERATOR";
    case Argument::Tag::AS_SYM_FLOAT: return "AS_SYM_FLOAT";
    case Argument::Tag::AS_SYM_FLOATS: return "AS_SYM_FLOATS";
    case Argument::Tag::AS_OPTIONAL_TENSOR: return "AS_OPTIONAL_TENSOR";
    case Argument::Tag::AS_COMPLEX: return "AS_COMPLEX";
    case Argument::Tag::AS_NESTED_TENSORS: return "AS_NESTED_TENSORS";
    case Argument::Tag::AS_INT_LISTS: return "AS_INT_LISTS";
    case Argument::Tag::AS_STRING_TO_ARGUMENT: return "AS_STRING_TO_ARGUMENT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, Argument::Tag& t) {
  if (s == "AS_NONE") { t = Argument::Tag::AS_NONE; return; }
  if (s == "AS_TENSOR") { t = Argument::Tag::AS_TENSOR; return; }
  if (s == "AS_TENSORS") { t = Argument::Tag::AS_TENSORS; return; }
  if (s == "AS_INT") { t = Argument::Tag::AS_INT; return; }
  if (s == "AS_INTS") { t = Argument::Tag::AS_INTS; return; }
  if (s == "AS_FLOAT") { t = Argument::Tag::AS_FLOAT; return; }
  if (s == "AS_FLOATS") { t = Argument::Tag::AS_FLOATS; return; }
  if (s == "AS_STRING") { t = Argument::Tag::AS_STRING; return; }
  if (s == "AS_STRINGS") { t = Argument::Tag::AS_STRINGS; return; }
  if (s == "AS_SYM_INT") { t = Argument::Tag::AS_SYM_INT; return; }
  if (s == "AS_SYM_INTS") { t = Argument::Tag::AS_SYM_INTS; return; }
  if (s == "AS_SCALAR_TYPE") { t = Argument::Tag::AS_SCALAR_TYPE; return; }
  if (s == "AS_MEMORY_FORMAT") { t = Argument::Tag::AS_MEMORY_FORMAT; return; }
  if (s == "AS_LAYOUT") { t = Argument::Tag::AS_LAYOUT; return; }
  if (s == "AS_DEVICE") { t = Argument::Tag::AS_DEVICE; return; }
  if (s == "AS_BOOL") { t = Argument::Tag::AS_BOOL; return; }
  if (s == "AS_BOOLS") { t = Argument::Tag::AS_BOOLS; return; }
  if (s == "AS_SYM_BOOL") { t = Argument::Tag::AS_SYM_BOOL; return; }
  if (s == "AS_SYM_BOOLS") { t = Argument::Tag::AS_SYM_BOOLS; return; }
  if (s == "AS_GRAPH") { t = Argument::Tag::AS_GRAPH; return; }
  if (s == "AS_OPTIONAL_TENSORS") { t = Argument::Tag::AS_OPTIONAL_TENSORS; return; }
  if (s == "AS_CUSTOM_OBJ") { t = Argument::Tag::AS_CUSTOM_OBJ; return; }
  if (s == "AS_OPERATOR") { t = Argument::Tag::AS_OPERATOR; return; }
  if (s == "AS_SYM_FLOAT") { t = Argument::Tag::AS_SYM_FLOAT; return; }
  if (s == "AS_SYM_FLOATS") { t = Argument::Tag::AS_SYM_FLOATS; return; }
  if (s == "AS_OPTIONAL_TENSOR") { t = Argument::Tag::AS_OPTIONAL_TENSOR; return; }
  if (s == "AS_COMPLEX") { t = Argument::Tag::AS_COMPLEX; return; }
  if (s == "AS_NESTED_TENSORS") { t = Argument::Tag::AS_NESTED_TENSORS; return; }
  if (s == "AS_INT_LISTS") { t = Argument::Tag::AS_INT_LISTS; return; }
  if (s == "AS_STRING_TO_ARGUMENT") { t = Argument::Tag::AS_STRING_TO_ARGUMENT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


class NamedArgument {
 private:
  std::string name;
  Argument arg;
  std::optional<int64_t> kind = std::nullopt;

 public:

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

  void set_name(std::string def) {
    name = std::move(def);
  }

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

  void set_arg(Argument def) {
    arg = std::move(def);
  }

  const std::optional<int64_t>& get_kind() const {
    return kind;
  }

  void set_kind(std::optional<int64_t> def) {
    kind = std::move(def);
  }

  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;
  std::optional<bool> is_hop_single_tensor_return = std::nullopt;
  std::optional<std::string> name = std::nullopt;

 public:

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

  void set_target(std::string def) {
    target = std::move(def);
  }

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

  void set_inputs(std::vector<NamedArgument> def) {
    inputs = std::move(def);
  }

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

  void set_outputs(std::vector<Argument> def) {
    outputs = std::move(def);
  }

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

  void set_metadata(std::unordered_map<std::string, std::string> def) {
    metadata = std::move(def);
  }

  const std::optional<bool>& get_is_hop_single_tensor_return() const {
    return is_hop_single_tensor_return;
  }

  void set_is_hop_single_tensor_return(std::optional<bool> def) {
    is_hop_single_tensor_return = std::move(def);
  }

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

  void set_name(std::optional<std::string> def) {
    name = std::move(def);
  }

  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;
  }

  void set_inputs(std::vector<Argument> def) {
    inputs = std::move(def);
  }

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

  void set_outputs(std::vector<Argument> def) {
    outputs = std::move(def);
  }

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

  void set_nodes(std::vector<Node> def) {
    nodes = std::move(def);
  }

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

  void set_tensor_values(std::unordered_map<std::string, TensorMeta> def) {
    tensor_values = std::move(def);
  }

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

  void set_sym_int_values(std::unordered_map<std::string, SymInt> def) {
    sym_int_values = std::move(def);
  }

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

  void set_sym_bool_values(std::unordered_map<std::string, SymBool> def) {
    sym_bool_values = std::move(def);
  }

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

  void set_is_single_tensor_return(bool def) {
    is_single_tensor_return = std::move(def);
  }

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

  void set_custom_obj_values(std::unordered_map<std::string, CustomObjArgument> def) {
    custom_obj_values = std::move(def);
  }

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

  void set_sym_float_values(std::unordered_map<std::string, SymFloat> def) {
    sym_float_values = std::move(def);
  }

  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;
  }

  void set_arg(Argument def) {
    arg = std::move(def);
  }

  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, F64, std::string, bool> variant_;
  Tag tag_;

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

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

  void set_as_none(bool def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::AS_NONE;
  }

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

  void set_as_int(int64_t def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::AS_INT;
  }

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

  void set_as_float(F64 def) {
    variant_.emplace<3>(std::move(def));
    tag_ = Tag::AS_FLOAT;
  }

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

  void set_as_string(std::string def) {
    variant_.emplace<4>(std::move(def));
    tag_ = Tag::AS_STRING;
  }

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

  void set_as_bool(bool def) {
    variant_.emplace<5>(std::move(def));
    tag_ = Tag::AS_BOOL;
  }

  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<F64>());
      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;
    }
  }
};

inline std::string_view printEnum(const ConstantValue::Tag& e) {
  switch (e) {
    case ConstantValue::Tag::AS_NONE: return "AS_NONE";
    case ConstantValue::Tag::AS_INT: return "AS_INT";
    case ConstantValue::Tag::AS_FLOAT: return "AS_FLOAT";
    case ConstantValue::Tag::AS_STRING: return "AS_STRING";
    case ConstantValue::Tag::AS_BOOL: return "AS_BOOL";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, ConstantValue::Tag& t) {
  if (s == "AS_NONE") { t = ConstantValue::Tag::AS_NONE; return; }
  if (s == "AS_INT") { t = ConstantValue::Tag::AS_INT; return; }
  if (s == "AS_FLOAT") { t = ConstantValue::Tag::AS_FLOAT; return; }
  if (s == "AS_STRING") { t = ConstantValue::Tag::AS_STRING; return; }
  if (s == "AS_BOOL") { t = ConstantValue::Tag::AS_BOOL; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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

 public:

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

  void set_name(std::string def) {
    name = std::move(def);
  }

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

  void set_value(ConstantValue def) {
    value = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_parameter_name(std::string def) {
    parameter_name = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_buffer_name(std::string def) {
    buffer_name = std::move(def);
  }

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

  void set_persistent(bool def) {
    persistent = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_tensor_constant_name(std::string def) {
    tensor_constant_name = std::move(def);
  }

  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;
  }

  void set_arg(CustomObjArgument def) {
    arg = std::move(def);
  }

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

  void set_custom_obj_name(std::string def) {
    custom_obj_name = std::move(def);
  }

  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;
  }

  void set_arg(TokenArgument def) {
    arg = std::move(def);
  }

  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_);
  }

  void set_user_input(UserInputSpec def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::USER_INPUT;
  }

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

  void set_parameter(InputToParameterSpec def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::PARAMETER;
  }

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

  void set_buffer(InputToBufferSpec def) {
    variant_.emplace<3>(std::move(def));
    tag_ = Tag::BUFFER;
  }

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

  void set_tensor_constant(InputToTensorConstantSpec def) {
    variant_.emplace<4>(std::move(def));
    tag_ = Tag::TENSOR_CONSTANT;
  }

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

  void set_custom_obj(InputToCustomObjSpec def) {
    variant_.emplace<5>(std::move(def));
    tag_ = Tag::CUSTOM_OBJ;
  }

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

  void set_token(InputTokenSpec def) {
    variant_.emplace<6>(std::move(def));
    tag_ = Tag::TOKEN;
  }

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

  void set_constant_input(InputToConstantInputSpec def) {
    variant_.emplace<7>(std::move(def));
    tag_ = Tag::CONSTANT_INPUT;
  }

  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;
    }
  }
};

inline std::string_view printEnum(const InputSpec::Tag& e) {
  switch (e) {
    case InputSpec::Tag::USER_INPUT: return "USER_INPUT";
    case InputSpec::Tag::PARAMETER: return "PARAMETER";
    case InputSpec::Tag::BUFFER: return "BUFFER";
    case InputSpec::Tag::TENSOR_CONSTANT: return "TENSOR_CONSTANT";
    case InputSpec::Tag::CUSTOM_OBJ: return "CUSTOM_OBJ";
    case InputSpec::Tag::TOKEN: return "TOKEN";
    case InputSpec::Tag::CONSTANT_INPUT: return "CONSTANT_INPUT";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, InputSpec::Tag& t) {
  if (s == "USER_INPUT") { t = InputSpec::Tag::USER_INPUT; return; }
  if (s == "PARAMETER") { t = InputSpec::Tag::PARAMETER; return; }
  if (s == "BUFFER") { t = InputSpec::Tag::BUFFER; return; }
  if (s == "TENSOR_CONSTANT") { t = InputSpec::Tag::TENSOR_CONSTANT; return; }
  if (s == "CUSTOM_OBJ") { t = InputSpec::Tag::CUSTOM_OBJ; return; }
  if (s == "TOKEN") { t = InputSpec::Tag::TOKEN; return; }
  if (s == "CONSTANT_INPUT") { t = InputSpec::Tag::CONSTANT_INPUT; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


class UserOutputSpec {
 private:
  Argument arg;

 public:

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

  void set_arg(Argument def) {
    arg = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_buffer_name(std::string def) {
    buffer_name = std::move(def);
  }

  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 ParameterMutationSpec {
 private:
  TensorArgument arg;
  std::string parameter_name;

 public:

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

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_parameter_name(std::string def) {
    parameter_name = std::move(def);
  }

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

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

 public:

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

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_parameter_name(std::string def) {
    parameter_name = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_user_input_name(std::string def) {
    user_input_name = std::move(def);
  }

  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;
  }

  void set_arg(TensorArgument def) {
    arg = std::move(def);
  }

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

  void set_user_input_name(std::string def) {
    user_input_name = std::move(def);
  }

  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;
  }

  void set_arg(TokenArgument def) {
    arg = std::move(def);
  }

  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, PARAMETER_MUTATION
  };

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

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

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

  void set_user_output(UserOutputSpec def) {
    variant_.emplace<1>(std::move(def));
    tag_ = Tag::USER_OUTPUT;
  }

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

  void set_loss_output(LossOutputSpec def) {
    variant_.emplace<2>(std::move(def));
    tag_ = Tag::LOSS_OUTPUT;
  }

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

  void set_buffer_mutation(BufferMutationSpec def) {
    variant_.emplace<3>(std::move(def));
    tag_ = Tag::BUFFER_MUTATION;
  }

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

  void set_gradient_to_parameter(GradientToParameterSpec def) {
    variant_.emplace<4>(std::move(def));
    tag_ = Tag::GRADIENT_TO_PARAMETER;
  }

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

  void set_gradient_to_user_input(GradientToUserInputSpec def) {
    variant_.emplace<5>(std::move(def));
    tag_ = Tag::GRADIENT_TO_USER_INPUT;
  }

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

  void set_user_input_mutation(UserInputMutationSpec def) {
    variant_.emplace<6>(std::move(def));
    tag_ = Tag::USER_INPUT_MUTATION;
  }

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

  void set_token(OutputTokenSpec def) {
    variant_.emplace<7>(std::move(def));
    tag_ = Tag::TOKEN;
  }

  const ParameterMutationSpec& get_parameter_mutation() const {
    return std::get<8>(variant_);
  }

  void set_parameter_mutation(ParameterMutationSpec def) {
    variant_.emplace<8>(std::move(def));
    tag_ = Tag::PARAMETER_MUTATION;
  }

  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;
    }
    if (nlohmann_json_t.tag_ == Tag::PARAMETER_MUTATION) {
      nlohmann_json_j["parameter_mutation"] = nlohmann_json_t.get_parameter_mutation();
      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;
    }
    if (nlohmann_json_j.contains("parameter_mutation")) {
      nlohmann_json_t.variant_.emplace<8>(nlohmann_json_j.at("parameter_mutation").template get<ParameterMutationSpec>());
      nlohmann_json_t.tag_ = Tag::PARAMETER_MUTATION;
      return;
    }
  }
};

inline std::string_view printEnum(const OutputSpec::Tag& e) {
  switch (e) {
    case OutputSpec::Tag::USER_OUTPUT: return "USER_OUTPUT";
    case OutputSpec::Tag::LOSS_OUTPUT: return "LOSS_OUTPUT";
    case OutputSpec::Tag::BUFFER_MUTATION: return "BUFFER_MUTATION";
    case OutputSpec::Tag::GRADIENT_TO_PARAMETER: return "GRADIENT_TO_PARAMETER";
    case OutputSpec::Tag::GRADIENT_TO_USER_INPUT: return "GRADIENT_TO_USER_INPUT";
    case OutputSpec::Tag::USER_INPUT_MUTATION: return "USER_INPUT_MUTATION";
    case OutputSpec::Tag::TOKEN: return "TOKEN";
    case OutputSpec::Tag::PARAMETER_MUTATION: return "PARAMETER_MUTATION";
    default:
      throw std::runtime_error("Unknown enum value");
  }
}

inline void parseEnum(std::string_view s, OutputSpec::Tag& t) {
  if (s == "USER_OUTPUT") { t = OutputSpec::Tag::USER_OUTPUT; return; }
  if (s == "LOSS_OUTPUT") { t = OutputSpec::Tag::LOSS_OUTPUT; return; }
  if (s == "BUFFER_MUTATION") { t = OutputSpec::Tag::BUFFER_MUTATION; return; }
  if (s == "GRADIENT_TO_PARAMETER") { t = OutputSpec::Tag::GRADIENT_TO_PARAMETER; return; }
  if (s == "GRADIENT_TO_USER_INPUT") { t = OutputSpec::Tag::GRADIENT_TO_USER_INPUT; return; }
  if (s == "USER_INPUT_MUTATION") { t = OutputSpec::Tag::USER_INPUT_MUTATION; return; }
  if (s == "TOKEN") { t = OutputSpec::Tag::TOKEN; return; }
  if (s == "PARAMETER_MUTATION") { t = OutputSpec::Tag::PARAMETER_MUTATION; return; }
  throw std::runtime_error("Unknown enum value: " + std::string{s});
}


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;
  }

  void set_input_specs(std::vector<InputSpec> def) {
    input_specs = std::move(def);
  }

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

  void set_output_specs(std::vector<OutputSpec> def) {
    output_specs = std::move(def);
  }

  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;
  }

  void set_min_val(std::optional<int64_t> def) {
    min_val = std::move(def);
  }

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

  void set_max_val(std::optional<int64_t> def) {
    max_val = std::move(def);
  }

  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;
  }

  void set_inputs(std::vector<Argument> def) {
    inputs = std::move(def);
  }

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

  void set_outputs(std::vector<Argument> def) {
    outputs = std::move(def);
  }

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

  void set_in_spec(std::string def) {
    in_spec = std::move(def);
  }

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

  void set_out_spec(std::string def) {
    out_spec = std::move(def);
  }

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

  void set_forward_arg_names(std::optional<std::vector<std::string>> def) {
    forward_arg_names = std::move(def);
  }

  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;
  }

  void set_fqn(std::string def) {
    fqn = std::move(def);
  }

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

  void set_signature(std::optional<ModuleCallSignature> def) {
    signature = std::move(def);
  }

  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 NamedTupleDef {
 private:
  std::vector<std::string> field_names;

 public:

  const std::vector<std::string>& get_field_names() const {
    return field_names;
  }

  void set_field_names(std::vector<std::string> def) {
    field_names = std::move(def);
  }

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

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

 public:

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

  void set_graph(Graph def) {
    graph = std::move(def);
  }

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

  void set_signature(GraphSignature def) {
    signature = std::move(def);
  }

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

  void set_module_call_graph(std::vector<ModuleCallEntry> def) {
    module_call_graph = std::move(def);
  }

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

  void set_metadata(std::unordered_map<std::string, std::string> def) {
    metadata = std::move(def);
  }

  const std::unordered_map<std::string, NamedTupleDef>& get_treespec_namedtuple_fields() const {
    return treespec_namedtuple_fields;
  }

  void set_treespec_namedtuple_fields(std::unordered_map<std::string, NamedTupleDef> def) {
    treespec_namedtuple_fields = std::move(def);
  }

  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;
  }

  void set_major(int64_t def) {
    major = std::move(def);
  }

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

  void set_minor(int64_t def) {
    minor = std::move(def);
  }

  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";
  std::vector<std::string> guards_code = {};

 public:

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

  void set_graph_module(GraphModule def) {
    graph_module = std::move(def);
  }

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

  void set_opset_version(std::unordered_map<std::string, int64_t> def) {
    opset_version = std::move(def);
  }

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

  void set_range_constraints(std::unordered_map<std::string, RangeConstraint> def) {
    range_constraints = std::move(def);
  }

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

  void set_schema_version(SchemaVersion def) {
    schema_version = std::move(def);
  }

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

  void set_verifiers(std::vector<std::string> def) {
    verifiers = std::move(def);
  }

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

  void set_torch_version(std::string def) {
    torch_version = std::move(def);
  }

  const std::vector<std::string>& get_guards_code() const {
    return guards_code;
  }

  void set_guards_code(std::vector<std::string> def) {
    guards_code = std::move(def);
  }

  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);
};

class PayloadMeta {
 private:
  std::string path_name;
  bool is_param;
  bool use_pickle;
  std::optional<TensorMeta> tensor_meta;

 public:

  const std::string& get_path_name() const {
    return path_name;
  }

  void set_path_name(std::string def) {
    path_name = std::move(def);
  }

  const bool& get_is_param() const {
    return is_param;
  }

  void set_is_param(bool def) {
    is_param = std::move(def);
  }

  const bool& get_use_pickle() const {
    return use_pickle;
  }

  void set_use_pickle(bool def) {
    use_pickle = std::move(def);
  }

  const std::optional<TensorMeta>& get_tensor_meta() const {
    return tensor_meta;
  }

  void set_tensor_meta(std::optional<TensorMeta> def) {
    tensor_meta = std::move(def);
  }

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

class PayloadConfig {
 private:
  std::unordered_map<std::string, PayloadMeta> config;

 public:

  const std::unordered_map<std::string, PayloadMeta>& get_config() const {
    return config;
  }

  void set_config(std::unordered_map<std::string, PayloadMeta> def) {
    config = std::move(def);
  }

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

class AOTInductorModelPickleData {
 private:
  std::string library_basename;
  std::vector<std::string> input_names;
  std::vector<std::string> output_names;
  std::optional<int64_t> floating_point_input_dtype = std::nullopt;
  std::optional<int64_t> floating_point_output_dtype = std::nullopt;
  std::optional<bool> aot_inductor_model_is_cpu = std::nullopt;

 public:

  const std::string& get_library_basename() const {
    return library_basename;
  }

  void set_library_basename(std::string def) {
    library_basename = std::move(def);
  }

  const std::vector<std::string>& get_input_names() const {
    return input_names;
  }

  void set_input_names(std::vector<std::string> def) {
    input_names = std::move(def);
  }

  const std::vector<std::string>& get_output_names() const {
    return output_names;
  }

  void set_output_names(std::vector<std::string> def) {
    output_names = std::move(def);
  }

  const std::optional<int64_t>& get_floating_point_input_dtype() const {
    return floating_point_input_dtype;
  }

  void set_floating_point_input_dtype(std::optional<int64_t> def) {
    floating_point_input_dtype = std::move(def);
  }

  const std::optional<int64_t>& get_floating_point_output_dtype() const {
    return floating_point_output_dtype;
  }

  void set_floating_point_output_dtype(std::optional<int64_t> def) {
    floating_point_output_dtype = std::move(def);
  }

  const std::optional<bool>& get_aot_inductor_model_is_cpu() const {
    return aot_inductor_model_is_cpu;
  }

  void set_aot_inductor_model_is_cpu(std::optional<bool> def) {
    aot_inductor_model_is_cpu = std::move(def);
  }

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

class ExternKernelNode {
 private:
  std::string name;
  Node node;

 public:

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

  void set_name(std::string def) {
    name = std::move(def);
  }

  const Node& get_node() const {
    return node;
  }

  void set_node(Node def) {
    node = std::move(def);
  }

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

class ExternKernelNodes {
 private:
  std::vector<ExternKernelNode> nodes;

 public:

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

  void set_nodes(std::vector<ExternKernelNode> def) {
    nodes = std::move(def);
  }

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

inline void to_json(nlohmann::json& nlohmann_json_j, const AOTInductorModelPickleData& nlohmann_json_t) {
  nlohmann_json_j["library_basename"] = nlohmann_json_t.library_basename;
  nlohmann_json_j["input_names"] = nlohmann_json_t.input_names;
  nlohmann_json_j["output_names"] = nlohmann_json_t.output_names;
  nlohmann_json_j["floating_point_input_dtype"] = nlohmann_json_t.floating_point_input_dtype;
  nlohmann_json_j["floating_point_output_dtype"] = nlohmann_json_t.floating_point_output_dtype;
  nlohmann_json_j["aot_inductor_model_is_cpu"] = nlohmann_json_t.aot_inductor_model_is_cpu;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, AOTInductorModelPickleData& nlohmann_json_t) {
  AOTInductorModelPickleData nlohmann_json_default_obj;
  nlohmann_json_t.library_basename = nlohmann_json_j.value("library_basename", nlohmann_json_default_obj.library_basename);
  nlohmann_json_t.input_names = nlohmann_json_j.value("input_names", nlohmann_json_default_obj.input_names);
  nlohmann_json_t.output_names = nlohmann_json_j.value("output_names", nlohmann_json_default_obj.output_names);
  nlohmann_json_t.floating_point_input_dtype = nlohmann_json_j.value("floating_point_input_dtype", nlohmann_json_default_obj.floating_point_input_dtype);
  nlohmann_json_t.floating_point_output_dtype = nlohmann_json_j.value("floating_point_output_dtype", nlohmann_json_default_obj.floating_point_output_dtype);
  nlohmann_json_t.aot_inductor_model_is_cpu = nlohmann_json_j.value("aot_inductor_model_is_cpu", nlohmann_json_default_obj.aot_inductor_model_is_cpu);
}

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 ComplexValue& nlohmann_json_t) {
  nlohmann_json_j["real"] = nlohmann_json_t.real;
  nlohmann_json_j["imag"] = nlohmann_json_t.imag;
}

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

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;
  nlohmann_json_j["guards_code"] = nlohmann_json_t.guards_code;
}

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);
  nlohmann_json_t.guards_code = nlohmann_json_j.value("guards_code", nlohmann_json_default_obj.guards_code);
}

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

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

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

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

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;
  nlohmann_json_j["treespec_namedtuple_fields"] = nlohmann_json_t.treespec_namedtuple_fields;
}

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);
  nlohmann_json_t.treespec_namedtuple_fields = nlohmann_json_j.value("treespec_namedtuple_fields", nlohmann_json_default_obj.treespec_namedtuple_fields);
}

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;
  nlohmann_json_j["kind"] = nlohmann_json_t.kind;
}

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);
  nlohmann_json_t.kind = nlohmann_json_j.value("kind", nlohmann_json_default_obj.kind);
}

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

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

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;
  nlohmann_json_j["is_hop_single_tensor_return"] = nlohmann_json_t.is_hop_single_tensor_return;
  nlohmann_json_j["name"] = nlohmann_json_t.name;
}

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);
  nlohmann_json_t.is_hop_single_tensor_return = nlohmann_json_j.value("is_hop_single_tensor_return", nlohmann_json_default_obj.is_hop_single_tensor_return);
  nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
}

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 ParameterMutationSpec& 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, ParameterMutationSpec& nlohmann_json_t) {
  ParameterMutationSpec 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 PayloadConfig& nlohmann_json_t) {
  nlohmann_json_j["config"] = nlohmann_json_t.config;
}

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

inline void to_json(nlohmann::json& nlohmann_json_j, const PayloadMeta& nlohmann_json_t) {
  nlohmann_json_j["path_name"] = nlohmann_json_t.path_name;
  nlohmann_json_j["is_param"] = nlohmann_json_t.is_param;
  nlohmann_json_j["use_pickle"] = nlohmann_json_t.use_pickle;
  nlohmann_json_j["tensor_meta"] = nlohmann_json_t.tensor_meta;
}

inline void from_json(const nlohmann::json& nlohmann_json_j, PayloadMeta& nlohmann_json_t) {
  PayloadMeta nlohmann_json_default_obj;
  nlohmann_json_t.path_name = nlohmann_json_j.value("path_name", nlohmann_json_default_obj.path_name);
  nlohmann_json_t.is_param = nlohmann_json_j.value("is_param", nlohmann_json_default_obj.is_param);
  nlohmann_json_t.use_pickle = nlohmann_json_j.value("use_pickle", nlohmann_json_default_obj.use_pickle);
  nlohmann_json_t.tensor_meta = nlohmann_json_j.value("tensor_meta", nlohmann_json_default_obj.tensor_meta);
}

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);
}


template <typename T> ForwardRef<T>::ForwardRef(ForwardRef<T>&&) = default;
template <typename T> ForwardRef<T>& ForwardRef<T>::operator=(ForwardRef<T>&&) = default;
template <typename T> ForwardRef<T>::~ForwardRef() = default;
} // namespace _export
} // namespace torch

// clang-format on

#else
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
#endif  // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
