diff --git a/CHANGELOG.md b/CHANGELOG.md index b45d61e..4e4ea64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,3 +18,6 @@ ## [0.4.2] - 2024-11-05 - adds support for [Predicted Outputs](https://platform.openai.com/docs/guides/latency-optimization#use-predicted-outputs) with the `prediction` option for OpenAI + +## [0.4.3] - 2024-11-11 +- adds support for `Predicate` module diff --git a/Gemfile b/Gemfile index 60fbde5..8b63055 100644 --- a/Gemfile +++ b/Gemfile @@ -22,3 +22,8 @@ group :development do gem "sorbet" gem "tapioca", require: false end + +group :test do + gem "vcr" + gem "webmock" +end diff --git a/Gemfile.lock b/Gemfile.lock index fa0a492..b659b64 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - raix (0.4.2) + raix (0.4.3) activesupport (>= 6.0) open_router (~> 0.2) @@ -18,6 +18,8 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) backport (1.2.0) base64 (0.2.0) @@ -26,6 +28,8 @@ GEM coderay (1.1.3) concurrent-ruby (1.3.3) connection_pool (2.4.1) + crack (0.4.5) + rexml diff-lcs (1.5.1) dotenv (3.1.2) drb (2.2.1) @@ -57,6 +61,7 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) + hashdiff (1.0.1) i18n (1.14.5) concurrent-ruby (~> 1.0) jaro_winkler (1.6.0) @@ -98,6 +103,7 @@ GEM pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) + public_suffix (5.0.5) racc (1.7.3) rainbow (3.1.1) rake (13.2.0) @@ -191,6 +197,11 @@ GEM concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) uri (0.13.0) + vcr (6.2.0) + webmock (3.18.1) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) yard (0.9.36) yard-sorbet (0.8.1) sorbet-runtime (>= 0.5) @@ -217,6 +228,8 @@ DEPENDENCIES solargraph-rails (~> 0.2.0.pre) sorbet tapioca + vcr + webmock BUNDLED WITH 2.4.12 diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..23074cd --- /dev/null +++ b/Guardfile @@ -0,0 +1,70 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# Note: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: "bundle exec rspec" do + require "guard/rspec/dsl" + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w(erb haml slim)) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance" + end +end diff --git a/README.md b/README.md index 05c785f..7b522cc 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,77 @@ Notably, Olympia does not use the `FunctionDispatch` module in its primary conve Streaming of the AI's response to the end user is handled by the `ReplyStream` class, passed to the final prompt declaration as its `stream` parameter. [Patterns of Application Development Using AI](https://leanpub.com/patterns-of-application-development-using-ai) devotes a whole chapter to describing how to write your own `ReplyStream` class. +## Predicate Module + +The `Raix::Predicate` module provides a simple way to handle yes/no/maybe questions using AI chat completion. It allows you to define blocks that handle different types of responses with their explanations. It is one of the concrete patterns described in the "Discrete Components" chapter of [Patterns of Application Development Using AI](https://leanpub.com/patterns-of-application-development-using-ai). + +### Usage + +Include the `Raix::Predicate` module in your class and define handlers using block syntax: + +```ruby +class Question + include Raix::Predicate + + yes? do |explanation| + puts "Affirmative: #{explanation}" + end + + no? do |explanation| + puts "Negative: #{explanation}" + end + + maybe? do |explanation| + puts "Uncertain: #{explanation}" + end +end + +question = Question.new +question.ask("Is Ruby a programming language?") +# => Affirmative: Yes, Ruby is a dynamic, object-oriented programming language... +``` + +### Features + +- Define handlers for yes, no, and/or maybe responses using the declarative class level block syntax. +- At least one handler (yes, no, or maybe) must be defined. +- Handlers receive the full AI response including explanation as an argument. +- Responses always start with "Yes, ", "No, ", or "Maybe, " followed by an explanation. +- Make sure to ask a question that can be answered with yes, no, or maybe (otherwise the results are indeterminate). + +### Example with Single Handler + +You can define only the handlers you need: + +```ruby +class SimpleQuestion + include Raix::Predicate + + # Only handle positive responses + yes? do |explanation| + puts "✅ #{explanation}" + end +end + +question = SimpleQuestion.new +question.ask("Is 2 + 2 = 4?") +# => ✅ Yes, 2 + 2 equals 4, this is a fundamental mathematical fact. +``` + +### Error Handling + +The module will raise a RuntimeError if you attempt to ask a question without defining any response handlers: + +```ruby +class InvalidQuestion + include Raix::Predicate +end + +question = InvalidQuestion.new +question.ask("Any question") +# => RuntimeError: Please define a yes and/or no block +``` + ## Installation Install the gem and add to the application's Gemfile by executing: diff --git a/lib/raix/predicate.rb b/lib/raix/predicate.rb new file mode 100644 index 0000000..639d6e7 --- /dev/null +++ b/lib/raix/predicate.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Raix + # A module for handling yes/no questions using AI chat completion. + # When included in a class, it provides methods to define handlers for + # yes and no responses. + # + # @example + # class Question + # include Raix::Predicate + # + # yes do |explanation| + # puts "Yes: #{explanation}" + # end + # + # no do |explanation| + # puts "No: #{explanation}" + # end + # end + # + # question = Question.new + # question.ask("Is Ruby a programming language?") + module Predicate + include ChatCompletion + + def self.included(base) + base.extend(ClassMethods) + end + + def ask(question) + raise "Please define a yes and/or no block" if self.class.yes_block.nil? && self.class.no_block.nil? + + transcript << { system: "Always answer 'Yes, ', 'No, ', or 'Maybe, ' followed by a concise explanation!" } + transcript << { user: question } + + chat_completion.tap do |response| + if response.downcase.start_with?("yes,") + instance_exec(response, &self.class.yes_block) if self.class.yes_block + elsif response.downcase.start_with?("no,") + instance_exec(response, &self.class.no_block) if self.class.no_block + elsif response.downcase.start_with?("maybe,") + instance_exec(response, &self.class.maybe_block) if self.class.maybe_block + end + end + end + + # Class methods added to the including class + module ClassMethods + attr_reader :yes_block, :no_block, :maybe_block + + def yes?(&block) + @yes_block = block + end + + def no?(&block) + @no_block = block + end + + def maybe?(&block) + @maybe_block = block + end + end + end +end diff --git a/lib/raix/version.rb b/lib/raix/version.rb index 826b95b..8f8e608 100644 --- a/lib/raix/version.rb +++ b/lib/raix/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Raix - VERSION = "0.4.2" + VERSION = "0.4.3" end diff --git a/spec/raix/chat_completion_spec.rb b/spec/raix/chat_completion_spec.rb index ce85f9a..7d58ea1 100644 --- a/spec/raix/chat_completion_spec.rb +++ b/spec/raix/chat_completion_spec.rb @@ -10,7 +10,7 @@ def initialize end end -RSpec.describe MeaningOfLife do +RSpec.describe MeaningOfLife, :vcr do subject { described_class.new } it "does a completion with OpenAI" do diff --git a/spec/raix/function_dispatch_spec.rb b/spec/raix/function_dispatch_spec.rb index 9d86a98..4200fe5 100644 --- a/spec/raix/function_dispatch_spec.rb +++ b/spec/raix/function_dispatch_spec.rb @@ -14,7 +14,7 @@ def initialize end end -RSpec.describe WhatIsTheWeather do +RSpec.describe WhatIsTheWeather, :vcr do subject { described_class.new } it "can call a function and loop to provide text response" do diff --git a/spec/raix/predicate_spec.rb b/spec/raix/predicate_spec.rb new file mode 100644 index 0000000..81ce023 --- /dev/null +++ b/spec/raix/predicate_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require "raix/predicate" + +class Question + include Raix::Predicate + + yes? do |explanation| + @callback.call(:yes, explanation) + end + + no? do |explanation| + @callback.call(:no, explanation) + end + + maybe? do |explanation| + @callback.call(:maybe, explanation) + end + + def initialize(callback) + @callback = callback + end +end + +class QuestionWithNoBlocks + include Raix::Predicate +end + +RSpec.describe Raix::Predicate, :vcr do + let(:callback) { double("callback") } + let(:question) { Question.new(callback) } + + it "yes" do + expect(callback).to receive(:call).with(:yes, "Yes, Ruby on Rails is a web application framework.") + question.ask("Is Ruby on Rails a web application framework?") + end + + it "no" do + expect(callback).to receive(:call).with(:no, "No, the Eiffel Tower is located in Paris, France, not Madrid, Spain.") + question.ask("Is the Eiffel Tower in Madrid?") + end + + it "maybe" do + expect(callback).to receive(:call).with(:maybe, "Maybe, it depends on the specific situation and context.") + question.ask("Should I quit my job?") + end + + it "raises an error if no blocks are defined" do + expect { QuestionWithNoBlocks.new.ask("Is Ruby on Rails a web application framework?") }.to raise_error(RuntimeError, "Please define a yes and/or no block") + end +end diff --git a/spec/raix/prompt_caching_spec.rb b/spec/raix/prompt_caching_spec.rb index fac8544..628bca6 100644 --- a/spec/raix/prompt_caching_spec.rb +++ b/spec/raix/prompt_caching_spec.rb @@ -25,7 +25,7 @@ def initialize end end -RSpec.describe GettingRealAnthropic do +RSpec.describe GettingRealAnthropic, :vcr do subject { described_class.new } it "does a completion with prompt caching" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d9fa47f..112755d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,6 +7,19 @@ require "pry" require "raix" +require "vcr" + +VCR.configure do |config| + config.cassette_library_dir = "spec/vcr" # the directory where your cassettes will be saved + config.hook_into :webmock # or :fakeweb + config.configure_rspec_metadata! + config.ignore_localhost = true + + config.default_cassette_options = { + match_requests_on: %i[method uri] + } +end + Dotenv.load retry_options = { @@ -45,4 +58,14 @@ config.expect_with :rspec do |c| c.syntax = :expect end + + config.before(:example, :novcr) do + VCR.turn_off! + WebMock.disable! + end + + config.after(:example, :novcr) do + VCR.turn_on! + WebMock.enable! + end end diff --git a/spec/vcr/GettingRealAnthropic/does_a_completion_with_prompt_caching.yml b/spec/vcr/GettingRealAnthropic/does_a_completion_with_prompt_caching.yml new file mode 100644 index 0000000..00bfc22 --- /dev/null +++ b/spec/vcr/GettingRealAnthropic/does_a_completion_with_prompt_caching.yml @@ -0,0 +1,769 @@ +--- +http_interactions: +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":[{"type":"text","text":"You + are a modern historian studying trends in modern business. You know the following + book callsed ''Getting Real'' very well:"},{"type":"text","text":"Introduction\nWhat + is Getting Real?\nAbout 37signals\nCaveats, disclaimers, and other preemptive + strikes\n\n\n What is Getting Real?\nWant to build a successful web app? Then + it’s time to Get Real. Getting Real is a smaller, faster, better way to build + software.\nGetting Real is about skipping all the stuff that represents real + (charts, graphs, boxes, arrows, schematics, wireframes, etc.) and actually + building the real thing.\nGetting real is less. Less mass, less software, + less features, less paperwork, less of everything that’s not essential (and + most of what you think is essential actually isn’t).\nGetting Real is staying + small and being agile.\nGetting Real starts with the interface, the real screens + that people are going to use. It begins with what the customer actually experiences + and builds backwards from there.This lets you get the interface right before + you get the software wrong.\nGetting Real is about iterations and lowering + the cost of change. Getting Real is all about launching, tweaking, and constantly + improving which makes it a perfect approach for web-based software.\nGetting + Real delivers just what customers need and eliminates anything they don’t.\nThe + benefits of Getting Real\nGetting Real delivers better results because it + forces you to deal with the actual problems you’re trying to solve instead + of your ideas about those problems. It forces you to deal with reality.\n\n + Getting Real foregoes functional specs and other transitory documentation + in favor of building real screens. A functional spec is make-believe, an illusion + of agreement, while an actual web page is reality. That’s what your customers + are going to see and use. That’s what matters. Getting Real gets you there + faster.\nAnd that means you’re making software decisions based on the real + thing instead of abstract notions.\nFinally, Getting Real is an approach ideally + suited to web-based software. The old school model of shipping software in + a box and then waiting a year or two to deliver an update is fading away. + Unlike installed software, web apps can constantly evolve on a day-to-day + basis. Getting Real leverages this advantage for all its worth.\nHow To Write + Vigorous Software\nVigorous writing is concise.A sentence should contain no + unnecessary words, a paragraph no unnecessary sentences, for the same reason + that a drawing should have no unnecessary lines and a machine no unnecessary + parts.This requires not that the writer make all sentences short or avoid + all detail and treat subjects only in outline, but that every word tell.\nFrom + “The Elements of Style” by William Strunk Jr.\nNo more bloat\nThe old way: + a lengthy, bureaucratic, we’re-doing-this-to-cover- our-asses process. The + typical result: bloated, forgettable soft- ware dripping with mediocrity. + Blech.\nGetting Real gets rid of...\nTimelines that take months or even years + Pie-in-the-sky functional specs Scalability debates\n\n Interminable staff + meetings\nThe “need” to hire dozens of employees Meaningless version numbers\nPristine + roadmaps that predict the perfect future Endless preference options\nOutsourced + support\nUnrealistic user testing\nUseless paperwork\nTop-down hierarchy\nYou + don’t need tons of money or a huge team or a lengthy development cycle to + build great software. Those things are the ingredients for slow, murky, changeless + applications. Getting real takes the opposite approach.\nIn this book we’ll + show you...\nThe importance of having a philosophy Why staying small is a + good thing\nHow to build less\nHow to get from idea to reality quickly How + to staff your team\nWhy you should design from the inside out Why writing + is so crucial\nWhy you should underdo your competition\n\n How to promote + your app and spread the word Secrets to successful support\nTips on keeping + momentum going after launch\n...and lots more\nThe focus is on big-picture + ideas. We won’t bog you down with detailed code snippets or css tricks. We’ll + stick to the major ideas and philosophies that drive the Getting Real process.\nIs + this book for you?\nYou’re an entrepreneur, designer, programmer, or marketer + working on a big idea.\nYou realize the old rules don’t apply anymore. Distribute + your software on cd-roms every year? How 2002. Version numbers? Out the window. + You need to build, launch, and tweak. Then rinse and repeat.\nOr maybe you’re + not yet on board with agile development and business structures, but you’re + eager to learn more.\nIf this sounds like you, then this book is for you.\nNote: + While this book’s emphasis is on building a web app, a lot of these ideas + are applicable to non-software activities too. The suggestions about small + teams, rapid prototyping, expect- ing iterations, and many others presented + here can serve as a guide whether you’re starting a business, writing a book, + designing a web site, recording an album, or doing a variety\nof other endeavors. + Once you start Getting Real in one area of your life, you’ll see how these + concepts can apply to a wide range of activities.\n\n About 37signals\nWhat + we do\n37signals is a small team that creates simple, focused software. Our + products help you collaborate and get organized. More than 350,000 people + and small businesses use our web-apps to get things done. Jeremy Wagstaff, + of the Wall Street Journal, wrote, “37signals products are beautifully simple, + elegant and intuitive tools that make an Outlook screen look like the soft- + ware equivalent of a torture chamber.” Our apps never put you on the rack.\nOur + modus operandi\nWe believe software is too complex. Too many features, too + many buttons, too much to learn. Our products do less than the competition + – intentionally. We build products that work smarter, feel better, allow you + to do things your way, and are easier to use.\nOur products\nAs of the publishing + date of this book, we have five commercial products and one open source web + application framework.\nBasecamp turns project management on its head. Instead + of Gantt charts, fancy graphs, and stats-heavy spreadsheets, Base- camp offers + message boards, to-do lists, simple scheduling, col- laborative writing, and + file sharing. So far, hundreds of thou- sands agree it’s a better way. Farhad + Manjoo of Salon.com said\n“Basecamp represents the future of software on the + Web.”\n\n Campfire brings simple group chat to the business setting. Businesses + in the know understand how valuable real-time persistent group chat can be. + Conventional instant messaging is great for quick 1-on-1 chats, but it’s miserable + for 3 or more people at once. Campfire solves that problem and plenty more.\nBackpack + is the alternative to those confusing, complex, “orga- nize your life in 25 + simple steps” personal information managers. Backpack’s simple take on pages, + notes, to-dos, and cellphone/ email-based reminders is a novel idea in a product + category that suffers from status-quo-itis. Thomas Weber of the Wall Street + Journal said it’s the best product in its class and David Pogue of the New + York Times called it a “very cool” organization tool.\nWriteboard lets you + write, share, revise, and compare text\nsolo or with others. It’s the refreshing + alternative to bloated word processors that are overkill for 95% of what you + write. John Gruber of Daring Fireball said, “Writeboard might be the clearest, + simplest web application I’ve ever seen.” Web-guru Jeffrey Zeldman said, “The + brilliant minds at 37signals have done it again.”\nTa-da List keeps all your + to-do lists together and organized online. Keep the lists to yourself or share + them with others for easy collaboration. There’s no easier way to get things + done. Over 100,000 lists with nearly 1,000,000 items have been created so + far.\nRuby on Rails, for developers, is a full-stack, open-source web framework + in Ruby for writing real-world applications quickly and easily. Rails takes + care of the busy work so you can focus on your idea. Nathan Torkington of + the O’Reilly publish- ing empire said “Ruby on Rails is astounding. Using + it is like watching a kung-fu movie, where a dozen bad-ass frameworks prepare + to beat up the little newcomer only to be handed their asses in a variety + of imaginative ways.” Gotta love that quote.\n\n Caveats, disclaimers, and + other preemptive strikes\nJust to get it out of the way, here are our responses + to some com- plaints we hear every now and again:\n“These techniques won’t + work for me.”\nGetting real is a system that’s worked terrifically for us. + That said, the ideas in this book won’t apply to every project under the sun. + If you are building a weapons system, a nuclear control plant, a banking system + for millions of customers, or some other life/finance-critical system, you’re + going to balk at some of our laissez-faire attitude. Go ahead and take additional + precautions.\nAnd it doesn’t have to be an all or nothing proposition. Even + if you can’t embrace Getting Real fully, there are bound to be at least a + few ideas in here you can sneak past the powers that be.\n“You didn’t invent + that idea.”\nWe’re not claiming to have invented these techniques. Many of + these concepts have been around in one form or another for a long time. Don’t + get huffy if you read some\nof our advice and it reminds you of something + you read about already on so and so’s weblog or in some book pub- lished 20 + years ago. It’s definitely possible. These tech- niques are not at all exclusive + to 37signals. We’re just telling you how we work and what’s been successful + for us.\n\n “You take too much of a black and white view.”\nIf our tone seems + too know-it-allish, bear with us. We think it’s better to present ideas in + bold strokes than to be wishy-washy about it. If that comes off as cocky or + arrogant, so be it. We’d rather be provocative than water everything down + with “it depends...” Of course there will be times when these rules need to + be stretched or broken. And some of these tactics may not apply to your situation. + Use your judgement and imagination.\n“This won’t work inside my company.”\nThink + you’re too big to Get Real? Even Microsoft is Getting Real (and we doubt you’re + bigger than them).\nEven if your company typically runs on long-term schedules + with big teams, there are still ways to get real.The first step is\nto break + up into smaller units. When there’s too many people involved, nothing gets + done. The leaner you are, the faster – and better – things get done.\nGranted, + it may take some salesmanship. Pitch your company on the Getting Real process. + Show them this book. Show them the real results you can achieve in less time + and with a smaller team.\nExplain that Getting Real is a low-risk, low-investment + way to test new concepts. See if you can split off from the mothership on + a smaller project as a proof of concept. Demonstrate results.\nOr, if you + really want to be ballsy, go stealth. Fly under the radar and demonstrate + real results. That’s the approach the Start.com team has used while Getting + Real at Microsoft. “I’ve watched the Start.com team work. They don’t ask permission,” + says Robert Scoble, Technical Evangelist at Microsoft. “They have a boss that + provides air cover. And they bite off a little bit at a time and do that and + respond to feedback.”\n\n Shipping Microsoft’s Start.com\nIn big companies, + processes and meetings are the norm. Many months are spent on planning features + and arguing details with the goal of everyone reaching an agreement on what + is the “right” thing for the customer.\nThat may be the right approach for + shrink-wrapped software, but with the web we have an incredible advantage. + Just ship it! Let the user tell you if it’s the right thing and if it’s not, + hey you can fix it and ship it to the web the same day if you want! There + is no word stronger than the customer’s – resist the urge to engage in long-winded + meetings and arguments. Just ship it and prove a point.\nMuch easier said + than done – this implies:\nMonths of planning are not necessary.\nMonths of + writing specs are not necessary – specs should have the foundations nailed + and details figured out and refined during the development phase. Don’t try + to close all open issues and nail every single detail before development starts.\nShip + less features, but quality features.\nYou don’t need a big bang approach with + a whole new release and bunch of features. Give the users byte-size pieces + that they can digest.\nIf there are minor bugs, ship it as soon you have the + core scenarios nailed and ship the bug fixes to web gradually after that.The + faster you get the user feedback the better. Ideas can sound great on paper + but in practice turn out to be suboptimal.The sooner you find out about fundamental + issues that are wrong with an idea, the better.\nOnce you iterate quickly + and react on customer feedback, you will establish a customer connection. + Remember the goal is to win the customer by building what they want.\n-Sanaz + Ahari, Program Manager of Start.com, Microsoft\n\n\n The Starting Line\nBuild + Less\nWhat’s Your Problem?\nFund Yourself\nFix Time and Budget, Flex Scope + Have an Enemy\nIt Shouldn’t be a Chore\n\n\n Build Less\nUnderdo your competition\nConventional + wisdom says that to beat your competitors you need to one-up them. If they + have four features, you need five (or 15, or 25). If they’re spending x, you + need to spend xx. If they have 20, you need 30.\nThis sort of one-upping Cold + War mentality is a dead-end. It’s an expensive, defensive, and paranoid way + of building products. Defensive, paranoid companies can’t think ahead, they + can only think behind. They don’t lead, they follow.\nIf you want to build + a company that follows, you might as well put down this book now.\nSo what + to do then? The answer is less. Do less than your com- petitors to beat them. + Solve the simple problems and leave the hairy, difficult, nasty problems to + everyone else. Instead of one- upping, try one-downing. Instead of outdoing, + try underdoing.\nWe’ll cover the concept of less throughout this book, but + for starters, less means:\nLess features\nLess options/preferences\nLess people + and corporate structure Less meetings and abstractions\nLess promises\n\n\n + What’s Your Problem?\nBuild software for yourself\nA great way to build software + is to start out by solving your own problems. You’ll be the target audience + and you’ll know what’s important and what’s not. That gives you a great head + start on delivering a breakout product.\nThe key here is understanding that + you’re not alone. If you’re having this problem, it’s likely hundreds of thousands + of others are in the same boat. There’s your market. Wasn’t that easy?\nBasecamp + originated in a problem: As a design firm we needed a simple way to communicate + with our clients about projects. We started out doing this via client ex- + tranets which we would update manually. But changing the html by hand every + time a project needed to be updated just wasn’t working. These project sites + always seemed to go stale and eventually were abandoned. It was frustrating + because it left us disorganized and left clients in the dark.\nSo we started + looking at other options. Yet every tool we found either 1) didn’t do what + we needed or 2) was bloated with fea- tures we didn’t need – like billing, + strict access controls, charts, graphs, etc. We knew there had to be a better + way so we decided to build our own.\nWhen you solve your own problem, you + create a tool that you’re passionate about. And passion is key. Passion means + you’ll truly use it and care about it. And that’s the best way to get others + to feel passionate about it too.\n\n Scratching your own itch\nThe Open + Source world embraced this mantra a long time ago – they call it “scratching + your own itch.” For the open source developers, it means they get the tools + they want, delivered the way they want them. But the benefit goes much deeper.\nAs + the designer or developer of a new application, you’re faced with hundreds + of micro-decisions each and every day: blue or green? One table or two? Static + or dynamic? Abort or recover? How do we make these decisions? If it’s something + we recognize as being important, we might ask.The rest, we guess.And all that + guessing builds up a kind of debt in our applications – an interconnected + web of assumptions.\nAs a developer, I hate this.The knowledge of all these + small-scale timebombs in the applications I write adds to my stress. Open + Source developers, scratching their own itches, don’t suffer this. Because + they are their own users, they know the correct answers to 90% of the decisions + they have to make. I think this is one of the reasons folks come home after + a hard day of coding and then work on open source: It’s relaxing.\n–Dave Thomas, + The Pragmatic Programmers\n\nBorn out of necessity\nCampaign Monitor really + was born out of necessity. For years we’d been frustrated by the quality of + the email marketing options out there. One tool would do x and y but never + z, the next had y\nand z nailed but just couldn’t get x right.We couldn’t + win.\nWe decided to clear our schedule and have a go at building our dream + email marketing tool.We consciously decided not to look at what everyone else + was doing and instead build something that would make ours and our customer’s + lives a little easier.\nAs it turned out, we weren’t the only ones who were + unhappy with the options out there.We made a few modifications to the software + so any design firm could use it and started spreading the word. In less than + six months, thousands of designers were using Campaign Monitor to send email + newsletters for themselves and their clients.\n–David Greiner, founder, Campaign + Monitor\n\n\n You need to care about it\nWhen you write a book, you need + to have more than an interesting story. You need to have a desire to tell + the story.You need to be personally invested in some way. If you’re going + to live with something for two years, three years, the rest of your life, + you need to care about it.\n–Malcolm Gladwell, author (from A Few Thin Slices + of Malcolm Gladwell)\n\n\n Fund Yourself\nOutside money is plan B\nThe first + priority of many startups is acquiring funding from investors. But remember, + if you turn to outsiders for funding, you’ll have to answer to them too. Expectations + are raised. Investors want their money back – and quickly. The sad fact is + cashing in often begins to trump building a quality product.\nThese days it + doesn’t take much to get rolling. Hardware\nis cheap and plenty of great infrastructure + software is open source and free. And passion doesn’t come with a price tag.\nSo + do what you can with the cash on hand. Think hard and determine what’s really + essential and what you can do without. What can you do with three people instead + of ten? What can you do with $20k instead of $100k? What can you do in three + months instead of six? What can you do if you keep your day job and build + your app on the side?\nConstraints force creativity\nRun on limited resources + and you’ll be forced to reckon with constraints earlier and more intensely. + And that’s a good thing. Constraints drive innovation.\n\n\n Constraints also + force you to get your idea out in the wild sooner rather than later – another + good thing. A month or two out of the gates you should have a pretty good + idea of whether you’re onto something or not. If you are, you’ll be self-sustain- + able shortly and won’t need external cash. If your idea’s a lemon, it’s time + to go back to the drawing board. At least you know now as opposed to months + (or years) down the road. And at least you can back out easily. Exit plans + get a lot trickier once inves- tors are involved.\nIf you’re creating software + just to make a quick buck, it will show. Truth is a quick payout is pretty + unlikely. So focus on building a quality tool that you and your customers + can live with for a long time.\n\nTwo paths\n[Jake Walker started one company + with investor money (Disclive) and one without (The Show). Here he discusses + the differences between the two paths.]\n\nThe root of all the problems wasn’t + raising money itself, but everything that came along with it.The expectations + are simply higher. People start taking salary, and the motivation is to build + it up and sell it, or find some other way for the initial investors to make + their money back. In the case of the first company,\nwe simply started acting + much bigger than we were – out of necessity...\n[With The Show] we realized + that we could deliver a much better product with less costs, only with more + time. And we gambled with a bit of our own money that people would be willing + to wait for quality over speed. But the company has stayed (and will likely + continue to be) a small operation.And ever since that first project, we’ve + been fully self funded.With just a bit of creative terms from our vendors, + we’ve never really need to put much of our own money into the operation at + all.And the expectation isn’t to grow and sell,but to grow for the sake of + growth and to continue to benefit from it financially.\n–A comment from Signal + vs. Noise\n\n","cache_control":{"type":"ephemeral"}}]},{"role":"user","content":"What + is the meaning of Getting Real according to the book? Begin your response + with According to the book,"}],"model":"anthropic/claude-3-haiku","max_tokens":1000,"temperature":0.0}' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:37:32 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a8ec0afb719c7-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1731289052-M1FmaSIlmErrMNX8ZSCb\",\"provider\":\"Anthropic\",\"model\":\"anthropic/claude-3-haiku\",\"object\":\"chat.completion\",\"created\":1731289052,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"end_turn\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"According + to the book, \\\"Getting Real\\\" is \\\"a smaller, faster, better way to + build software.\\\" The key principles of Getting Real include:\\n\\n1. Skipping + the abstract planning and documentation (like functional specs, wireframes, + etc.) and instead focusing on building the actual product.\\n\\n2. Doing less + - less features, less options, less people, less meetings, etc. The goal is + to be lean and agile rather than bloated and bureaucratic.\\n\\n3. Starting + with the user interface and customer experience, and building backwards from + there. This ensures the product is focused on solving real user problems.\\n\\n4. + Embracing an iterative, launch-and-improve approach rather than trying to + perfect everything upfront. Web-based software can be constantly updated, + so the focus is on getting something out there quickly and refining it based + on user feedback.\\n\\n5. Avoiding the traditional software development process + of lengthy timelines, big teams, and extensive planning in favor of a more + nimble, resource-constrained approach.\\n\\nThe core idea is to be pragmatic, + focus on the essentials, and get the actual product in front of users as quickly + as possible, rather than getting bogged down in abstract planning and documentation. + This \\\"getting real\\\" approach is presented as an effective way to build + successful web-based software.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":4884,\"completion_tokens\":285,\"total_tokens\":5169}}" + recorded_at: Mon, 11 Nov 2024 01:37:35 GMT +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":[{"type":"text","text":"You + are a modern historian studying trends in modern business. You know the following + book callsed ''Getting Real'' very well:"},{"type":"text","text":"Introduction\nWhat + is Getting Real?\nAbout 37signals\nCaveats, disclaimers, and other preemptive + strikes\n\n\n What is Getting Real?\nWant to build a successful web app? Then + it’s time to Get Real. Getting Real is a smaller, faster, better way to build + software.\nGetting Real is about skipping all the stuff that represents real + (charts, graphs, boxes, arrows, schematics, wireframes, etc.) and actually + building the real thing.\nGetting real is less. Less mass, less software, + less features, less paperwork, less of everything that’s not essential (and + most of what you think is essential actually isn’t).\nGetting Real is staying + small and being agile.\nGetting Real starts with the interface, the real screens + that people are going to use. It begins with what the customer actually experiences + and builds backwards from there.This lets you get the interface right before + you get the software wrong.\nGetting Real is about iterations and lowering + the cost of change. Getting Real is all about launching, tweaking, and constantly + improving which makes it a perfect approach for web-based software.\nGetting + Real delivers just what customers need and eliminates anything they don’t.\nThe + benefits of Getting Real\nGetting Real delivers better results because it + forces you to deal with the actual problems you’re trying to solve instead + of your ideas about those problems. It forces you to deal with reality.\n\n + Getting Real foregoes functional specs and other transitory documentation + in favor of building real screens. A functional spec is make-believe, an illusion + of agreement, while an actual web page is reality. That’s what your customers + are going to see and use. That’s what matters. Getting Real gets you there + faster.\nAnd that means you’re making software decisions based on the real + thing instead of abstract notions.\nFinally, Getting Real is an approach ideally + suited to web-based software. The old school model of shipping software in + a box and then waiting a year or two to deliver an update is fading away. + Unlike installed software, web apps can constantly evolve on a day-to-day + basis. Getting Real leverages this advantage for all its worth.\nHow To Write + Vigorous Software\nVigorous writing is concise.A sentence should contain no + unnecessary words, a paragraph no unnecessary sentences, for the same reason + that a drawing should have no unnecessary lines and a machine no unnecessary + parts.This requires not that the writer make all sentences short or avoid + all detail and treat subjects only in outline, but that every word tell.\nFrom + “The Elements of Style” by William Strunk Jr.\nNo more bloat\nThe old way: + a lengthy, bureaucratic, we’re-doing-this-to-cover- our-asses process. The + typical result: bloated, forgettable soft- ware dripping with mediocrity. + Blech.\nGetting Real gets rid of...\nTimelines that take months or even years + Pie-in-the-sky functional specs Scalability debates\n\n Interminable staff + meetings\nThe “need” to hire dozens of employees Meaningless version numbers\nPristine + roadmaps that predict the perfect future Endless preference options\nOutsourced + support\nUnrealistic user testing\nUseless paperwork\nTop-down hierarchy\nYou + don’t need tons of money or a huge team or a lengthy development cycle to + build great software. Those things are the ingredients for slow, murky, changeless + applications. Getting real takes the opposite approach.\nIn this book we’ll + show you...\nThe importance of having a philosophy Why staying small is a + good thing\nHow to build less\nHow to get from idea to reality quickly How + to staff your team\nWhy you should design from the inside out Why writing + is so crucial\nWhy you should underdo your competition\n\n How to promote + your app and spread the word Secrets to successful support\nTips on keeping + momentum going after launch\n...and lots more\nThe focus is on big-picture + ideas. We won’t bog you down with detailed code snippets or css tricks. We’ll + stick to the major ideas and philosophies that drive the Getting Real process.\nIs + this book for you?\nYou’re an entrepreneur, designer, programmer, or marketer + working on a big idea.\nYou realize the old rules don’t apply anymore. Distribute + your software on cd-roms every year? How 2002. Version numbers? Out the window. + You need to build, launch, and tweak. Then rinse and repeat.\nOr maybe you’re + not yet on board with agile development and business structures, but you’re + eager to learn more.\nIf this sounds like you, then this book is for you.\nNote: + While this book’s emphasis is on building a web app, a lot of these ideas + are applicable to non-software activities too. The suggestions about small + teams, rapid prototyping, expect- ing iterations, and many others presented + here can serve as a guide whether you’re starting a business, writing a book, + designing a web site, recording an album, or doing a variety\nof other endeavors. + Once you start Getting Real in one area of your life, you’ll see how these + concepts can apply to a wide range of activities.\n\n About 37signals\nWhat + we do\n37signals is a small team that creates simple, focused software. Our + products help you collaborate and get organized. More than 350,000 people + and small businesses use our web-apps to get things done. Jeremy Wagstaff, + of the Wall Street Journal, wrote, “37signals products are beautifully simple, + elegant and intuitive tools that make an Outlook screen look like the soft- + ware equivalent of a torture chamber.” Our apps never put you on the rack.\nOur + modus operandi\nWe believe software is too complex. Too many features, too + many buttons, too much to learn. Our products do less than the competition + – intentionally. We build products that work smarter, feel better, allow you + to do things your way, and are easier to use.\nOur products\nAs of the publishing + date of this book, we have five commercial products and one open source web + application framework.\nBasecamp turns project management on its head. Instead + of Gantt charts, fancy graphs, and stats-heavy spreadsheets, Base- camp offers + message boards, to-do lists, simple scheduling, col- laborative writing, and + file sharing. So far, hundreds of thou- sands agree it’s a better way. Farhad + Manjoo of Salon.com said\n“Basecamp represents the future of software on the + Web.”\n\n Campfire brings simple group chat to the business setting. Businesses + in the know understand how valuable real-time persistent group chat can be. + Conventional instant messaging is great for quick 1-on-1 chats, but it’s miserable + for 3 or more people at once. Campfire solves that problem and plenty more.\nBackpack + is the alternative to those confusing, complex, “orga- nize your life in 25 + simple steps” personal information managers. Backpack’s simple take on pages, + notes, to-dos, and cellphone/ email-based reminders is a novel idea in a product + category that suffers from status-quo-itis. Thomas Weber of the Wall Street + Journal said it’s the best product in its class and David Pogue of the New + York Times called it a “very cool” organization tool.\nWriteboard lets you + write, share, revise, and compare text\nsolo or with others. It’s the refreshing + alternative to bloated word processors that are overkill for 95% of what you + write. John Gruber of Daring Fireball said, “Writeboard might be the clearest, + simplest web application I’ve ever seen.” Web-guru Jeffrey Zeldman said, “The + brilliant minds at 37signals have done it again.”\nTa-da List keeps all your + to-do lists together and organized online. Keep the lists to yourself or share + them with others for easy collaboration. There’s no easier way to get things + done. Over 100,000 lists with nearly 1,000,000 items have been created so + far.\nRuby on Rails, for developers, is a full-stack, open-source web framework + in Ruby for writing real-world applications quickly and easily. Rails takes + care of the busy work so you can focus on your idea. Nathan Torkington of + the O’Reilly publish- ing empire said “Ruby on Rails is astounding. Using + it is like watching a kung-fu movie, where a dozen bad-ass frameworks prepare + to beat up the little newcomer only to be handed their asses in a variety + of imaginative ways.” Gotta love that quote.\n\n Caveats, disclaimers, and + other preemptive strikes\nJust to get it out of the way, here are our responses + to some com- plaints we hear every now and again:\n“These techniques won’t + work for me.”\nGetting real is a system that’s worked terrifically for us. + That said, the ideas in this book won’t apply to every project under the sun. + If you are building a weapons system, a nuclear control plant, a banking system + for millions of customers, or some other life/finance-critical system, you’re + going to balk at some of our laissez-faire attitude. Go ahead and take additional + precautions.\nAnd it doesn’t have to be an all or nothing proposition. Even + if you can’t embrace Getting Real fully, there are bound to be at least a + few ideas in here you can sneak past the powers that be.\n“You didn’t invent + that idea.”\nWe’re not claiming to have invented these techniques. Many of + these concepts have been around in one form or another for a long time. Don’t + get huffy if you read some\nof our advice and it reminds you of something + you read about already on so and so’s weblog or in some book pub- lished 20 + years ago. It’s definitely possible. These tech- niques are not at all exclusive + to 37signals. We’re just telling you how we work and what’s been successful + for us.\n\n “You take too much of a black and white view.”\nIf our tone seems + too know-it-allish, bear with us. We think it’s better to present ideas in + bold strokes than to be wishy-washy about it. If that comes off as cocky or + arrogant, so be it. We’d rather be provocative than water everything down + with “it depends...” Of course there will be times when these rules need to + be stretched or broken. And some of these tactics may not apply to your situation. + Use your judgement and imagination.\n“This won’t work inside my company.”\nThink + you’re too big to Get Real? Even Microsoft is Getting Real (and we doubt you’re + bigger than them).\nEven if your company typically runs on long-term schedules + with big teams, there are still ways to get real.The first step is\nto break + up into smaller units. When there’s too many people involved, nothing gets + done. The leaner you are, the faster – and better – things get done.\nGranted, + it may take some salesmanship. Pitch your company on the Getting Real process. + Show them this book. Show them the real results you can achieve in less time + and with a smaller team.\nExplain that Getting Real is a low-risk, low-investment + way to test new concepts. See if you can split off from the mothership on + a smaller project as a proof of concept. Demonstrate results.\nOr, if you + really want to be ballsy, go stealth. Fly under the radar and demonstrate + real results. That’s the approach the Start.com team has used while Getting + Real at Microsoft. “I’ve watched the Start.com team work. They don’t ask permission,” + says Robert Scoble, Technical Evangelist at Microsoft. “They have a boss that + provides air cover. And they bite off a little bit at a time and do that and + respond to feedback.”\n\n Shipping Microsoft’s Start.com\nIn big companies, + processes and meetings are the norm. Many months are spent on planning features + and arguing details with the goal of everyone reaching an agreement on what + is the “right” thing for the customer.\nThat may be the right approach for + shrink-wrapped software, but with the web we have an incredible advantage. + Just ship it! Let the user tell you if it’s the right thing and if it’s not, + hey you can fix it and ship it to the web the same day if you want! There + is no word stronger than the customer’s – resist the urge to engage in long-winded + meetings and arguments. Just ship it and prove a point.\nMuch easier said + than done – this implies:\nMonths of planning are not necessary.\nMonths of + writing specs are not necessary – specs should have the foundations nailed + and details figured out and refined during the development phase. Don’t try + to close all open issues and nail every single detail before development starts.\nShip + less features, but quality features.\nYou don’t need a big bang approach with + a whole new release and bunch of features. Give the users byte-size pieces + that they can digest.\nIf there are minor bugs, ship it as soon you have the + core scenarios nailed and ship the bug fixes to web gradually after that.The + faster you get the user feedback the better. Ideas can sound great on paper + but in practice turn out to be suboptimal.The sooner you find out about fundamental + issues that are wrong with an idea, the better.\nOnce you iterate quickly + and react on customer feedback, you will establish a customer connection. + Remember the goal is to win the customer by building what they want.\n-Sanaz + Ahari, Program Manager of Start.com, Microsoft\n\n\n The Starting Line\nBuild + Less\nWhat’s Your Problem?\nFund Yourself\nFix Time and Budget, Flex Scope + Have an Enemy\nIt Shouldn’t be a Chore\n\n\n Build Less\nUnderdo your competition\nConventional + wisdom says that to beat your competitors you need to one-up them. If they + have four features, you need five (or 15, or 25). If they’re spending x, you + need to spend xx. If they have 20, you need 30.\nThis sort of one-upping Cold + War mentality is a dead-end. It’s an expensive, defensive, and paranoid way + of building products. Defensive, paranoid companies can’t think ahead, they + can only think behind. They don’t lead, they follow.\nIf you want to build + a company that follows, you might as well put down this book now.\nSo what + to do then? The answer is less. Do less than your com- petitors to beat them. + Solve the simple problems and leave the hairy, difficult, nasty problems to + everyone else. Instead of one- upping, try one-downing. Instead of outdoing, + try underdoing.\nWe’ll cover the concept of less throughout this book, but + for starters, less means:\nLess features\nLess options/preferences\nLess people + and corporate structure Less meetings and abstractions\nLess promises\n\n\n + What’s Your Problem?\nBuild software for yourself\nA great way to build software + is to start out by solving your own problems. You’ll be the target audience + and you’ll know what’s important and what’s not. That gives you a great head + start on delivering a breakout product.\nThe key here is understanding that + you’re not alone. If you’re having this problem, it’s likely hundreds of thousands + of others are in the same boat. There’s your market. Wasn’t that easy?\nBasecamp + originated in a problem: As a design firm we needed a simple way to communicate + with our clients about projects. We started out doing this via client ex- + tranets which we would update manually. But changing the html by hand every + time a project needed to be updated just wasn’t working. These project sites + always seemed to go stale and eventually were abandoned. It was frustrating + because it left us disorganized and left clients in the dark.\nSo we started + looking at other options. Yet every tool we found either 1) didn’t do what + we needed or 2) was bloated with fea- tures we didn’t need – like billing, + strict access controls, charts, graphs, etc. We knew there had to be a better + way so we decided to build our own.\nWhen you solve your own problem, you + create a tool that you’re passionate about. And passion is key. Passion means + you’ll truly use it and care about it. And that’s the best way to get others + to feel passionate about it too.\n\n Scratching your own itch\nThe Open + Source world embraced this mantra a long time ago – they call it “scratching + your own itch.” For the open source developers, it means they get the tools + they want, delivered the way they want them. But the benefit goes much deeper.\nAs + the designer or developer of a new application, you’re faced with hundreds + of micro-decisions each and every day: blue or green? One table or two? Static + or dynamic? Abort or recover? How do we make these decisions? If it’s something + we recognize as being important, we might ask.The rest, we guess.And all that + guessing builds up a kind of debt in our applications – an interconnected + web of assumptions.\nAs a developer, I hate this.The knowledge of all these + small-scale timebombs in the applications I write adds to my stress. Open + Source developers, scratching their own itches, don’t suffer this. Because + they are their own users, they know the correct answers to 90% of the decisions + they have to make. I think this is one of the reasons folks come home after + a hard day of coding and then work on open source: It’s relaxing.\n–Dave Thomas, + The Pragmatic Programmers\n\nBorn out of necessity\nCampaign Monitor really + was born out of necessity. For years we’d been frustrated by the quality of + the email marketing options out there. One tool would do x and y but never + z, the next had y\nand z nailed but just couldn’t get x right.We couldn’t + win.\nWe decided to clear our schedule and have a go at building our dream + email marketing tool.We consciously decided not to look at what everyone else + was doing and instead build something that would make ours and our customer’s + lives a little easier.\nAs it turned out, we weren’t the only ones who were + unhappy with the options out there.We made a few modifications to the software + so any design firm could use it and started spreading the word. In less than + six months, thousands of designers were using Campaign Monitor to send email + newsletters for themselves and their clients.\n–David Greiner, founder, Campaign + Monitor\n\n\n You need to care about it\nWhen you write a book, you need + to have more than an interesting story. You need to have a desire to tell + the story.You need to be personally invested in some way. If you’re going + to live with something for two years, three years, the rest of your life, + you need to care about it.\n–Malcolm Gladwell, author (from A Few Thin Slices + of Malcolm Gladwell)\n\n\n Fund Yourself\nOutside money is plan B\nThe first + priority of many startups is acquiring funding from investors. But remember, + if you turn to outsiders for funding, you’ll have to answer to them too. Expectations + are raised. Investors want their money back – and quickly. The sad fact is + cashing in often begins to trump building a quality product.\nThese days it + doesn’t take much to get rolling. Hardware\nis cheap and plenty of great infrastructure + software is open source and free. And passion doesn’t come with a price tag.\nSo + do what you can with the cash on hand. Think hard and determine what’s really + essential and what you can do without. What can you do with three people instead + of ten? What can you do with $20k instead of $100k? What can you do in three + months instead of six? What can you do if you keep your day job and build + your app on the side?\nConstraints force creativity\nRun on limited resources + and you’ll be forced to reckon with constraints earlier and more intensely. + And that’s a good thing. Constraints drive innovation.\n\n\n Constraints also + force you to get your idea out in the wild sooner rather than later – another + good thing. A month or two out of the gates you should have a pretty good + idea of whether you’re onto something or not. If you are, you’ll be self-sustain- + able shortly and won’t need external cash. If your idea’s a lemon, it’s time + to go back to the drawing board. At least you know now as opposed to months + (or years) down the road. And at least you can back out easily. Exit plans + get a lot trickier once inves- tors are involved.\nIf you’re creating software + just to make a quick buck, it will show. Truth is a quick payout is pretty + unlikely. So focus on building a quality tool that you and your customers + can live with for a long time.\n\nTwo paths\n[Jake Walker started one company + with investor money (Disclive) and one without (The Show). Here he discusses + the differences between the two paths.]\n\nThe root of all the problems wasn’t + raising money itself, but everything that came along with it.The expectations + are simply higher. People start taking salary, and the motivation is to build + it up and sell it, or find some other way for the initial investors to make + their money back. In the case of the first company,\nwe simply started acting + much bigger than we were – out of necessity...\n[With The Show] we realized + that we could deliver a much better product with less costs, only with more + time. And we gambled with a bit of our own money that people would be willing + to wait for quality over speed. But the company has stayed (and will likely + continue to be) a small operation.And ever since that first project, we’ve + been fully self funded.With just a bit of creative terms from our vendors, + we’ve never really need to put much of our own money into the operation at + all.And the expectation isn’t to grow and sell,but to grow for the sake of + growth and to continue to benefit from it financially.\n–A comment from Signal + vs. Noise\n\n","cache_control":{"type":"ephemeral"}}]},{"role":"user","content":"What + is the meaning of Getting Real according to the book? Begin your response + with According to the book,"}],"model":"anthropic/claude-3-haiku","max_tokens":1000,"temperature":0.0}' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:37:35 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a8ed5beeade93-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1731289055-7lM7yhtp335znp1qegkj\",\"provider\":\"Anthropic\",\"model\":\"anthropic/claude-3-haiku\",\"object\":\"chat.completion\",\"created\":1731289055,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"end_turn\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"According + to the book, \\\"Getting Real\\\" is \\\"a smaller, faster, better way to + build software.\\\" The key principles of Getting Real include:\\n\\n1. Skipping + the abstract planning and documentation (like functional specs, wireframes, + etc.) and instead focusing on building the actual product.\\n\\n2. Doing less + - less features, less options, less people, less meetings, etc. The goal is + to be lean and agile rather than bloated and bureaucratic.\\n\\n3. Starting + with the user interface and customer experience, and building backwards from + there. This ensures the product is focused on solving real user problems.\\n\\n4. + Embracing an iterative, launch-and-improve approach rather than trying to + perfect everything upfront. Web-based software can be constantly updated, + so the focus is on getting something out there quickly and refining it based + on user feedback.\\n\\n5. Avoiding the traditional software development process + of lengthy timelines, big teams, and extensive planning in favor of a more + nimble, resource-constrained approach.\\n\\nThe core idea is to be pragmatic, + focus on the essentials, and get the actual product in front of users as quickly + as possible, rather than getting bogged down in abstract planning and documentation. + This \\\"getting real\\\" approach is presented as an effective way to build + successful web-based software.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":4884,\"completion_tokens\":285,\"total_tokens\":5169}}" + recorded_at: Mon, 11 Nov 2024 01:37:38 GMT +- request: + method: get + uri: https://openrouter.ai/api/v1/generation?id=gen-1731289055-7lM7yhtp335znp1qegkj + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:37:40 GMT + Content-Type: + - application/json; charset=UTF-8 + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a8ef5dbb79e16-EWR + body: + encoding: ASCII-8BIT + string: '{"data":{"id":"gen-1731289055-7lM7yhtp335znp1qegkj","upstream_id":"msg_01LqVPLhTPzzk2dDSGd826AH","total_cost":0.0004688775,"cache_discount":0.0010926,"provider_name":"Anthropic","created_at":"2024-11-11T01:37:39.137992+00:00","model":"anthropic/claude-3-haiku","app_id":179379,"streamed":true,"cancelled":false,"latency":787,"moderation_latency":230,"generation_time":1905,"finish_reason":"end_turn","tokens_prompt":4538,"tokens_completion":257,"native_tokens_prompt":4884,"native_tokens_completion":285,"native_tokens_reasoning":null,"num_media_prompt":null,"num_media_completion":null,"origin":"https://github.com/OlympiaAI/open_router","usage":0.0004688775}}' + recorded_at: Mon, 11 Nov 2024 01:37:40 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/MeaningOfLife/does_a_completion_with_OpenAI.yml b/spec/vcr/MeaningOfLife/does_a_completion_with_OpenAI.yml new file mode 100644 index 0000000..f52e6dc --- /dev/null +++ b/spec/vcr/MeaningOfLife/does_a_completion_with_OpenAI.yml @@ -0,0 +1,112 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.openai.com/v1/chat/completions + body: + encoding: UTF-8 + string: '{"max_completion_tokens":16384,"seed":9999,"temperature":0.0,"model":"gpt-4o","messages":[{"role":"user","content":"What + is the meaning of life?"}]}' + headers: + Content-Type: + - application/json + Authorization: + - Bearer REDACTED + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:39:49 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Expose-Headers: + - X-Request-ID + Openai-Organization: + - user-4zwavkzyrdiz309q8ya0cgco + Openai-Processing-Ms: + - '4097' + Openai-Version: + - '2020-10-01' + X-Ratelimit-Limit-Requests: + - '10000' + X-Ratelimit-Limit-Tokens: + - '30000000' + X-Ratelimit-Remaining-Requests: + - '9999' + X-Ratelimit-Remaining-Tokens: + - '29999975' + X-Ratelimit-Reset-Requests: + - 6ms + X-Ratelimit-Reset-Tokens: + - 0s + X-Request-Id: + - req_d02a075405d7a5a759c649f8122f224f + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Cf-Cache-Status: + - DYNAMIC + Set-Cookie: + - __cf_bm=ojMtLbp_7eBOMXVWQTsf8g0ttiS1mCCeNlUcir2Qps4-1731289189-1.0.1.1-9dOHj5V.nRPaGjJifY05F2CNTcp6CBj.gt4rPwtzylL9HOoeIYiSc_JZA8psvTBg4_gmXZ8a7dQfALOzet5bdA; + path=/; expires=Mon, 11-Nov-24 02:09:49 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=TYqMe2vRano0MqvEOy_Eno8gLwd25v9KrOvCjGeJIMI-1731289189951-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + X-Content-Type-Options: + - nosniff + Server: + - cloudflare + Cf-Ray: + - 8e0a9202cad2431b-EWR + Alt-Svc: + - h3=":443"; ma=86400 + body: + encoding: ASCII-8BIT + string: | + { + "id": "chatcmpl-ASDh3mkyUGKlINj5Pd3C60o0iIhsk", + "object": "chat.completion", + "created": 1731289185, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The meaning of life is a profound and philosophical question that has been contemplated by thinkers, theologians, and scientists for centuries. Different perspectives offer various interpretations:\n\n1. **Philosophical Perspective**: Philosophers like Aristotle and existentialists like Jean-Paul Sartre have explored life's meaning through concepts like purpose, happiness, and individual freedom. For some, the meaning of life is about finding personal fulfillment and creating one's own purpose.\n\n2. **Religious Perspective**: Many religions provide their own interpretations, often involving a relationship with a higher power, spiritual growth, and adherence to certain moral or ethical codes. For example, in Christianity, the meaning of life might involve serving God and preparing for an afterlife.\n\n3. **Scientific Perspective**: From a scientific standpoint, life can be seen as a series of biological processes. Some scientists and secular thinkers might argue that life has no inherent meaning beyond survival and reproduction, and any meaning is constructed by individuals.\n\n4. **Personal Perspective**: On a personal level, many people find meaning through relationships, achievements, creativity, and contributing to the well-being of others.\n\nUltimately, the meaning of life is subjective and can vary greatly from person to person. It often involves a combination of personal beliefs, cultural influences, and individual experiences.", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 14, + "completion_tokens": 257, + "total_tokens": 271, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_159d8341cc" + } + recorded_at: Mon, 11 Nov 2024 01:39:49 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/MeaningOfLife/does_a_completion_with_OpenRouter.yml b/spec/vcr/MeaningOfLife/does_a_completion_with_OpenRouter.yml new file mode 100644 index 0000000..bd59c2e --- /dev/null +++ b/spec/vcr/MeaningOfLife/does_a_completion_with_OpenRouter.yml @@ -0,0 +1,130 @@ +--- +http_interactions: +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the meaning of life?"}],"model":"meta-llama/llama-3-8b-instruct:free","max_tokens":1000,"seed":9999,"temperature":0.0}' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:39:50 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a921d8bb842a6-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n{\"id\":\"gen-1731289190-DSagLOMzjok7vvakKnSH\",\"provider\":\"Lepton\",\"model\":\"meta-llama/llama-3-8b-instruct\",\"object\":\"chat.completion\",\"created\":1731289190,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"The + meaning of life is a question that has puzzled philosophers, scientists, and + thinkers for centuries. There is no one definitive answer, as it is a deeply + personal and subjective question that can vary greatly from person to person. + However, here are some possible perspectives and insights that may help shed + some light on this question:\\n\\n1. **Existentialism**: According to existentialist + philosophers like Jean-Paul Sartre and Martin Heidegger, the meaning of life + is not predetermined or given by external forces. Instead, it is created by + individuals through their choices, actions, and experiences. In this view, + the meaning of life is subjective and personal, and it is up to each individual + to create their own meaning.\\n2. **Purpose**: Some people believe that the + meaning of life is to find one's purpose or passion. This could be a career, + a hobby, or a personal goal that brings fulfillment and satisfaction. According + to this view, the meaning of life is to pursue one's purpose with dedication + and enthusiasm.\\n3. **Happiness**: Another perspective is that the meaning + of life is to find happiness and well-being. This could be achieved through + relationships, personal growth, or a sense of accomplishment. According to + this view, the meaning of life is to cultivate happiness and fulfillment in + one's life.\\n4. **Spirituality**: For many people, the meaning of life is + connected to their spiritual beliefs or practices. This could include a sense + of connection to a higher power, a sense of purpose or direction, or a sense + of transcendence or unity with the universe.\\n5. **Evolutionary perspective**: + From an evolutionary perspective, the meaning of life could be seen as the + perpetuation of the species. According to this view, the meaning of life is + to survive and reproduce, ensuring the continuation of the human species.\\n6. + **Cosmic perspective**: Some people believe that the meaning of life is to + understand our place in the universe and to find our connection to the cosmos. + According to this view, the meaning of life is to explore, discover, and appreciate + the vastness and complexity of the universe.\\n7. **Moral purpose**: Another + perspective is that the meaning of life is to live a life of moral purpose + and integrity. According to this view, the meaning of life is to act with + kindness, compassion, and justice, and to make a positive impact on the world.\\n8. + **Self-actualization**: According to humanistic psychologist Abraham Maslow, + the meaning of life is to self-actualize, or to become the best version of + oneself. According to this view, the meaning of life is to realize one's full + potential and to live a life of authenticity and purpose.\\n\\nUltimately, + the meaning of life is a deeply personal and subjective question that can + vary greatly from person to person. While these perspectives may provide some + insights, the meaning of life is ultimately a mystery that each individual + must discover for themselves.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":17,\"completion_tokens\":591,\"total_tokens\":608}}" + recorded_at: Mon, 11 Nov 2024 01:39:56 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/MeaningOfLife/with_predicted_outputs/does_a_completion_with_OpenAI.yml b/spec/vcr/MeaningOfLife/with_predicted_outputs/does_a_completion_with_OpenAI.yml new file mode 100644 index 0000000..a86662a --- /dev/null +++ b/spec/vcr/MeaningOfLife/with_predicted_outputs/does_a_completion_with_OpenAI.yml @@ -0,0 +1,115 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.openai.com/v1/chat/completions + body: + encoding: UTF-8 + string: '{"prediction":{"type":"content","content":"THE MEANING OF LIFE CAN + VARY GREATLY FROM PERSON TO PERSON, OFTEN INVOLVING THE PURSUIT OF HAPPINESS, + CARE OF OTHERS, AND PERSONAL GROWTH!."},"max_tokens":1000,"seed":9999,"temperature":0.0,"model":"gpt-4o","messages":[{"role":"system","content":"Answer + the user question in ALL CAPS."},{"role":"user","content":"WHAT IS THE MEANING + OF LIFE?"}]}' + headers: + Content-Type: + - application/json + Authorization: + - Bearer REDACTED + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:40:02 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Expose-Headers: + - X-Request-ID + Openai-Organization: + - user-4zwavkzyrdiz309q8ya0cgco + Openai-Processing-Ms: + - '5627' + Openai-Version: + - '2020-10-01' + X-Ratelimit-Limit-Requests: + - '10000' + X-Ratelimit-Limit-Tokens: + - '30000000' + X-Ratelimit-Remaining-Requests: + - '9999' + X-Ratelimit-Remaining-Tokens: + - '29998980' + X-Ratelimit-Reset-Requests: + - 6ms + X-Ratelimit-Reset-Tokens: + - 2ms + X-Request-Id: + - req_de338f1746bdd8b60075e860ac443b38 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Cf-Cache-Status: + - DYNAMIC + Set-Cookie: + - __cf_bm=KCT28kt.cWctFcq.9v1Hhc9cvmwSGQ5h1k88cTAGZkE-1731289202-1.0.1.1-PpFuXMgkWlGUsId9iWR_fb6V2iX43iLFuz6SuJsQk69VfP3RJbwr73npBPpk3nHFgLbulh5fmx5f1OEbMkpKkg; + path=/; expires=Mon, 11-Nov-24 02:10:02 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=hdT9ILRoU8UmgdZ5KPYkbVPSc9lB_kjGON1oI3PGpvA-1731289202566-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + X-Content-Type-Options: + - nosniff + Server: + - cloudflare + Cf-Ray: + - 8e0a92471b92422e-EWR + Alt-Svc: + - h3=":443"; ma=86400 + body: + encoding: ASCII-8BIT + string: | + { + "id": "chatcmpl-ASDhGbSXW2YQ6hm0XBUSXda1oWqXy", + "object": "chat.completion", + "created": 1731289198, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "THE MEANING OF LIFE IS A SUBJECTIVE QUESTION THAT VARIES GREATLY DEPENDING ON PERSONAL BELIEFS, PHILOSOPHICAL VIEWS, AND CULTURAL BACKGROUNDS. SOME PEOPLE FIND MEANING THROUGH RELIGION, OTHERS THROUGH CONNECTIONS WITH FAMILY AND FRIENDS, PURSUIT OF KNOWLEDGE, OR CONTRIBUTING TO SOCIETY. ULTIMATELY, IT'S ABOUT WHAT GIVES YOU PURPOSE AND FULFILLMENT.", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 40, + "completion_tokens": 139, + "total_tokens": 179, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 6, + "rejected_prediction_tokens": 37 + } + }, + "system_fingerprint": "fp_72bbfa6014" + } + recorded_at: Mon, 11 Nov 2024 01:40:02 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/Raix_Predicate/maybe.yml b/spec/vcr/Raix_Predicate/maybe.yml new file mode 100644 index 0000000..98641c3 --- /dev/null +++ b/spec/vcr/Raix_Predicate/maybe.yml @@ -0,0 +1,64 @@ +--- +http_interactions: +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":"Always answer ''Yes, '', ''No, + '', or ''Maybe, '' followed by a concise explanation!"},{"role":"user","content":"Should + I quit my job?"}],"model":"meta-llama/llama-3-8b-instruct:free","max_tokens":1000,"temperature":0.0}' + headers: + Authorization: + - REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:30:51 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a84f979c8c42a-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1731288651-EY4eenIoR1d4niMiwMoK\",\"provider\":\"Lepton\",\"model\":\"meta-llama/llama-3-8b-instruct\",\"object\":\"chat.completion\",\"created\":1731288651,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"Maybe, it depends on the specific situation and context.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":42,\"completion_tokens\":76,\"total_tokens\":118}}" + recorded_at: Mon, 11 Nov 2024 01:30:52 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/Raix_Predicate/no.yml b/spec/vcr/Raix_Predicate/no.yml new file mode 100644 index 0000000..7ca43f9 --- /dev/null +++ b/spec/vcr/Raix_Predicate/no.yml @@ -0,0 +1,62 @@ +--- +http_interactions: +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":"Always answer ''Yes, '', ''No, + '', or ''Maybe, '' followed by a concise explanation!"},{"role":"user","content":"Is + the Eiffel Tower in Madrid?"}],"model":"meta-llama/llama-3-8b-instruct:free","max_tokens":1000,"temperature":0.0}' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:30:50 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a84f3c9964339-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1731288651-3phJY0AHxIfda4tzhonr\",\"provider\":\"Lepton\",\"model\":\"meta-llama/llama-3-8b-instruct\",\"object\":\"chat.completion\",\"created\":1731288651,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"No, + the Eiffel Tower is located in Paris, France, not Madrid, Spain.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":45,\"completion_tokens\":20,\"total_tokens\":65}}" + recorded_at: Mon, 11 Nov 2024 01:30:51 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/Raix_Predicate/yes.yml b/spec/vcr/Raix_Predicate/yes.yml new file mode 100644 index 0000000..9149614 --- /dev/null +++ b/spec/vcr/Raix_Predicate/yes.yml @@ -0,0 +1,62 @@ +--- +http_interactions: +- request: + method: post + uri: https://openrouter.ai/api/v1/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":"Always answer ''Yes, '', ''No, + '', or ''Maybe, '' followed by a concise explanation!"},{"role":"user","content":"Is + Ruby on Rails a web application framework?"}],"model":"meta-llama/llama-3-8b-instruct:free","max_tokens":1000,"temperature":0.0}' + headers: + Authorization: + - Bearer REDACTED + Content-Type: + - application/json + X-Title: + - OpenRouter Ruby Client + Http-Referer: + - https://github.com/OlympiaAI/open_router + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:30:50 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Allow-Origin: + - "*" + Cf-Placement: + - local-EWR + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + Vary: + - Accept-Encoding + Server: + - cloudflare + Cf-Ray: + - 8e0a84ef1f931967-EWR + body: + encoding: ASCII-8BIT + string: "\n \n\n \n\n \n\n \n\n \n\n + \ \n\n \n\n \n\n \n\n \n\n \n\n + \ \n{\"id\":\"gen-1731288650-XUq3WyEJOxhengNF9FHk\",\"provider\":\"Lepton\",\"model\":\"meta-llama/llama-3-8b-instruct\",\"object\":\"chat.completion\",\"created\":1731288650,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"stop\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"Yes, Ruby on Rails is a web application framework.\",\"refusal\":\"\"}}],\"usage\":{\"prompt_tokens\":45,\"completion_tokens\":25,\"total_tokens\":70}}" + recorded_at: Mon, 11 Nov 2024 01:30:50 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/vcr/WhatIsTheWeather/can_call_a_function_and_loop_to_provide_text_response.yml b/spec/vcr/WhatIsTheWeather/can_call_a_function_and_loop_to_provide_text_response.yml new file mode 100644 index 0000000..f0b18d8 --- /dev/null +++ b/spec/vcr/WhatIsTheWeather/can_call_a_function_and_loop_to_provide_text_response.yml @@ -0,0 +1,235 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.openai.com/v1/chat/completions + body: + encoding: UTF-8 + string: '{"max_completion_tokens":16384,"seed":9999,"temperature":0.0,"tools":[{"type":"function","function":{"name":"check_weather","parameters":{"type":"object","properties":{"location":{"type":"string"}}},"description":"Check + the weather for a location"}}],"model":"gpt-4o","messages":[{"role":"user","content":"What + is the weather in Zipolite, Oaxaca?"}]}' + headers: + Content-Type: + - application/json + Authorization: + - Bearer REDACTED + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:38:30 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Expose-Headers: + - X-Request-ID + Openai-Organization: + - user-4zwavkzyrdiz309q8ya0cgco + Openai-Processing-Ms: + - '1522' + Openai-Version: + - '2020-10-01' + X-Ratelimit-Limit-Requests: + - '10000' + X-Ratelimit-Limit-Tokens: + - '30000000' + X-Ratelimit-Remaining-Requests: + - '9999' + X-Ratelimit-Remaining-Tokens: + - '29999973' + X-Ratelimit-Reset-Requests: + - 6ms + X-Ratelimit-Reset-Tokens: + - 0s + X-Request-Id: + - req_bde7c4103d282f5b99f3a203f24ea6d7 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Cf-Cache-Status: + - DYNAMIC + Set-Cookie: + - __cf_bm=AeOmZgC2SVURbXv9yu9sTrYUDxSpOmqCEpZee5UBdIY-1731289110-1.0.1.1-KHtAcVIudUmZcUrBfMenWTBpnriJWZ7zLmNdOHXg6_E0AzrF9oUdBvmhNkToyww0ET3tHlB3wnAWNirFkC7xpg; + path=/; expires=Mon, 11-Nov-24 02:08:30 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=wqGLhhvUPvCLRIE1Q18f0mxUAT_Tn4FtYSeFHsOprhM-1731289110227-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + X-Content-Type-Options: + - nosniff + Server: + - cloudflare + Cf-Ray: + - 8e0a9020996841e1-EWR + Alt-Svc: + - h3=":443"; ma=86400 + body: + encoding: ASCII-8BIT + string: | + { + "id": "chatcmpl-ASDfohdIyygHjk30tXYfeeiwPiW6q", + "object": "chat.completion", + "created": 1731289108, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_wXrgPz7Ako28ZVXD7JNRodUY", + "type": "function", + "function": { + "name": "check_weather", + "arguments": "{\"location\":\"Zipolite, Oaxaca\"}" + } + } + ], + "refusal": null + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 54, + "completion_tokens": 17, + "total_tokens": 71, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_159d8341cc" + } + recorded_at: Mon, 11 Nov 2024 01:38:30 GMT +- request: + method: post + uri: https://api.openai.com/v1/chat/completions + body: + encoding: UTF-8 + string: '{"max_completion_tokens":16384,"seed":9999,"temperature":0.0,"tools":[{"type":"function","function":{"name":"check_weather","parameters":{"type":"object","properties":{"location":{"type":"string"}}},"description":"Check + the weather for a location"}}],"model":"gpt-4o","messages":[{"role":"user","content":"What + is the weather in Zipolite, Oaxaca?"},{"role":"assistant","content":null,"tool_calls":[{"id":"0cb04f91-758a-4ef3-8432","type":"function","function":{"name":"check_weather","arguments":"{\"location\":\"Zipolite, + Oaxaca\"}"}}]},{"role":"tool","tool_call_id":"0cb04f91-758a-4ef3-8432","name":"check_weather","content":"The + weather in Zipolite, Oaxaca is hot and sunny"}]}' + headers: + Content-Type: + - application/json + Authorization: + - Bearer REDACTED + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 11 Nov 2024 01:38:31 GMT + Content-Type: + - application/json + Transfer-Encoding: + - chunked + Connection: + - keep-alive + Access-Control-Expose-Headers: + - X-Request-ID + Openai-Organization: + - user-4zwavkzyrdiz309q8ya0cgco + Openai-Processing-Ms: + - '652' + Openai-Version: + - '2020-10-01' + X-Ratelimit-Limit-Requests: + - '10000' + X-Ratelimit-Limit-Tokens: + - '30000000' + X-Ratelimit-Remaining-Requests: + - '9999' + X-Ratelimit-Remaining-Tokens: + - '29999958' + X-Ratelimit-Reset-Requests: + - 6ms + X-Ratelimit-Reset-Tokens: + - 0s + X-Request-Id: + - req_ddc56a0dcd3b6e5741d3ae807de72898 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Cf-Cache-Status: + - DYNAMIC + Set-Cookie: + - __cf_bm=OneP2ANhmWGuVo7MTwHvA3vmqlym8UelFilYvTIzDuo-1731289111-1.0.1.1-4zAn6.ho3OCCFvVM5Ogi.Mbop72NkVsMoapTbv5QEGRc5qDrMdnmFiSzhOx0qppfVDBhtpt9xY4N2wPwRrSXrw; + path=/; expires=Mon, 11-Nov-24 02:08:31 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=dCaA8Gm9s1J6BCot9GBa6XfAcP1gHQ9OEmt9bqBfxAg-1731289111081-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + X-Content-Type-Options: + - nosniff + Server: + - cloudflare + Cf-Ray: + - 8e0a902b391b8cec-EWR + Alt-Svc: + - h3=":443"; ma=86400 + body: + encoding: ASCII-8BIT + string: | + { + "id": "chatcmpl-ASDfqSLtHr8S4RYa6slYi5WrLcSEV", + "object": "chat.completion", + "created": 1731289110, + "model": "gpt-4o-2024-08-06", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "The weather in Zipolite, Oaxaca is currently hot and sunny.", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 90, + "completion_tokens": 14, + "total_tokens": 104, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": "fp_159d8341cc" + } + recorded_at: Mon, 11 Nov 2024 01:38:31 GMT +recorded_with: VCR 6.2.0