open-interpreter icon indicating copy to clipboard operation
open-interpreter copied to clipboard

Enhance integration capabilities by enabling passing of initial prompt to LLM from command line

Open funwarioisii opened this issue 1 year ago • 3 comments

Describe the changes you have made:

I have added the ability to pass initial prompts from the command line to the LLM to improve integration with other files and processes.

For example, when I write DDL in a web application, I can make the work more routine to have the model file and its tests written.

Here is what I do when I am developing a Rails application. After writing the DDL, I create the model files, add validation, write mock, and add type information for GraphQL.

exmaple(click me)
$ cat db/schemata/books.schema
create_table "books" do |t|
  t.string 'title'
  t.timestamps
end

$ TABLE="books.schema" bundle exec rake llm:generate
$ cat prompt.txt
    I am developing a web service using Rails, ridgepole, and graphql-ruby.
    Please read db/schemata/#{model_name}.schema and carry out the following tasks:

    - Create a model file in app/models
    - Create a GraphQL type file in app/graphql/types
    - Create a mock using FactoryBot in spec/factories

    For example, if the schema is db/schemata/quests.schema,

    create_table 'quests',
                 id: :integer,
                 unsigned: true,
                 force: :cascade,
                 options: 'ENGINE=InnoDB' do |t|
      t.string 'title', null: false
      t.text 'description', null: false

      t.bigint 'user_id', null: false, unsigned: true
      t.bigint 'category_id', null: false, unsigned: true

      t.datetime 'start_at', null: false
      t.datetime 'end_at', null: false

      t.timestamps

      t.index ['category_id']
    end

    Then the following should be created:

    ## Create a model file in app/models

    Create app/models/quest.rb with,

    # frozen_string_literal: true

    class Quest < ApplicationRecord
      belongs_to :user
      belongs_to :category

      validates :title, presence: true
      validates :description, presence: true
      validates :start_at, presence: true
      validates :end_at, presence: true
    end

    written inside.

    ## Create a GraphQL type file in app/graphql/types

    Create app/graphql/types/quest_type.rb with,

    # frozen_string_literal: true

    module Types
      class QuestType < Types::BaseObject
        field :id, Integer, null: false

        field :description, String, null: false
        field :title, String, null: false

        field :category, Types::CategoryType, null: false
        field :user, Types::UserType, null: false

        field :end_at, GraphQL::Types::ISO8601DateTime, null: false
        field :start_at, GraphQL::Types::ISO8601DateTime, null: false

        field :created_at, GraphQL::Types::ISO8601DateTime, null: false
        field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
      end
    end

    written inside.

    ## Create a mock using FactoryBot in spec/factories

    Create spec/factories/quests.rb with,

    # frozen_string_literal: true

    FactoryBot.define do
      factory :quest do
        title { 'MyString' }
        description { 'MyText' }

        start_at { Time.zone.now - 1.year }
        end_at { Time.zone.now + 1.year }

        association :user, factory: :user
        association :category, factory: :category
      end
    end

    written inside.

$ interpreter -y --load_message=prompt.txt
(...)

Reference any relevant issues (e.g. "Fixes #000"):

Pre-Submission Checklist (optional but appreciated):

  • [x] I have included relevant documentation updates (stored in /docs)
  • [x] I have read docs/CONTRIBUTING.md
  • [x] I have read docs/ROADMAP.md

OS Tests (optional but appreciated):

  • [ ] Tested on Windows
  • [x] Tested on MacOS
  • [ ] Tested on Linux

funwarioisii avatar Mar 19 '24 04:03 funwarioisii

Hi @funwarioisii Thank you for the PR. I like the idea of being able to launch OI with a file as an argument but I don't know if this implementation is correct. Why does core need to know about the file?

MikeBirdTech avatar Mar 20 '24 23:03 MikeBirdTech

Hi @MikeBirdTech Thank you for your review comments.

The reasons for the changes to core are as follows.

First, let me explain my understanding of the original implementation. This implementation passes messages from #terminal_interface to core.OpenInterpreter#chat and OpenInterpreter#chat to #terminal_interface. In this way, the terminal_interface is able to repeatedly output and input messages.

#terminal_interface sets the flag interactive to False if the message has been input from the beginning.

https://github.com/OpenInterpreter/open-interpreter/blob/57aeea6185fa8329d5a1f5521967351f6a5a1ec7/interpreter/terminal_interface/terminal_interface.py#L71-L74

And if interactive is False, the conversation will be terminated. https://github.com/OpenInterpreter/open-interpreter/blob/57aeea6185fa8329d5a1f5521967351f6a5a1ec7/interpreter/terminal_interface/terminal_interface.py#L433-L435

So, going back to the beginning, if we pass messages in the initial state, interactive will always be False, and the mechanism to go back and forth between #terminal_interface and core.OpenInterpreter#chat will break.

Therefore, I believe it is necessary to create a special bypass for core.OpenInterpreter#chat. I considered alternatives, such as using the length of interpreter.messages inside #terminal_interface to avoid having to modify core.OpenInterpreter#chat directly, but these did not work out well, resulting in infinite loops, among other issues.

funwarioisii avatar Mar 21 '24 03:03 funwarioisii

@MikeBirdTech

I thought about it for a while and found a good way. No more changes to core are needed.

https://github.com/OpenInterpreter/open-interpreter/pull/1097/commits/cac6528db77712e050121df01bb65c69e736f42f

funwarioisii avatar Mar 21 '24 03:03 funwarioisii