langchainrb icon indicating copy to clipboard operation
langchainrb copied to clipboard

Langchain::Prompt.load_from_path fails when loading yaml

Open johnknapp opened this issue 2 years ago • 6 comments

This is my first project using lanchain-rb and I am so glad to leave python on the shelf for now!

Anyway, prompt = Langchain::Prompt.load_from_path(file_path: 'prompts/foo.yaml') is failing with error /gems/psych-5.1.1.1/lib/psych/class_loader.rb:99:in find': Tried to load unspecified class: Symbol (Psych::DisallowedClass)

The failure is caused by a security fix in psych gem (prohibiting symbols) so you may want to do something with your gemspec or whatever. (By the way, adding psych to my Gemfile backdated to 4.0.1 and requiring it didn't solve my langchain-rb issue. (that's what psych issues for this error recommend))

I'll need to use json for now but would prefer to use yaml.

The trace is below.

prompt = Langchain::Prompt.load_from_path(file_path: 'prompts/foo.yaml')
/Users/jk/.rvm/gems/ruby-3.2.2@foo/gems/psych-5.1.1.1/lib/psych/class_loader.rb:99:in `find': Tried to load unspecified class: Symbol (Psych::DisallowedClass)
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/class_loader.rb:28:in `load'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/class_loader.rb:40:in `symbol'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/class_loader.rb:32:in `symbolize'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/class_loader.rb:84:in `symbolize'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/scalar_scanner.rb:80:in `tokenize'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:65:in `deserialize'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:130:in `visit_Psych_Nodes_Scalar'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/visitor.rb:30:in `visit'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/visitor.rb:6:in `accept'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:35:in `accept'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:346:in `block in revive_hash'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:345:in `each'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:345:in `each_slice'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:345:in `revive_hash'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/to_ruby.rb:169:in `visit_Psych_Nodes_Mapping'
	from /Users/jk/.rvm/gems/ruby-3.2.2@dcidr/gems/psych-5.1.1.1/lib/psych/visitors/visitor.rb:30:in `visit'
	... 14 levels...

johnknapp avatar Dec 04 '23 22:12 johnknapp

@johnknapp Are you able to share the yaml file you're trying to load? I've never seen this issue before!

andreibondarev avatar Dec 05 '23 01:12 andreibondarev

Here you go @andreibondarev, the yaml is attached (inside a zip because I couldn't attach the yaml :-/). As an FYI, I'm also attaching the json version which loaded fine.

Working from code samples on the main README, running these three commands produced the error trace as seen above.

prompt = Langchain::Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke about {content}.", input_variables: ["adjective", "content"])
prompt.save(file_path: "prompt_template.yaml")
prompt = Langchain::Prompt.load_from_path(file_path: "prompt_template.yaml")

Note that I generated the yaml file by changing the file extension from json (as shown in the readme) to yaml. Also note this isn't rails/activerecord. I'm using the roda framework and sequel db toolkit. I ran these commands from within the sequel CLI (essentially an IRB)

prompt_template.json prompt_template.yaml.zip

johnknapp avatar Dec 05 '23 01:12 johnknapp

By the way, I just tried with an irb shell and got the same error.

johnknapp avatar Dec 05 '23 01:12 johnknapp

@johnknapp I had noticed that your prompt looks like the following:

---
:_type: prompt
:input_variables:
- adjective
- content
:template: Tell me a {adjective} joke about {content}.

I was able to get it running if I modified the keys:

---
_type: prompt
input_variables:
- adjective
- content
template: Tell me a {adjective} joke about {content}.

andreibondarev avatar Dec 05 '23 16:12 andreibondarev

That's interesting @andreibondarev, and it makes sense considering the psych error. This sounds like a problem with the prompt.save method eh?

johnknapp avatar Dec 05 '23 16:12 johnknapp

Well, lib/langchain/prompt/base.rb has this:


    #
    # Save the object to a file in JSON or YAML format.
    #
    # @param file_path [String, Pathname] The path to the file to save the object to
    #
    # @raise [ArgumentError] If file_path doesn't end with .json or .yaml or .yml
    #
    # @return [void]
    #
    def save(file_path:)
      save_path = file_path.is_a?(String) ? Pathname.new(file_path) : file_path
      directory_path = save_path.dirname
      FileUtils.mkdir_p(directory_path) unless directory_path.directory?

      case save_path.extname
      when ".json"
        File.write(file_path, to_h.to_json)
      when ".yaml", ".yml"
        File.write(file_path, to_h.to_yaml)
      else
        raise ArgumentError, "#{file_path} must be json or yaml file"
      end
    end

But I don't know why / how that code is symbolizing the keys.

johnknapp avatar Dec 05 '23 16:12 johnknapp