Class: LlmLogs::PromptSyncer
- Inherits:
-
Object
- Object
- LlmLogs::PromptSyncer
- Defined in:
- app/services/llm_logs/prompt_syncer.rb
Constant Summary collapse
- REQUIRED_FIELDS =
%w[slug name].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(path:, auto_tag:) ⇒ PromptSyncer
constructor
A new instance of PromptSyncer.
Constructor Details
#initialize(path:, auto_tag:) ⇒ PromptSyncer
Returns a new instance of PromptSyncer.
38 39 40 41 |
# File 'app/services/llm_logs/prompt_syncer.rb', line 38 def initialize(path:, auto_tag:) @path = Pathname.new(path) @auto_tag = auto_tag end |
Class Method Details
.body_file_only?(path) ⇒ Boolean
25 26 27 28 29 30 31 |
# File 'app/services/llm_logs/prompt_syncer.rb', line 25 def self.body_file_only?(path) raw = File.read(path) # Files referenced as body_file targets have no YAML front-matter. # Files with front-matter are prompts and will be validated (missing # slug/name raises a clear error rather than being silently skipped). !raw.start_with?("---") end |
.parse(raw) ⇒ Object
33 34 35 36 |
# File 'app/services/llm_logs/prompt_syncer.rb', line 33 def self.parse(raw) _, front_yaml, body = raw.split(/^---\s*$/, 3) [YAML.safe_load(front_yaml.to_s, permitted_classes: [Symbol], aliases: true) || {}, body.to_s.sub(/\A\n+/, "")] end |
.sync_all(root:, subfolders:) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'app/services/llm_logs/prompt_syncer.rb', line 8 def self.sync_all(root:, subfolders:) root = Pathname.new(root) subfolders.each do |sub| dir = root / sub next unless dir.directory? Dir.glob(dir / "*.md").sort.each do |path| # Skip files that are referenced as body_file targets rather than # top-level prompts — those have no top-level `slug:` and are pulled # in by the parent template instead. pathname = Pathname.new(path) next if body_file_only?(pathname) new(path: pathname, auto_tag: sub).call end end end |
Instance Method Details
#call ⇒ 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 74 75 76 |
# File 'app/services/llm_logs/prompt_syncer.rb', line 43 def call raw = @path.read raise "Missing front-matter in #{@path}" unless raw.start_with?("---") front, body = self.class.parse(raw) REQUIRED_FIELDS.each do |field| raise "Missing required front-matter field '#{field}' in #{@path}" unless front[field].is_a?(String) && !front[field].strip.empty? end ActiveRecord::Base.transaction do = (Array(front["tags"]) + [@auto_tag]).map(&:to_s).uniq prompt = LlmLogs::Prompt.find_or_initialize_by(slug: front["slug"]) created = prompt.new_record? prompt.name = front["name"] prompt.description = front["description"] prompt. = prompt.save! = (front, body) model = front["model"] model_params = front["model_params"].is_a?(Hash) ? front["model_params"] : {} model_params = model_params.deep_stringify_keys if version_needs_update?(prompt, , model, model_params) prompt.update_content!(messages: , model: model, model_params: model_params, changelog: "Synced from #{@path.basename}") status = created ? "Created" : "Updated" else status = "Unchanged" end log "#{status}: #{prompt.slug}" end end |