Created
July 15, 2025 04:06
-
-
Save kieranklaassen/804ba99f5f4bcae3af5705a12b0caab8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PromptReader | |
PROMPTS_DIR = Rails.root.join("app", "prompts") | |
# Reads the content of a prompt file or Leva::Prompt object and renders it with Liquid templating | |
# | |
# @example Read a prompt file without Liquid templating | |
# PromptReader.read("welcome_message") | |
# | |
# @example Read a prompt file with Liquid templating | |
# PromptReader.read("greeting", name: "John") | |
# | |
# @example Read a prompt file in a subfolder | |
# PromptReader.read("chatbot/welcome_message") | |
# PromptReader.read("summaries/newsletter_summary_prompt") | |
# | |
# @example Read a Leva::Prompt object with Liquid templating | |
# leva_prompt = Leva::Prompt.find(1) | |
# PromptReader.read(leva_prompt, name: "John") | |
# | |
# @param prompt [String, Leva::Prompt] the name of the prompt file to read (without extension) or a Leva::Prompt object | |
# Can include subfolder paths like "folder/prompt_name" | |
# @param options [Hash] optional parameters to render within the Liquid template | |
# @return [String, nil] the content of the file or Leva::Prompt, rendered with Liquid templating, or nil if file does not exist | |
def self.read(prompt, **options) | |
content = if prompt.is_a?(Leva::Prompt) | |
prompt.user_prompt | |
else | |
# Support for nested folders by directly joining the path with .md extension | |
file_path = PROMPTS_DIR.join("#{prompt}.md") | |
# If file doesn't exist, try to find it without adding .md (in case it already has an extension) | |
unless File.exist?(file_path) | |
alt_path = PROMPTS_DIR.join(prompt) | |
file_path = alt_path if File.exist?(alt_path) | |
end | |
# Log the file path for debugging | |
Rails.logger.debug("Looking for prompt at: #{file_path}") | |
File.exist?(file_path) ? File.read(file_path) : nil | |
end | |
# Log if content is nil | |
if content.nil? | |
Rails.logger.warn("Prompt content is nil for: #{prompt}") | |
return nil | |
end | |
if options.any? | |
template = Liquid::Template.parse(content) | |
# Ensure missing variables are left intact in the template | |
template_vars = options.transform_keys(&:to_s) | |
missing_keys = template.root.nodelist.select { |node| node.is_a?(Liquid::Variable) && !template_vars.key?(node.name.name) }.map { |node| node.name.name } | |
missing_keys.each { |key| template_vars[key] = "{{ #{key} }}" } | |
template.render(template_vars) | |
else | |
content | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment