tork-governance 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +425 -0
- data/Rakefile +38 -0
- data/lib/tork/client.rb +228 -0
- data/lib/tork/configuration.rb +73 -0
- data/lib/tork/errors.rb +84 -0
- data/lib/tork/resources/evaluation.rb +115 -0
- data/lib/tork/resources/metrics.rb +122 -0
- data/lib/tork/resources/policy.rb +115 -0
- data/lib/tork/version.rb +5 -0
- data/lib/tork.rb +85 -0
- data/tork-governance.gemspec +53 -0
- metadata +217 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tork
|
|
4
|
+
# Configuration class for Tork SDK
|
|
5
|
+
class Configuration
|
|
6
|
+
# @return [String] The API key for authentication
|
|
7
|
+
attr_accessor :api_key
|
|
8
|
+
|
|
9
|
+
# @return [String] The base URL for the Tork API
|
|
10
|
+
attr_accessor :base_url
|
|
11
|
+
|
|
12
|
+
# @return [Integer] Request timeout in seconds
|
|
13
|
+
attr_accessor :timeout
|
|
14
|
+
|
|
15
|
+
# @return [Integer] Maximum number of retries for failed requests
|
|
16
|
+
attr_accessor :max_retries
|
|
17
|
+
|
|
18
|
+
# @return [Float] Base delay for exponential backoff (in seconds)
|
|
19
|
+
attr_accessor :retry_base_delay
|
|
20
|
+
|
|
21
|
+
# @return [Float] Maximum delay between retries (in seconds)
|
|
22
|
+
attr_accessor :retry_max_delay
|
|
23
|
+
|
|
24
|
+
# @return [Boolean] Whether to raise on rate limit or return error response
|
|
25
|
+
attr_accessor :raise_on_rate_limit
|
|
26
|
+
|
|
27
|
+
# @return [Logger, nil] Logger instance for debugging
|
|
28
|
+
attr_accessor :logger
|
|
29
|
+
|
|
30
|
+
# @return [String, nil] Custom user agent string
|
|
31
|
+
attr_accessor :user_agent
|
|
32
|
+
|
|
33
|
+
# Default configuration values
|
|
34
|
+
DEFAULTS = {
|
|
35
|
+
base_url: "https://api.tork.network/v1",
|
|
36
|
+
timeout: 30,
|
|
37
|
+
max_retries: 3,
|
|
38
|
+
retry_base_delay: 0.5,
|
|
39
|
+
retry_max_delay: 30.0,
|
|
40
|
+
raise_on_rate_limit: true,
|
|
41
|
+
logger: nil,
|
|
42
|
+
user_agent: nil
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
def initialize
|
|
46
|
+
DEFAULTS.each do |key, value|
|
|
47
|
+
send("#{key}=", value)
|
|
48
|
+
end
|
|
49
|
+
@api_key = ENV["TORK_API_KEY"]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Validate the configuration
|
|
53
|
+
# @raise [Tork::AuthenticationError] if API key is missing
|
|
54
|
+
def validate!
|
|
55
|
+
raise AuthenticationError, "API key is required" if api_key.nil? || api_key.empty?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Reset configuration to defaults
|
|
59
|
+
def reset!
|
|
60
|
+
DEFAULTS.each do |key, value|
|
|
61
|
+
send("#{key}=", value)
|
|
62
|
+
end
|
|
63
|
+
@api_key = ENV["TORK_API_KEY"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Build user agent string
|
|
67
|
+
# @return [String]
|
|
68
|
+
def full_user_agent
|
|
69
|
+
base = "tork-ruby/#{Tork::VERSION} Ruby/#{RUBY_VERSION}"
|
|
70
|
+
user_agent ? "#{user_agent} #{base}" : base
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/tork/errors.rb
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tork
|
|
4
|
+
# Base error class for all Tork errors
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
attr_reader :http_status, :code, :details
|
|
7
|
+
|
|
8
|
+
def initialize(message = nil, http_status: nil, code: nil, details: nil)
|
|
9
|
+
@http_status = http_status
|
|
10
|
+
@code = code
|
|
11
|
+
@details = details
|
|
12
|
+
super(message)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Raised when API authentication fails
|
|
17
|
+
class AuthenticationError < Error
|
|
18
|
+
def initialize(message = "Invalid or missing API key")
|
|
19
|
+
super(message, http_status: 401, code: "AUTHENTICATION_ERROR")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised when rate limit is exceeded
|
|
24
|
+
class RateLimitError < Error
|
|
25
|
+
attr_reader :retry_after
|
|
26
|
+
|
|
27
|
+
def initialize(message = "Rate limit exceeded", retry_after: nil)
|
|
28
|
+
@retry_after = retry_after
|
|
29
|
+
super(message, http_status: 429, code: "RATE_LIMIT_ERROR")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Raised when a resource is not found
|
|
34
|
+
class NotFoundError < Error
|
|
35
|
+
def initialize(message = "Resource not found")
|
|
36
|
+
super(message, http_status: 404, code: "NOT_FOUND")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Raised when request validation fails
|
|
41
|
+
class ValidationError < Error
|
|
42
|
+
def initialize(message = "Validation failed", details: nil)
|
|
43
|
+
super(message, http_status: 400, code: "VALIDATION_ERROR", details: details)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Raised when the server returns an error
|
|
48
|
+
class ServerError < Error
|
|
49
|
+
def initialize(message = "Server error")
|
|
50
|
+
super(message, http_status: 500, code: "SERVER_ERROR")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Raised when a request times out
|
|
55
|
+
class TimeoutError < Error
|
|
56
|
+
def initialize(message = "Request timed out")
|
|
57
|
+
super(message, code: "TIMEOUT_ERROR")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Raised when a connection cannot be established
|
|
62
|
+
class ConnectionError < Error
|
|
63
|
+
def initialize(message = "Failed to connect to Tork API")
|
|
64
|
+
super(message, code: "CONNECTION_ERROR")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Raised when a policy violation is detected
|
|
69
|
+
class PolicyViolationError < Error
|
|
70
|
+
attr_reader :violations
|
|
71
|
+
|
|
72
|
+
def initialize(message = "Policy violation detected", violations: [])
|
|
73
|
+
@violations = violations
|
|
74
|
+
super(message, http_status: 422, code: "POLICY_VIOLATION")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Raised when usage limit is exceeded
|
|
79
|
+
class UsageLimitError < Error
|
|
80
|
+
def initialize(message = "Usage limit exceeded")
|
|
81
|
+
super(message, http_status: 429, code: "USAGE_LIMIT_ERROR")
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tork
|
|
4
|
+
module Resources
|
|
5
|
+
# Evaluation resource for content evaluation
|
|
6
|
+
class Evaluation
|
|
7
|
+
# @param client [Tork::Client] The API client
|
|
8
|
+
def initialize(client)
|
|
9
|
+
@client = client
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Evaluate content against policies
|
|
13
|
+
# @param prompt [String] The prompt/input to evaluate
|
|
14
|
+
# @param response [String, nil] The response/output to evaluate
|
|
15
|
+
# @param policy_id [String, nil] Specific policy ID (uses default if nil)
|
|
16
|
+
# @param checks [Array<String>] Checks to perform (pii, toxicity, moderation)
|
|
17
|
+
# @param options [Hash] Additional options
|
|
18
|
+
# @return [Hash] Evaluation result
|
|
19
|
+
def create(prompt:, response: nil, policy_id: nil, checks: nil, **options)
|
|
20
|
+
body = { content: prompt }
|
|
21
|
+
body[:response] = response if response
|
|
22
|
+
body[:policy_id] = policy_id if policy_id
|
|
23
|
+
body[:checks] = checks if checks
|
|
24
|
+
body.merge!(options) unless options.empty?
|
|
25
|
+
|
|
26
|
+
@client.post("/evaluate", body)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Get an evaluation by ID
|
|
30
|
+
# @param id [String] Evaluation ID
|
|
31
|
+
# @return [Hash] Evaluation details
|
|
32
|
+
def get(id)
|
|
33
|
+
@client.get("/evaluations/#{id}")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# List recent evaluations
|
|
37
|
+
# @param page [Integer] Page number
|
|
38
|
+
# @param per_page [Integer] Items per page
|
|
39
|
+
# @param policy_id [String, nil] Filter by policy
|
|
40
|
+
# @param status [String, nil] Filter by status (passed, failed, flagged)
|
|
41
|
+
# @param start_date [String, nil] Start date (ISO 8601)
|
|
42
|
+
# @param end_date [String, nil] End date (ISO 8601)
|
|
43
|
+
# @return [Hash] List of evaluations
|
|
44
|
+
def list(page: 1, per_page: 20, policy_id: nil, status: nil, start_date: nil, end_date: nil)
|
|
45
|
+
params = { page: page, per_page: per_page }
|
|
46
|
+
params[:policy_id] = policy_id if policy_id
|
|
47
|
+
params[:status] = status if status
|
|
48
|
+
params[:start_date] = start_date if start_date
|
|
49
|
+
params[:end_date] = end_date if end_date
|
|
50
|
+
@client.get("/evaluations", params)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Batch evaluate multiple content items
|
|
54
|
+
# @param items [Array<Hash>] Array of items to evaluate
|
|
55
|
+
# @param policy_id [String, nil] Policy to apply to all
|
|
56
|
+
# @return [Hash] Batch evaluation results
|
|
57
|
+
def batch(items, policy_id: nil)
|
|
58
|
+
body = { items: items }
|
|
59
|
+
body[:policy_id] = policy_id if policy_id
|
|
60
|
+
@client.post("/evaluate/batch", body)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Evaluate and get detailed analysis
|
|
64
|
+
# @param prompt [String] Content to analyze
|
|
65
|
+
# @param analysis_types [Array<String>] Types of analysis
|
|
66
|
+
# @return [Hash] Detailed analysis
|
|
67
|
+
def analyze(prompt:, analysis_types: %w[pii toxicity sentiment topics])
|
|
68
|
+
@client.post("/evaluate/analyze", {
|
|
69
|
+
content: prompt,
|
|
70
|
+
analysis_types: analysis_types
|
|
71
|
+
})
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Check PII in content
|
|
75
|
+
# @param content [String] Content to check
|
|
76
|
+
# @param pii_types [Array<String>, nil] Specific PII types to detect
|
|
77
|
+
# @param redact [Boolean] Whether to return redacted version
|
|
78
|
+
# @return [Hash] PII detection results
|
|
79
|
+
def detect_pii(content:, pii_types: nil, redact: false)
|
|
80
|
+
body = { content: content, redact: redact }
|
|
81
|
+
body[:pii_types] = pii_types if pii_types
|
|
82
|
+
@client.post("/pii/detect", body)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Redact PII from content
|
|
86
|
+
# @param content [String] Content to redact
|
|
87
|
+
# @param pii_types [Array<String>, nil] Specific PII types to redact
|
|
88
|
+
# @param replacement [String] Replacement format (mask, type, custom)
|
|
89
|
+
# @return [Hash] Redacted content
|
|
90
|
+
def redact_pii(content:, pii_types: nil, replacement: "mask")
|
|
91
|
+
body = { content: content, replacement: replacement }
|
|
92
|
+
body[:pii_types] = pii_types if pii_types
|
|
93
|
+
@client.post("/pii/redact", body)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Check for jailbreak attempts
|
|
97
|
+
# @param prompt [String] Prompt to check
|
|
98
|
+
# @return [Hash] Jailbreak detection results
|
|
99
|
+
def detect_jailbreak(prompt:)
|
|
100
|
+
@client.post("/jailbreak/detect", { prompt: prompt })
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Validate RAG chunks
|
|
104
|
+
# @param chunks [Array<Hash>] RAG chunks to validate
|
|
105
|
+
# @param query [String] Original query
|
|
106
|
+
# @return [Hash] Validation results
|
|
107
|
+
def validate_rag(chunks:, query:)
|
|
108
|
+
@client.post("/rag/validate", {
|
|
109
|
+
chunks: chunks,
|
|
110
|
+
query: query
|
|
111
|
+
})
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tork
|
|
4
|
+
module Resources
|
|
5
|
+
# Metrics resource for analytics and reporting
|
|
6
|
+
class Metrics
|
|
7
|
+
# @param client [Tork::Client] The API client
|
|
8
|
+
def initialize(client)
|
|
9
|
+
@client = client
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Get Torking X score for an evaluation
|
|
13
|
+
# @param evaluation_id [String] Evaluation ID
|
|
14
|
+
# @return [Hash] Torking X metrics
|
|
15
|
+
def torking_x(evaluation_id:)
|
|
16
|
+
@client.get("/metrics/torking-x/#{evaluation_id}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Get usage statistics
|
|
20
|
+
# @param period [String] Time period (day, week, month, year)
|
|
21
|
+
# @param start_date [String, nil] Start date (ISO 8601)
|
|
22
|
+
# @param end_date [String, nil] End date (ISO 8601)
|
|
23
|
+
# @return [Hash] Usage statistics
|
|
24
|
+
def usage(period: "month", start_date: nil, end_date: nil)
|
|
25
|
+
params = { period: period }
|
|
26
|
+
params[:start_date] = start_date if start_date
|
|
27
|
+
params[:end_date] = end_date if end_date
|
|
28
|
+
@client.get("/metrics/usage", params)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Get policy performance metrics
|
|
32
|
+
# @param policy_id [String, nil] Specific policy ID
|
|
33
|
+
# @param period [String] Time period
|
|
34
|
+
# @return [Hash] Policy metrics
|
|
35
|
+
def policy_performance(policy_id: nil, period: "month")
|
|
36
|
+
params = { period: period }
|
|
37
|
+
params[:policy_id] = policy_id if policy_id
|
|
38
|
+
@client.get("/metrics/policies", params)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Get violation statistics
|
|
42
|
+
# @param period [String] Time period
|
|
43
|
+
# @param group_by [String] Grouping (policy, type, severity)
|
|
44
|
+
# @return [Hash] Violation statistics
|
|
45
|
+
def violations(period: "month", group_by: "type")
|
|
46
|
+
@client.get("/metrics/violations", {
|
|
47
|
+
period: period,
|
|
48
|
+
group_by: group_by
|
|
49
|
+
})
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Get PII detection statistics
|
|
53
|
+
# @param period [String] Time period
|
|
54
|
+
# @return [Hash] PII statistics
|
|
55
|
+
def pii_stats(period: "month")
|
|
56
|
+
@client.get("/metrics/pii", { period: period })
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Get latency metrics
|
|
60
|
+
# @param period [String] Time period
|
|
61
|
+
# @param percentiles [Array<Integer>] Percentiles to calculate
|
|
62
|
+
# @return [Hash] Latency metrics
|
|
63
|
+
def latency(period: "day", percentiles: [50, 95, 99])
|
|
64
|
+
@client.get("/metrics/latency", {
|
|
65
|
+
period: period,
|
|
66
|
+
percentiles: percentiles.join(",")
|
|
67
|
+
})
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Get cost metrics
|
|
71
|
+
# @param period [String] Time period
|
|
72
|
+
# @param group_by [String] Grouping (day, policy, model)
|
|
73
|
+
# @return [Hash] Cost breakdown
|
|
74
|
+
def costs(period: "month", group_by: "day")
|
|
75
|
+
@client.get("/metrics/costs", {
|
|
76
|
+
period: period,
|
|
77
|
+
group_by: group_by
|
|
78
|
+
})
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get real-time metrics
|
|
82
|
+
# @return [Hash] Current metrics snapshot
|
|
83
|
+
def realtime
|
|
84
|
+
@client.get("/metrics/realtime")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Get compliance report
|
|
88
|
+
# @param start_date [String] Start date (ISO 8601)
|
|
89
|
+
# @param end_date [String] End date (ISO 8601)
|
|
90
|
+
# @param format [String] Report format (json, pdf)
|
|
91
|
+
# @return [Hash] Compliance report data
|
|
92
|
+
def compliance_report(start_date:, end_date:, format: "json")
|
|
93
|
+
@client.get("/metrics/compliance", {
|
|
94
|
+
start_date: start_date,
|
|
95
|
+
end_date: end_date,
|
|
96
|
+
format: format
|
|
97
|
+
})
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Get dashboard summary
|
|
101
|
+
# @return [Hash] Dashboard metrics
|
|
102
|
+
def dashboard
|
|
103
|
+
@client.get("/metrics/dashboard")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Export metrics
|
|
107
|
+
# @param type [String] Export type (usage, violations, costs)
|
|
108
|
+
# @param start_date [String] Start date
|
|
109
|
+
# @param end_date [String] End date
|
|
110
|
+
# @param format [String] Export format (csv, json)
|
|
111
|
+
# @return [Hash] Export URL or data
|
|
112
|
+
def export(type:, start_date:, end_date:, format: "csv")
|
|
113
|
+
@client.post("/metrics/export", {
|
|
114
|
+
type: type,
|
|
115
|
+
start_date: start_date,
|
|
116
|
+
end_date: end_date,
|
|
117
|
+
format: format
|
|
118
|
+
})
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tork
|
|
4
|
+
module Resources
|
|
5
|
+
# Policy resource for managing governance policies
|
|
6
|
+
class Policy
|
|
7
|
+
# @param client [Tork::Client] The API client
|
|
8
|
+
def initialize(client)
|
|
9
|
+
@client = client
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# List all policies
|
|
13
|
+
# @param page [Integer] Page number (default: 1)
|
|
14
|
+
# @param per_page [Integer] Items per page (default: 20)
|
|
15
|
+
# @param status [String, nil] Filter by status (active, draft, archived)
|
|
16
|
+
# @return [Hash] List of policies with pagination info
|
|
17
|
+
def list(page: 1, per_page: 20, status: nil)
|
|
18
|
+
params = { page: page, per_page: per_page }
|
|
19
|
+
params[:status] = status if status
|
|
20
|
+
@client.get("/policies", params)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Get a specific policy
|
|
24
|
+
# @param id [String] Policy ID
|
|
25
|
+
# @return [Hash] Policy details
|
|
26
|
+
def get(id)
|
|
27
|
+
@client.get("/policies/#{id}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Create a new policy
|
|
31
|
+
# @param name [String] Policy name
|
|
32
|
+
# @param description [String, nil] Policy description
|
|
33
|
+
# @param rules [Array<Hash>] Policy rules
|
|
34
|
+
# @param enabled [Boolean] Whether policy is enabled (default: true)
|
|
35
|
+
# @param options [Hash] Additional options
|
|
36
|
+
# @return [Hash] Created policy
|
|
37
|
+
def create(name:, rules:, description: nil, enabled: true, **options)
|
|
38
|
+
body = {
|
|
39
|
+
name: name,
|
|
40
|
+
rules: rules,
|
|
41
|
+
enabled: enabled,
|
|
42
|
+
**options
|
|
43
|
+
}
|
|
44
|
+
body[:description] = description if description
|
|
45
|
+
@client.post("/policies", body)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Update a policy
|
|
49
|
+
# @param id [String] Policy ID
|
|
50
|
+
# @param attributes [Hash] Attributes to update
|
|
51
|
+
# @return [Hash] Updated policy
|
|
52
|
+
def update(id, **attributes)
|
|
53
|
+
@client.patch("/policies/#{id}", attributes)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Delete a policy
|
|
57
|
+
# @param id [String] Policy ID
|
|
58
|
+
# @return [Hash] Deletion confirmation
|
|
59
|
+
def delete(id)
|
|
60
|
+
@client.delete("/policies/#{id}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Duplicate a policy
|
|
64
|
+
# @param id [String] Policy ID to duplicate
|
|
65
|
+
# @param name [String, nil] New name for the duplicate
|
|
66
|
+
# @return [Hash] Duplicated policy
|
|
67
|
+
def duplicate(id, name: nil)
|
|
68
|
+
body = {}
|
|
69
|
+
body[:name] = name if name
|
|
70
|
+
@client.post("/policies/#{id}/duplicate", body)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Enable a policy
|
|
74
|
+
# @param id [String] Policy ID
|
|
75
|
+
# @return [Hash] Updated policy
|
|
76
|
+
def enable(id)
|
|
77
|
+
update(id, enabled: true)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Disable a policy
|
|
81
|
+
# @param id [String] Policy ID
|
|
82
|
+
# @return [Hash] Updated policy
|
|
83
|
+
def disable(id)
|
|
84
|
+
update(id, enabled: false)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Get policy versions
|
|
88
|
+
# @param id [String] Policy ID
|
|
89
|
+
# @return [Hash] List of versions
|
|
90
|
+
def versions(id)
|
|
91
|
+
@client.get("/policies/#{id}/versions")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Restore a policy version
|
|
95
|
+
# @param id [String] Policy ID
|
|
96
|
+
# @param version_id [String] Version ID to restore
|
|
97
|
+
# @return [Hash] Restored policy
|
|
98
|
+
def restore_version(id, version_id)
|
|
99
|
+
@client.post("/policies/#{id}/versions/#{version_id}/restore")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Test a policy with sample content
|
|
103
|
+
# @param id [String] Policy ID
|
|
104
|
+
# @param content [String] Content to test
|
|
105
|
+
# @param context [Hash] Additional context
|
|
106
|
+
# @return [Hash] Test results
|
|
107
|
+
def test(id, content:, context: {})
|
|
108
|
+
@client.post("/policies/#{id}/test", {
|
|
109
|
+
content: content,
|
|
110
|
+
context: context
|
|
111
|
+
})
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
data/lib/tork/version.rb
ADDED
data/lib/tork.rb
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tork/version"
|
|
4
|
+
require_relative "tork/errors"
|
|
5
|
+
require_relative "tork/configuration"
|
|
6
|
+
require_relative "tork/client"
|
|
7
|
+
require_relative "tork/resources/policy"
|
|
8
|
+
require_relative "tork/resources/evaluation"
|
|
9
|
+
require_relative "tork/resources/metrics"
|
|
10
|
+
|
|
11
|
+
# Tork AI Governance SDK for Ruby
|
|
12
|
+
#
|
|
13
|
+
# @example Basic usage
|
|
14
|
+
# Tork.configure do |config|
|
|
15
|
+
# config.api_key = "tork_your_api_key"
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# client = Tork::Client.new
|
|
19
|
+
# result = client.evaluate(prompt: "Hello world")
|
|
20
|
+
#
|
|
21
|
+
# @example Direct client initialization
|
|
22
|
+
# client = Tork::Client.new(api_key: "tork_your_api_key")
|
|
23
|
+
# result = client.evaluate(prompt: "Hello world")
|
|
24
|
+
#
|
|
25
|
+
module Tork
|
|
26
|
+
class << self
|
|
27
|
+
# @return [Configuration] Global configuration instance
|
|
28
|
+
def configuration
|
|
29
|
+
@configuration ||= Configuration.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Configure the Tork SDK
|
|
33
|
+
# @yield [Configuration] Configuration instance
|
|
34
|
+
# @example
|
|
35
|
+
# Tork.configure do |config|
|
|
36
|
+
# config.api_key = "tork_your_api_key"
|
|
37
|
+
# config.timeout = 60
|
|
38
|
+
# end
|
|
39
|
+
def configure
|
|
40
|
+
yield(configuration)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Reset configuration to defaults
|
|
44
|
+
def reset_configuration!
|
|
45
|
+
@configuration = Configuration.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Create a new client with global configuration
|
|
49
|
+
# @return [Client]
|
|
50
|
+
def client
|
|
51
|
+
@client ||= Client.new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Reset the default client
|
|
55
|
+
def reset_client!
|
|
56
|
+
@client = nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Convenience method to evaluate content
|
|
60
|
+
# @param prompt [String] Content to evaluate
|
|
61
|
+
# @param options [Hash] Additional options
|
|
62
|
+
# @return [Hash] Evaluation result
|
|
63
|
+
def evaluate(prompt:, **options)
|
|
64
|
+
client.evaluate(prompt: prompt, **options)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Access policies via default client
|
|
68
|
+
# @return [Resources::Policy]
|
|
69
|
+
def policies
|
|
70
|
+
client.policies
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Access evaluations via default client
|
|
74
|
+
# @return [Resources::Evaluation]
|
|
75
|
+
def evaluations
|
|
76
|
+
client.evaluations
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Access metrics via default client
|
|
80
|
+
# @return [Resources::Metrics]
|
|
81
|
+
def metrics
|
|
82
|
+
client.metrics
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/tork/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "tork-governance"
|
|
7
|
+
spec.version = Tork::VERSION
|
|
8
|
+
spec.authors = ["Tork Network"]
|
|
9
|
+
spec.email = ["support@tork.network"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Ruby SDK for Tork AI Governance Platform"
|
|
12
|
+
spec.description = <<~DESC
|
|
13
|
+
Official Ruby SDK for the Tork AI Governance Platform. Provides comprehensive
|
|
14
|
+
tools for AI safety, content moderation, PII detection, policy enforcement,
|
|
15
|
+
and compliance monitoring for LLM applications.
|
|
16
|
+
DESC
|
|
17
|
+
spec.homepage = "https://tork.network"
|
|
18
|
+
spec.license = "MIT"
|
|
19
|
+
spec.required_ruby_version = ">= 2.7.0"
|
|
20
|
+
|
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["source_code_uri"] = "https://github.com/torkjacobs/tork-ruby-sdk"
|
|
23
|
+
spec.metadata["changelog_uri"] = "https://github.com/torkjacobs/tork-ruby-sdk/blob/main/CHANGELOG.md"
|
|
24
|
+
spec.metadata["documentation_uri"] = "https://docs.tork.network/sdks/ruby"
|
|
25
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/torkjacobs/tork-ruby-sdk/issues"
|
|
26
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
27
|
+
|
|
28
|
+
# Specify which files should be added to the gem
|
|
29
|
+
spec.files = Dir.chdir(__dir__) do
|
|
30
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
31
|
+
(File.expand_path(f) == __FILE__) ||
|
|
32
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
spec.bindir = "exe"
|
|
36
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
37
|
+
spec.require_paths = ["lib"]
|
|
38
|
+
|
|
39
|
+
# Runtime dependencies
|
|
40
|
+
spec.add_dependency "faraday", "~> 2.0"
|
|
41
|
+
spec.add_dependency "faraday-retry", "~> 2.0"
|
|
42
|
+
|
|
43
|
+
# Development dependencies
|
|
44
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
|
45
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
46
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
47
|
+
spec.add_development_dependency "rubocop", "~> 1.0"
|
|
48
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.0"
|
|
49
|
+
spec.add_development_dependency "simplecov", "~> 0.22"
|
|
50
|
+
spec.add_development_dependency "vcr", "~> 6.0"
|
|
51
|
+
spec.add_development_dependency "webmock", "~> 3.0"
|
|
52
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
|
53
|
+
end
|