Skip to content

Commit 6104f6d

Browse files
authored
Merge pull request #1232 from imapersonman/main
Contributing interaction and sending command probably
2 parents 77f11f2 + 65a1f11 commit 6104f6d

File tree

6 files changed

+229
-26
lines changed

6 files changed

+229
-26
lines changed

interpreter/core/core.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def __init__(
7373
skills_path=None,
7474
import_skills=False,
7575
multi_line=False,
76+
contribute_conversation=False
7677
):
7778
# State
7879
self.messages = [] if messages is None else messages
@@ -90,6 +91,7 @@ def __init__(
9091
self.disable_telemetry = disable_telemetry
9192
self.in_terminal_interface = in_terminal_interface
9293
self.multi_line = multi_line
94+
self.contribute_conversation = contribute_conversation
9395

9496
# Loop messages
9597
self.force_task_completion = force_task_completion
@@ -136,6 +138,11 @@ def wait(self):
136138
def anonymous_telemetry(self) -> bool:
137139
return not self.disable_telemetry and not self.offline
138140

141+
@property
142+
def will_contribute(self):
143+
overrides = self.offline or not self.conversation_history or self.disable_telemetry
144+
return self.contribute_conversation and not overrides
145+
139146
def chat(self, message=None, display=True, stream=False, blocking=True):
140147
try:
141148
self.responding = True

interpreter/core/utils/telemetry.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,3 @@ def send_telemetry(event_name, properties=None):
6363
pass
6464

6565

66-
def contribute_conversations(conversations):
67-
url = "https://api.openinterpreter.com/v0/conversations/contribute/"
68-
version = pkg_resources.get_distribution("open-interpreter").version
69-
70-
if conversations and len(conversations) > 1:
71-
payload = {
72-
"conversations": [conv for sublist in conversations for conv in sublist],
73-
"oi_version": version
74-
}
75-
else:
76-
payload = {
77-
"conversations": [conversations[0]],
78-
"oi_version": version
79-
}
80-
try:
81-
response = requests.post(url, json=payload)
82-
if response.status_code != 200:
83-
print(f"Failed to contribute conversation: {response.status_code} {response.text}")
84-
return None
85-
else:
86-
print(f"Successfully contributed conversation!")
87-
except requests.RequestException as e:
88-
print(f"Failed to contribute conversation: {e}")
89-
return None
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import os
2+
import json
3+
import time
4+
from typing import List, TypedDict
5+
6+
import pkg_resources
7+
import requests
8+
9+
from interpreter.terminal_interface.profiles.profiles import write_key_to_profile
10+
from interpreter.terminal_interface.utils.display_markdown_message import display_markdown_message
11+
12+
13+
contribute_cache_path = os.path.join(
14+
os.path.expanduser("~"), ".cache", "open-interpreter", "contribute.json"
15+
)
16+
17+
18+
def display_contribution_message():
19+
display_markdown_message(
20+
"""
21+
---
22+
> We're training an open-source language model!
23+
24+
You can help us train it with your past, current, or future conversations by:
25+
1. Closing out of OpenInterpreter,
26+
2. Running `interpreter --contribute_conversation`.
27+
"""
28+
)
29+
time.sleep(1)
30+
31+
32+
def display_contributing_current_message():
33+
display_markdown_message(
34+
f"""
35+
---
36+
> This conversation will be used to train OpenInterpreter's language model.
37+
"""
38+
)
39+
40+
41+
def send_past_conversations(interpreter):
42+
past_conversations = get_all_conversations(interpreter)
43+
if len(past_conversations) > 0:
44+
print()
45+
print("Sending all previous conversations to OpenInterpreter...")
46+
contribute_conversations(past_conversations)
47+
print()
48+
49+
50+
def set_send_future_conversations(interpreter, should_send_future):
51+
write_key_to_profile("contribute_conversation", should_send_future)
52+
display_markdown_message(
53+
"""
54+
> OpenInterpreter will contribute all your conversations from now on.
55+
56+
To change this, consult the documentation at [https://unassuminglink.com](https://www.readthefuckingmanual.com).
57+
"""
58+
)
59+
60+
61+
def user_wants_to_contribute_past():
62+
print("Would you like to contribute all past conversations?")
63+
response = input("(y/n) ")
64+
return response.lower() == "y"
65+
66+
67+
def user_wants_to_contribute_future():
68+
print("Would you like to contribute all future conversations?")
69+
response = input("(y/n) ")
70+
return response.lower() == "y"
71+
72+
73+
def contribute_conversation_launch_logic(interpreter):
74+
contribution_cache = get_contribute_cache_contents()
75+
76+
if interpreter.will_contribute:
77+
contribute_past_and_future_logic(interpreter, contribution_cache)
78+
elif not contribution_cache["displayed_contribution_message"]:
79+
display_contribution_message()
80+
81+
# don't show the contribution message again no matter what.
82+
contribution_cache["displayed_contribution_message"] = True
83+
write_to_contribution_cache(contribution_cache)
84+
85+
86+
class ContributionCache(TypedDict):
87+
displayed_contribution_message: bool
88+
asked_to_contribute_past: bool
89+
asked_to_contribute_future: bool
90+
91+
92+
# modifies the contribution cache!
93+
def contribute_past_and_future_logic(
94+
interpreter, contribution_cache: ContributionCache
95+
):
96+
if not contribution_cache["asked_to_contribute_past"]:
97+
if user_wants_to_contribute_past():
98+
send_past_conversations(interpreter)
99+
contribution_cache["asked_to_contribute_past"] = True
100+
101+
if not contribution_cache["asked_to_contribute_future"]:
102+
if user_wants_to_contribute_future():
103+
set_send_future_conversations(interpreter, True)
104+
contribution_cache["asked_to_contribute_future"] = True
105+
106+
display_contributing_current_message()
107+
108+
109+
# Returns a {"asked_to_run_contribute": bool, "asked_to_contribute_past": bool}
110+
# as the first part of its Tuple, a bool as a second.
111+
# Writes the contribution cache file if it doesn't already exist.
112+
# The bool is True if the file does not already exist, False if it does.
113+
def get_contribute_cache_contents() -> ContributionCache:
114+
if not os.path.exists(contribute_cache_path):
115+
default_dict: ContributionCache = {
116+
"asked_to_contribute_past": False,
117+
"displayed_contribution_message": False,
118+
"asked_to_contribute_future": False,
119+
}
120+
with open(contribute_cache_path, "a") as file:
121+
file.write(json.dumps(default_dict))
122+
return default_dict
123+
else:
124+
with open(contribute_cache_path, "r") as file:
125+
contribute_cache = json.load(file)
126+
return contribute_cache
127+
128+
129+
# Takes in a {"asked_to_run_contribute": bool, "asked_to_contribute_past": bool}
130+
def write_to_contribution_cache(contribution_cache: ContributionCache):
131+
with open(contribute_cache_path, "w") as file:
132+
json.dump(contribution_cache, file)
133+
134+
135+
def get_all_conversations(interpreter) -> List[List]:
136+
def is_conversation_path(path: str):
137+
_, ext = os.path.splitext(path)
138+
return ext == ".json"
139+
140+
history_path = interpreter.conversation_history_path
141+
all_conversations: List[List] = []
142+
conversation_files = os.listdir(history_path) if os.path.exists(history_path) else []
143+
for mpath in conversation_files:
144+
if not is_conversation_path(mpath):
145+
continue
146+
full_path = os.path.join(history_path, mpath)
147+
with open(full_path, "r") as cfile:
148+
conversation = json.load(cfile)
149+
all_conversations.append(conversation)
150+
return all_conversations
151+
152+
153+
def is_list_of_lists(l):
154+
return isinstance(l, list) and all([isinstance(e, list) for e in l])
155+
156+
157+
def contribute_conversations(conversations: List[List]):
158+
if len(conversations) == 0 or len(conversations[0]) == 0:
159+
return None
160+
161+
url = "https://api.openinterpreter.com/v0/conversations/contribute/"
162+
version = pkg_resources.get_distribution("open-interpreter").version
163+
164+
payload = {"conversations": conversations, "oi_version": version}
165+
166+
assert is_list_of_lists(payload["conversations"]), "the contribution payload is not a list of lists!"
167+
168+
try:
169+
response = requests.post(url, json=payload)
170+
if response.status_code != 200:
171+
print(
172+
f"Failed to contribute conversation: {response.status_code} {response.text}"
173+
)
174+
return None
175+
else:
176+
print(f"Successfully contributed conversations!")
177+
except requests.RequestException as e:
178+
print(f"Failed to contribute conversation: {e}")
179+
return None

interpreter/terminal_interface/profiles/profiles.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,6 @@ def apply_profile_to_object(obj, profile):
566566
else:
567567
setattr(obj, key, value)
568568

569-
570569
def open_storage_dir(directory):
571570
dir = os.path.join(oi_dir, directory)
572571

@@ -759,3 +758,29 @@ def migrate_user_app_directory():
759758
elif user_version == "0.2.0":
760759
old_dir = platformdirs.user_config_dir("Open Interpreter Terminal")
761760
migrate_app_directory(old_dir, oi_dir, profile_dir)
761+
762+
763+
def write_key_to_profile(key, value):
764+
try:
765+
with open(user_default_profile_path, 'r') as file:
766+
lines = file.readlines()
767+
768+
version_line_index = None
769+
new_lines = []
770+
for index, line in enumerate(lines):
771+
if line.strip().startswith("version:"):
772+
version_line_index = index
773+
break
774+
new_lines.append(line)
775+
776+
# Insert the new key-value pair before the version line
777+
if version_line_index is not None:
778+
if f"{key}: {value}\n" not in new_lines:
779+
new_lines.append(f"{key}: {value}\n\n") # Adding a newline for separation
780+
# Append the version line and all subsequent lines
781+
new_lines.extend(lines[version_line_index:])
782+
783+
with open(user_default_profile_path, 'w') as file:
784+
file.writelines(new_lines)
785+
except Exception:
786+
pass # Fail silently

interpreter/terminal_interface/start_terminal_interface.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import pkg_resources
66

7+
from interpreter.terminal_interface.contributing_conversations import contribute_conversation_launch_logic, contribute_conversations
8+
79
from ..core.core import OpenInterpreter
810
from .conversation_navigator import conversation_navigator
911
from .profiles.profiles import open_storage_dir, profile, reset_profile
@@ -237,6 +239,12 @@ def start_terminal_interface(interpreter):
237239
"help_text": "get Open Interpreter's version number",
238240
"type": bool,
239241
},
242+
{
243+
"name": "contribute_conversation",
244+
"help_text": "let Open Interpreter use the current conversation to train an Open-Source LLM",
245+
"type": bool,
246+
"attribute": {"object": interpreter, "attr_name": "contribute_conversation"},
247+
}
240248
]
241249

242250
# Check for deprecated flags before parsing arguments
@@ -422,11 +430,13 @@ def start_terminal_interface(interpreter):
422430
if args.server:
423431
interpreter.server()
424432
return
425-
433+
426434
validate_llm_settings(interpreter)
427435

428436
interpreter.in_terminal_interface = True
429437

438+
contribute_conversation_launch_logic(interpreter)
439+
430440
interpreter.chat()
431441

432442

@@ -457,4 +467,8 @@ def main():
457467
except KeyboardInterrupt:
458468
pass
459469
finally:
470+
if interpreter.will_contribute:
471+
contribute_conversations([interpreter.messages])
472+
print("Thank you for contributing to our training data!")
460473
interpreter.computer.terminate()
474+

interpreter/terminal_interface/validate_llm_settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import litellm
99
from prompt_toolkit import prompt
1010

11+
from interpreter.terminal_interface.contributing_conversations import contribute_conversation_launch_logic
12+
1113
from .utils.display_markdown_message import display_markdown_message
1214

1315

0 commit comments

Comments
 (0)