lex-prompt 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/lib/legion/extensions/prompt/client.rb +16 -0
- data/lib/legion/extensions/prompt/helpers/template_renderer.rb +30 -0
- data/lib/legion/extensions/prompt/runners/prompt.rb +111 -0
- data/lib/legion/extensions/prompt/version.rb +9 -0
- data/lib/legion/extensions/prompt.rb +14 -0
- metadata +47 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: '0790ff654b0cbe3cd763f78988e7392301a4e51532a45f94ab31f13911547803'
|
|
4
|
+
data.tar.gz: 118bf80427c47630a7a551634fe963fb10fe4bd2ed5363ead4d3d334bcb7b299
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a037896893b6dbbb6832328029c941c69972a367f7fbbdf0ebba0b3f29a1118c6345e77db43f0e47490e646275040bde14c3884380785465f5a95cef1f079799
|
|
7
|
+
data.tar.gz: ed3e3334cb08cf1422538b7b848a376d508411763bd41036f43212608c39d5fdb40a98170792d14aaaa1a66ea8668d42f368ca53bef223a5eff37c412be03748
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Prompt
|
|
8
|
+
module Helpers
|
|
9
|
+
module TemplateRenderer
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def render(template, variables: {})
|
|
13
|
+
result = template.dup
|
|
14
|
+
variables.each { |key, val| result.gsub!("{{#{key}}}", val.to_s) }
|
|
15
|
+
result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extract_variables(template)
|
|
19
|
+
template.scan(/\{\{(\w+)\}\}/).flatten.uniq
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def content_hash(template, model_params = {})
|
|
23
|
+
payload = "#{template}|#{model_params.sort}"
|
|
24
|
+
OpenSSL::Digest.new('SHA256').hexdigest(payload)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Prompt
|
|
6
|
+
module Runners
|
|
7
|
+
module Prompt
|
|
8
|
+
def create_prompt(name:, template:, description: nil, model_params: {}, **)
|
|
9
|
+
now = Time.now.utc
|
|
10
|
+
prompt_id = db[:prompts].insert(name: name, description: description, created_at: now, updated_at: now)
|
|
11
|
+
hash = Helpers::TemplateRenderer.content_hash(template, model_params)
|
|
12
|
+
db[:prompt_versions].insert(
|
|
13
|
+
prompt_id: prompt_id, version: 1, template: template,
|
|
14
|
+
model_params: serialize_params(model_params), content_hash: hash, created_at: now
|
|
15
|
+
)
|
|
16
|
+
{ created: true, name: name, version: 1, prompt_id: prompt_id }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update_prompt(name:, template:, model_params: {}, **)
|
|
20
|
+
prompt = db[:prompts].where(name: name).first
|
|
21
|
+
return { error: 'not_found' } unless prompt
|
|
22
|
+
|
|
23
|
+
hash = Helpers::TemplateRenderer.content_hash(template, model_params)
|
|
24
|
+
latest = db[:prompt_versions].where(prompt_id: prompt[:id]).order(Sequel.desc(:version)).first
|
|
25
|
+
return { updated: false, reason: 'no_change' } if latest && latest[:content_hash] == hash
|
|
26
|
+
|
|
27
|
+
new_version = (latest ? latest[:version] : 0) + 1
|
|
28
|
+
db[:prompt_versions].insert(
|
|
29
|
+
prompt_id: prompt[:id], version: new_version, template: template,
|
|
30
|
+
model_params: serialize_params(model_params), content_hash: hash, created_at: Time.now.utc
|
|
31
|
+
)
|
|
32
|
+
db[:prompts].where(id: prompt[:id]).update(updated_at: Time.now.utc)
|
|
33
|
+
{ updated: true, name: name, version: new_version }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def get_prompt(name:, version: nil, tag: nil, **)
|
|
37
|
+
prompt = db[:prompts].where(name: name).first
|
|
38
|
+
return { error: 'not_found' } unless prompt
|
|
39
|
+
|
|
40
|
+
pv = resolve_version(prompt[:id], version: version, tag: tag)
|
|
41
|
+
return { error: 'version_not_found' } unless pv
|
|
42
|
+
|
|
43
|
+
{ name: name, version: pv[:version], template: pv[:template],
|
|
44
|
+
model_params: deserialize_params(pv[:model_params]),
|
|
45
|
+
content_hash: pv[:content_hash], created_at: pv[:created_at] }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def list_prompts(**)
|
|
49
|
+
db[:prompts].all.map do |prompt|
|
|
50
|
+
latest = db[:prompt_versions].where(prompt_id: prompt[:id]).order(Sequel.desc(:version)).first
|
|
51
|
+
{ name: prompt[:name], description: prompt[:description],
|
|
52
|
+
latest_version: latest ? latest[:version] : nil, updated_at: prompt[:updated_at] }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def tag_prompt(name:, tag:, version: nil, **)
|
|
57
|
+
prompt = db[:prompts].where(name: name).first
|
|
58
|
+
return { error: 'not_found' } unless prompt
|
|
59
|
+
|
|
60
|
+
pv = resolve_version(prompt[:id], version: version)
|
|
61
|
+
return { error: 'version_not_found' } unless pv
|
|
62
|
+
|
|
63
|
+
db[:prompt_tags].insert_conflict(target: %i[prompt_id tag], update: { version_id: pv[:id] })
|
|
64
|
+
.insert(prompt_id: prompt[:id], tag: tag, version_id: pv[:id], created_at: Time.now.utc)
|
|
65
|
+
{ tagged: true, name: name, tag: tag, version: pv[:version] }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def render_prompt(name:, variables: {}, version: nil, tag: nil, **)
|
|
69
|
+
pv = get_prompt(name: name, version: version, tag: tag)
|
|
70
|
+
return pv if pv[:error]
|
|
71
|
+
|
|
72
|
+
rendered = Helpers::TemplateRenderer.render(pv[:template], variables: variables)
|
|
73
|
+
{ rendered: rendered, prompt_version: pv[:version] }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def resolve_version(prompt_id, version: nil, tag: nil)
|
|
79
|
+
if tag
|
|
80
|
+
tag_row = db[:prompt_tags].where(prompt_id: prompt_id, tag: tag).first
|
|
81
|
+
tag_row ? db[:prompt_versions].where(id: tag_row[:version_id]).first : nil
|
|
82
|
+
elsif version
|
|
83
|
+
db[:prompt_versions].where(prompt_id: prompt_id, version: version).first
|
|
84
|
+
else
|
|
85
|
+
db[:prompt_versions].where(prompt_id: prompt_id).order(Sequel.desc(:version)).first
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def serialize_params(params)
|
|
90
|
+
return '{}' if params.nil? || params.empty?
|
|
91
|
+
|
|
92
|
+
::JSON.dump(params)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def deserialize_params(raw)
|
|
96
|
+
return {} if raw.nil? || raw.empty? || raw == '{}'
|
|
97
|
+
|
|
98
|
+
result = ::JSON.parse(raw)
|
|
99
|
+
result.is_a?(Hash) ? result.transform_keys(&:to_sym) : {}
|
|
100
|
+
rescue ::JSON::ParserError
|
|
101
|
+
{}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def db
|
|
105
|
+
@db
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'prompt/version'
|
|
4
|
+
require_relative 'prompt/helpers/template_renderer'
|
|
5
|
+
require_relative 'prompt/runners/prompt'
|
|
6
|
+
require_relative 'prompt/client'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Prompt
|
|
11
|
+
extend Legion::Extensions::Core if defined?(Legion::Extensions::Core)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-prompt
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Matthew Iverson
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Provides versioned prompt storage with immutable versions, tagged releases,
|
|
13
|
+
template rendering, and a playground for testing prompts.
|
|
14
|
+
email:
|
|
15
|
+
- matt@iverson.io
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- lib/legion/extensions/prompt.rb
|
|
21
|
+
- lib/legion/extensions/prompt/client.rb
|
|
22
|
+
- lib/legion/extensions/prompt/helpers/template_renderer.rb
|
|
23
|
+
- lib/legion/extensions/prompt/runners/prompt.rb
|
|
24
|
+
- lib/legion/extensions/prompt/version.rb
|
|
25
|
+
homepage: https://github.com/LegionIO/lex-prompt
|
|
26
|
+
licenses:
|
|
27
|
+
- MIT
|
|
28
|
+
metadata:
|
|
29
|
+
rubygems_mfa_required: 'true'
|
|
30
|
+
rdoc_options: []
|
|
31
|
+
require_paths:
|
|
32
|
+
- lib
|
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '3.4'
|
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
requirements: []
|
|
44
|
+
rubygems_version: 3.6.9
|
|
45
|
+
specification_version: 4
|
|
46
|
+
summary: Versioned prompt management for LegionIO
|
|
47
|
+
test_files: []
|