Enhance integration capabilities by enabling passing of initial prompt to LLM from command line
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
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?
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.
@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