Class: TurnKit::OutputPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/turnkit/output_policy.rb

Constant Summary collapse

DEFAULT_SCHEMA =
{
  type: "object",
  properties: {
    approved: { type: "boolean" },
    violations: {
      type: "array",
      items: {
        type: "object",
        properties: {
          rule: { type: "string" },
          message: { type: "string" }
        },
        required: [ "rule", "message" ]
      }
    }
  },
  required: [ "approved", "violations" ]
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content:, name: "output_policy", model: nil, thinking: nil, client: nil) ⇒ OutputPolicy

Returns a new instance of OutputPolicy.

Raises:

  • (ArgumentError)


34
35
36
37
38
39
40
41
# File 'lib/turnkit/output_policy.rb', line 34

def initialize(content:, name: "output_policy", model: nil, thinking: nil, client: nil)
  @name = name.to_s
  @content = content.to_s
  @model = model
  @thinking = Agent.normalize_thinking(thinking)
  @client = client
  raise ArgumentError, "content is required" if @content.empty?
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



24
25
26
# File 'lib/turnkit/output_policy.rb', line 24

def client
  @client
end

#contentObject (readonly)

Returns the value of attribute content.



24
25
26
# File 'lib/turnkit/output_policy.rb', line 24

def content
  @content
end

#modelObject (readonly)

Returns the value of attribute model.



24
25
26
# File 'lib/turnkit/output_policy.rb', line 24

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name.



24
25
26
# File 'lib/turnkit/output_policy.rb', line 24

def name
  @name
end

#thinkingObject (readonly)

Returns the value of attribute thinking.



24
25
26
# File 'lib/turnkit/output_policy.rb', line 24

def thinking
  @thinking
end

Class Method Details

.from_file(path, name: nil, **options) ⇒ Object



26
27
28
# File 'lib/turnkit/output_policy.rb', line 26

def self.from_file(path, name: nil, **options)
  new(name: name || File.basename(path, File.extname(path)), content: File.read(path), **options)
end

.from_skill(skill, **options) ⇒ Object



30
31
32
# File 'lib/turnkit/output_policy.rb', line 30

def self.from_skill(skill, **options)
  new(name: skill.key, content: skill.content, **options)
end

Instance Method Details

#call(output, run: nil, turn: nil) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/turnkit/output_policy.rb', line 43

def call(output, run: nil, turn: nil)
  model_name = model || turn&.model || run&.turn&.model || TurnKit.default_model
  result = if turn
    turn.internal_model_call(
      model: model_name,
      messages: audit_messages(output),
      tools: [],
      instructions: audit_instructions,
      thinking: thinking,
      output_schema: DEFAULT_SCHEMA,
      metadata: { output_policy: name },
      purpose: "output_policy",
      client: client
    )
  else
    audit_client = client || TurnKit.client
    audit_client.validate!(model: model_name)
    chat(audit_client, model: model_name, messages: audit_messages(output), tools: [], instructions: audit_instructions, thinking: thinking, output_schema: DEFAULT_SCHEMA, metadata: { output_policy: name })
  end
  data = result.output_data || parse_json(result.text)
  return if data.fetch("approved", false)

  Array(data["violations"]).map do |violation|
    attrs = violation.transform_keys(&:to_s)
    OutputAudit::Violation.new(
      rule: attrs["rule"] || name,
      message: attrs["message"] || "output policy failed",
      metadata: attrs.reject { |key, _| %w[rule message].include?(key) }
    )
  end
end