From a8e07b1967b07f97ca195f472d3eef90276ec30a Mon Sep 17 00:00:00 2001 From: kokuyouwind Date: Mon, 13 May 2024 15:01:00 +0900 Subject: [PATCH] case 1: rbs prototype rb + Anthropic Claude 3 Haiku --- case1/log | 325 +++++++++++++++++++++++++++++++++++++++++++ case1/sig/config.rbs | 8 +- case1/sig/runner.rbs | 8 +- 3 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 case1/log diff --git a/case1/log b/case1/log new file mode 100644 index 0000000..d44a6ee --- /dev/null +++ b/case1/log @@ -0,0 +1,325 @@ +Run RbsGoose.(Code Directory: lib, Signature Directory: sig) +!!!!!!!! Prompt !!!!!!!! + +role: user +content: +Your job is to output a more reasonable RBS type definition based on the given Ruby code and RBS type definition. +For all input RBS type definitions, output an improved RBS type definition. +Replace untyped with concrete types whenever possible and add any missing method definitions, attr_accessor, etc. +Correct any mistakes in existing types. + + +========Input======== +```ruby:lib/email.rb +class Email + # @dynamic address + attr_reader :address + + def initialize(address:) + @address = address + end + + def ==(other) + other.is_a?(self.class) && other.address == address + end + + def hash + self.class.hash ^ address.hash + end +end +``` + +```rbs:sig/email.rbs +class Email + @address: untyped + + attr_reader address: untyped + + def initialize: (address: untyped) -> void + + def ==: (untyped other) -> untyped + + def hash: () -> untyped +end +``` + +```ruby:lib/person.rb +class Person + # @dynamic name, contacts + attr_reader :name + attr_reader :contacts + + def initialize(name:) + @name = name + @contacts = [] + end + + def name=(name) + @name = name + end + + def guess_country() + contacts.map do |contact| + case contact + when Phone + contact.country + end + end.compact.first + end +end +``` + +```rbs:sig/person.rbs +class Person + @name: untyped + + @contacts: untyped + + attr_reader name: untyped + + attr_reader contacts: untyped + + def initialize: (name: untyped) -> void + + def name=: (untyped name) -> void + + def guess_country: () -> untyped +end +``` + +```ruby:lib/phone.rb +class Phone + # @dynamic country, number + attr_reader :country, :number + + def initialize(country:, number:) + @country = country + @number = number + end + + def ==(other) + if other.is_a?(Phone) + # @type var other: Phone + other.country == country && other.number == number + else + false + end + end + + def hash + self.class.hash ^ country.hash ^ number.hash + end +end +``` + +```rbs:sig/phone.rbs +class Phone + @country: untyped + + @number: untyped + + attr_reader country: untyped + + attr_reader number: untyped + + def initialize: (country: untyped, number: untyped) -> void + + def ==: (untyped other) -> (untyped | nil) + + def hash: () -> untyped +end +``` + + +========Output======== +```rbs:sig/email.rbs +class Email + @address: String + + attr_reader address: String + + def initialize: (address: String) -> void + + def ==: (Object other) -> bool + + def hash: () -> Integer +end +``` + +```rbs:sig/person.rbs +class Person + @name: String + + @contacts: Array[(Email | Phone)] + + attr_reader name: String + + attr_reader contacts: Array[(Email | Phone)] + + def initialize: (name: String) -> void + + def name=: (String name) -> void + + def guess_country: () -> (String | nil) +end +``` + +```rbs:sig/phone.rbs +class Phone + @country: String + + @number: String + + attr_reader country: String + + attr_reader number: String + + def initialize: (country: String, number: String) -> void + + def ==: (Object other) -> (bool | nil) + + def hash: () -> Integer +end +``` + + +========Input======== +```ruby:lib/config.rb +class Config + def self.configure(&block) + new.tap(&block) + end + + %w[client role prompt].each { attr_accessor _1.to_sym } +end + +if __FILE__ == $0 + require 'dotenv/load' + require 'langchain' + require 'openai' + + config = Config.configure do |config| + config.client = Langchain::LLM::OpenAI.new(api_key: ENV.fetch('OPENAI_ACCESS_TOKEN')) + config.role = 'user' + config.prompt = 'Hello.' + end + + pp config.client + pp config.role + pp config.prompt +end +``` + +```rbs:sig/config.rbs +class Config + def self.configure: () { (untyped) -> untyped } -> untyped +end +``` + +```ruby:lib/runner.rb +require_relative 'config' + +class Runner + def initialize(config) + @config = config + end + + def run + config.client.chat(messages: [{ role: config.role, content: config.prompt}]).chat_completion + end + + private + + attr_reader :config +end + +if __FILE__ == $0 + require 'dotenv/load' + require 'langchain' + require 'openai' + + config = Config.configure do |config| + config.client = Langchain::LLM::OpenAI.new(api_key: ENV.fetch('OPENAI_ACCESS_TOKEN')) + config.role = 'user' + config.prompt = 'Hello.' + end + runner = Runner.new(config) + pp runner.run +end +``` + +```rbs:sig/runner.rbs +class Runner + @config: untyped + + def initialize: (untyped config) -> void + + def run: () -> untyped + + private + + attr_reader config: untyped +end +``` + + +========Output======== + +!!!!!!!! Stats !!!!!!!! + + spend: 3.277885999996215[s] + prompt_tokens: 1446 + completion_tokens: 406 +!!!!!!!! Result !!!!!!!! + +Here are the improved RBS type definitions based on the given Ruby code: + +```rbs:sig/config.rbs +class Config + def self.configure: () { (Config) -> void } -> Config + + attr_accessor client: Langchain::LLM::OpenAI + attr_accessor role: String + attr_accessor prompt: String +end +``` + +```rbs:sig/runner.rbs +class Runner + @config: Config + + def initialize: (Config config) -> void + + def run: () -> untyped + + private + + attr_reader config: Config +end +``` + +Explanation: + +1. For the `Config` class: + - The `configure` method now has a concrete return type of `Config` and takes a block that accepts a `Config` object. + - The `attr_accessor` methods have been added for the `client`, `role`, and `prompt` attributes, with their respective types. + +2. For the `Runner` class: + - The `@config` instance variable is now typed as `Config`. + - The `initialize` method now takes a `Config` object as its argument. + - The `attr_reader` for the `config` attribute is now typed as `Config`. + +The improvements made are: + +1. Replaced `untyped` with concrete types whenever possible, such as `String`, `Langchain::LLM::OpenAI`, and `Config`. +2. Added the missing `attr_accessor` definitions for the `Config` class. +3. Corrected the type of the `@config` instance variable and the `initialize` method argument in the `Runner` class to use the `Config` type. + +These changes make the RBS type definitions more accurate and useful for the provided Ruby code. + +write refined rbs to sig/config.rbs +done. + +write refined rbs to sig/runner.rbs +done. + diff --git a/case1/sig/config.rbs b/case1/sig/config.rbs index e91a246..05be150 100644 --- a/case1/sig/config.rbs +++ b/case1/sig/config.rbs @@ -1,3 +1,7 @@ class Config - def self.configure: () { (untyped) -> untyped } -> untyped -end + def self.configure: () { (Config) -> void } -> Config + + attr_accessor client: Langchain::LLM::OpenAI + attr_accessor role: String + attr_accessor prompt: String +end \ No newline at end of file diff --git a/case1/sig/runner.rbs b/case1/sig/runner.rbs index b1588e8..c1140db 100644 --- a/case1/sig/runner.rbs +++ b/case1/sig/runner.rbs @@ -1,11 +1,11 @@ class Runner - @config: untyped + @config: Config - def initialize: (untyped config) -> void + def initialize: (Config config) -> void def run: () -> untyped private - attr_reader config: untyped -end + attr_reader config: Config +end \ No newline at end of file