Skip to content

Commit 6ee0586

Browse files
authored
Add remote server support for Ollama, Add template profile, Updated Llamafiles
Add remote server support for Ollama, Add template profile, Updated Llamafiles
2 parents 33d6e55 + fe34c1a commit 6ee0586

File tree

11 files changed

+1478
-1087
lines changed

11 files changed

+1478
-1087
lines changed

docs/guides/profiles.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Profiles are Python files that configure Open Interpreter. A wide range of field
88

99
You can access your Profiles by running `interpreter --profiles`. This will open the directory where all of your Profiles are stored.
1010

11+
If you want to make your own profile, start with the [Template Profile](https://github.com/OpenInterpreter/open-interpreter/blob/main/interpreter/terminal_interface/profiles/defaults/template_profile.py).
12+
1113
To apply a Profile to an Open Interpreter session, you can run `interpreter --profile <name>`
1214

1315
# Example Profile

interpreter/core/async_core.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def __init__(self, *args, **kwargs):
4747
self.output_queue = None
4848
self.unsent_messages = deque()
4949
self.id = os.getenv("INTERPRETER_ID", datetime.now().timestamp())
50-
self.print = True # Will print output
50+
self.print = False # Will print output
5151

5252
self.require_acknowledge = (
5353
os.getenv("INTERPRETER_REQUIRE_ACKNOWLEDGE", "False").lower() == "true"
@@ -121,7 +121,7 @@ def respond(self, run_code=None):
121121
if self.stop_event.is_set():
122122
return
123123

124-
if self.print:
124+
if self.print or self.debug:
125125
if "start" in chunk:
126126
print("\n")
127127
if chunk["type"] in ["code", "console"] and "format" in chunk:
@@ -133,7 +133,11 @@ def respond(self, run_code=None):
133133
if "format" in chunk and "base64" in chunk["format"]:
134134
print("\n[An image was produced]")
135135
else:
136-
print(chunk.get("content", ""), end="", flush=True)
136+
content = chunk.get("content", "")
137+
content = (
138+
str(content).encode("ascii", "ignore").decode("ascii")
139+
)
140+
print(content, end="", flush=True)
137141

138142
self.output_queue.sync_q.put(chunk)
139143

interpreter/core/llm/llm.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -310,34 +310,34 @@ def load(self):
310310

311311
if self.model.startswith("ollama/"):
312312
model_name = self.model.replace("ollama/", "")
313+
api_base = getattr(self, 'api_base', None) or "http://localhost:11434"
314+
names = []
313315
try:
314316
# List out all downloaded ollama models. Will fail if ollama isn't installed
315-
result = subprocess.run(
316-
["ollama", "list"], capture_output=True, text=True, check=True
317-
)
317+
response = requests.get(f"{api_base}/api/tags")
318+
if response.ok:
319+
data = response.json()
320+
names = [
321+
model['name'].replace(":latest", "")
322+
for model in data['models']
323+
if 'name' in model and model['name']
324+
]
325+
318326
except Exception as e:
319327
print(str(e))
320328
self.interpreter.display_message(
321329
f"> Ollama not found\n\nPlease download Ollama from [ollama.com](https://ollama.com/) to use `{model_name}`.\n"
322330
)
323331
exit()
324332

325-
lines = result.stdout.split("\n")
326-
names = [
327-
line.split()[0].replace(":latest", "")
328-
for line in lines[1:]
329-
if line.strip()
330-
] # Extract names, trim out ":latest", skip header
331-
333+
# Download model if not already installed
332334
if model_name not in names:
333335
self.interpreter.display_message(f"\nDownloading {model_name}...\n")
334-
subprocess.run(["ollama", "pull", model_name], check=True)
336+
requests.post(f"{api_base}/api/pull", json={"name": model_name})
335337

336338
# Get context window if not set
337339
if self.context_window == None:
338-
response = requests.post(
339-
"http://localhost:11434/api/show", json={"name": model_name}
340-
)
340+
response = requests.post(f"{api_base}/api/show", json={"name": model_name})
341341
model_info = response.json().get("model_info", {})
342342
context_length = None
343343
for key in model_info:

interpreter/core/llm/run_tool_calling_llm.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
from .utils.merge_deltas import merge_deltas
24
from .utils.parse_partial_json import parse_partial_json
35

@@ -170,6 +172,7 @@ def run_tool_calling_llm(llm, request_params):
170172
function_call_detected = False
171173
accumulated_review = ""
172174
review_category = None
175+
buffer = ""
173176

174177
for chunk in llm.completions(**request_params):
175178
if "choices" not in chunk or len(chunk["choices"]) == 0:
@@ -222,11 +225,23 @@ def run_tool_calling_llm(llm, request_params):
222225
]:
223226
delta["content"] = delta["content"].replace(tag, "")
224227

225-
yield {
226-
"type": "review",
227-
"format": review_category,
228-
"content": delta["content"],
229-
}
228+
if re.search("</.*>$", accumulated_review):
229+
buffer += delta["content"]
230+
continue
231+
elif buffer:
232+
yield {
233+
"type": "review",
234+
"format": review_category,
235+
"content": buffer + delta["content"],
236+
}
237+
buffer = ""
238+
else:
239+
yield {
240+
"type": "review",
241+
"format": review_category,
242+
"content": delta["content"],
243+
}
244+
buffer = ""
230245

231246
else:
232247
yield {"type": "message", "content": delta["content"]}

interpreter/core/respond.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ def respond(interpreter):
9898
"""
9999
)
100100
break
101-
# Provide extra information on how to change API keys, if we encounter that error
102-
# (Many people writing GitHub issues were struggling with this)
101+
102+
# Provide extra information on how to change API keys, if we encounter that error
103+
# (Many people writing GitHub issues were struggling with this)
104+
103105
except Exception as e:
104106
error_message = str(e).lower()
105107
if (
@@ -115,36 +117,34 @@ def respond(interpreter):
115117
interpreter.offline == False and "not have access" in str(e).lower()
116118
):
117119
"""
118-
Check for invalid model in error message and then fallback to groq, then OpenAI.
120+
Check for invalid model in error message and then fallback.
119121
"""
120122
if (
121123
"invalid model" in error_message
122124
or "model does not exist" in error_message
123125
):
124-
provider_message = f" The model '{interpreter.llm.model}' does not exist or is invalid. Please check the model name and try again.\n\nWould you like to try an alternative model instead? (y/n)\n\n "
126+
provider_message = f"\n\nThe model '{interpreter.llm.model}' does not exist or is invalid. Please check the model name and try again.\n\nWould you like to try Open Interpreter's hosted `i` model instead? (y/n)\n\n "
125127
elif "groq" in error_message:
126-
provider_message = f" You do not have access to {interpreter.llm.model}. Please check with Groq for more details.\n\nWould you like to try an alternative model instead? (y/n)\n\n "
128+
provider_message = f"\n\nYou do not have access to {interpreter.llm.model}. Please check with Groq for more details.\n\nWould you like to try Open Interpreter's hosted `i` model instead? (y/n)\n\n "
127129
else:
128-
provider_message = f" You do not have access to {interpreter.llm.model}. You will need to add a payment method and purchase credits for the OpenAI API billing page (different from ChatGPT) to use `GPT-4`.\n\nhttps://platform.openai.com/account/billing/overview\n\nWould you like to try GPT-3.5-TURBO instead? (y/n)\n\n "
130+
provider_message = f"\n\nYou do not have access to {interpreter.llm.model}. If you are using an OpenAI model, you may need to add a payment method and purchase credits for the OpenAI API billing page (this is different from ChatGPT Plus).\n\nhttps://platform.openai.com/account/billing/overview\n\nWould you like to try Open Interpreter's hosted `i` model instead? (y/n)\n\n"
129131

130-
response = input(provider_message)
132+
print(provider_message)
133+
134+
response = input()
131135
print("") # <- Aesthetic choice
132136

133137
if response.strip().lower() == "y":
134-
interpreter.llm.model = "gpt-3.5-turbo-1106"
135-
interpreter.llm.context_window = 16000
136-
interpreter.llm.max_tokens = 4096
137-
interpreter.llm.supports_functions = True
138+
interpreter.llm.model = "i"
139+
display_markdown_message(f"> Model set to `i`")
138140
display_markdown_message(
139-
f"> Model set to `{interpreter.llm.model}`"
141+
"***Note:*** *Conversations with this model will be used to train our open-source model.*\n"
140142
)
143+
141144
else:
142-
raise Exception(
143-
"\n\nYou will need to add a payment method and purchase credits for the OpenAI API billing page (different from ChatGPT) to use GPT-4.\n\nhttps://platform.openai.com/account/billing/overview"
144-
)
145+
raise
145146
elif interpreter.offline and not interpreter.os:
146-
print(traceback.format_exc())
147-
raise Exception("Error occurred. " + str(e))
147+
raise
148148
else:
149149
raise
150150

interpreter/terminal_interface/local_setup.py

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,46 +47,58 @@ def download_model(models_dir, models, interpreter):
4747
try:
4848
model_list = [
4949
{
50-
"name": "Llama-3-8B-Instruct",
51-
"file_name": " Meta-Llama-3-8B-Instruct.Q5_K_M.llamafile",
52-
"size": 5.76,
53-
"url": "https://huggingface.co/jartine/Meta-Llama-3-8B-Instruct-llamafile/resolve/main/Meta-Llama-3-8B-Instruct.Q5_K_M.llamafile?download=true",
50+
"name": "Llama-3.1-8B-Instruct",
51+
"file_name": "Meta-Llama-3-8B-Instruct.Q4_K_M.llamafile",
52+
"size": 4.95,
53+
"url": "https://huggingface.co/Mozilla/Meta-Llama-3.1-8B-Instruct-llamafile/resolve/main/Meta-Llama-3.1-8B-Instruct.Q4_K_M.llamafile?download=true",
54+
},
55+
{
56+
"name": "Gemma-2-9b",
57+
"file_name": "gemma-2-9b-it.Q4_K_M.llamafile",
58+
"size": 5.79,
59+
"url": "https://huggingface.co/jartine/gemma-2-9b-it-llamafile/resolve/main/gemma-2-9b-it.Q4_K_M.llamafile?download=true",
5460
},
5561
{
5662
"name": "Phi-3-mini",
57-
"file_name": "Phi-3-mini-4k-instruct.Q5_K_M.llamafile",
58-
"size": 2.84,
59-
"url": "https://huggingface.co/jartine/Phi-3-mini-4k-instruct-llamafile/resolve/main/Phi-3-mini-4k-instruct.Q5_K_M.llamafile?download=true",
63+
"file_name": "Phi-3-mini-4k-instruct.Q4_K_M.llamafile",
64+
"size": 2.42,
65+
"url": "https://huggingface.co/Mozilla/Phi-3-mini-4k-instruct-llamafile/resolve/main/Phi-3-mini-4k-instruct.Q4_K_M.llamafile?download=true",
6066
},
6167
{
62-
"name": "TinyLlama-1.1B",
63-
"file_name": "TinyLlama-1.1B-Chat-v1.0.Q5_K_M.llamafile",
64-
"size": 0.76,
65-
"url": "https://huggingface.co/jartine/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q5_K_M.llamafile?download=true",
68+
"name": "Moondream2 (vision)",
69+
"file_name": "moondream2-q5km-050824.llamafile",
70+
"size": 1.98,
71+
"url": "https://huggingface.co/cjpais/moondream2-llamafile/resolve/main/moondream2-q5km-050824.llamafile?download=true",
6672
},
6773
{
68-
"name": "Rocket-3B",
69-
"file_name": "rocket-3b.Q5_K_M.llamafile",
70-
"size": 1.89,
71-
"url": "https://huggingface.co/jartine/rocket-3B-llamafile/resolve/main/rocket-3b.Q5_K_M.llamafile?download=true",
74+
"name": "Mistral-7B-Instruct",
75+
"file_name": "Mistral-7B-Instruct-v0.3.Q5_K_M.llamafile",
76+
"size": 4.40,
77+
"url": "https://huggingface.co/Mozilla/Mistral-7B-Instruct-v0.3-llamafile/resolve/main/Mistral-7B-Instruct-v0.3.Q4_K_M.llamafile?download=true",
7278
},
7379
{
74-
"name": "Phi-2",
75-
"file_name": "phi-2.Q5_K_M.llamafile",
76-
"size": 1.96,
77-
"url": "https://huggingface.co/jartine/phi-2-llamafile/resolve/main/phi-2.Q5_K_M.llamafile?download=true",
80+
"name": "Gemma-2-27b",
81+
"file_name": "gemma-2-27b-it.Q4_K_M.llamafile",
82+
"size": 16.7,
83+
"url": "https://huggingface.co/jartine/gemma-2-27b-it-llamafile/resolve/main/gemma-2-27b-it.Q4_K_M.llamafile?download=true",
7884
},
7985
{
80-
"name": "LLaVA 1.5",
81-
"file_name": "llava-v1.5-7b-q4.llamafile",
82-
"size": 3.97,
83-
"url": "https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4.llamafile?download=true",
86+
"name": "TinyLlama-1.1B",
87+
"file_name": "TinyLlama-1.1B-Chat-v1.0.Q4_K_M.llamafile",
88+
"size": 0.70,
89+
"url": "https://huggingface.co/Mozilla/TinyLlama-1.1B-Chat-v1.0-llamafile/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q4_K_M.llamafile?download=true",
8490
},
8591
{
86-
"name": "Mistral-7B-Instruct",
87-
"file_name": "mistral-7b-instruct-v0.2.Q5_K_M.llamafile",
88-
"size": 5.15,
89-
"url": "https://huggingface.co/jartine/Mistral-7B-Instruct-v0.2-llamafile/resolve/main/mistral-7b-instruct-v0.2.Q5_K_M.llamafile?download=true",
92+
"name": "Rocket-3B",
93+
"file_name": "rocket-3b.Q4_K_M.llamafile",
94+
"size": 1.74,
95+
"url": "https://huggingface.co/Mozilla/rocket-3B-llamafile/resolve/main/rocket-3b.Q4_K_M.llamafile?download=true",
96+
},
97+
{
98+
"name": "LLaVA 1.5 (vision)",
99+
"file_name": "llava-v1.5-7b-q4.llamafile",
100+
"size": 4.29,
101+
"url": "https://huggingface.co/Mozilla/llava-v1.5-7b-llamafile/resolve/main/llava-v1.5-7b-q4.llamafile?download=true",
90102
},
91103
{
92104
"name": "WizardCoder-Python-13B",
@@ -96,9 +108,9 @@ def download_model(models_dir, models, interpreter):
96108
},
97109
{
98110
"name": "WizardCoder-Python-34B",
99-
"file_name": "wizardcoder-python-34b-v1.0.Q5_K_M.llamafile",
100-
"size": 22.23,
101-
"url": "https://huggingface.co/jartine/WizardCoder-Python-34B-V1.0-llamafile/resolve/main/wizardcoder-python-34b-v1.0.Q5_K_M.llamafile?download=true",
111+
"file_name": "wizardcoder-python-34b-v1.0.Q4_K_M.llamafile",
112+
"size": 20.22,
113+
"url": "https://huggingface.co/Mozilla/WizardCoder-Python-34B-V1.0-llamafile/resolve/main/wizardcoder-python-34b-v1.0.Q4_K_M.llamafile?download=true",
102114
},
103115
{
104116
"name": "Mixtral-8x7B-Instruct",
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
This is the template Open Interpreter profile.
3+
4+
A starting point for creating a new profile.
5+
6+
Learn about all the available settings - https://docs.openinterpreter.com/settings/all-settings
7+
8+
"""
9+
10+
# Import the interpreter
11+
from interpreter import interpreter
12+
13+
# You can import other libraries too
14+
from datetime import date
15+
16+
# You can set variables
17+
today = date.today()
18+
19+
# LLM Settings
20+
interpreter.llm.model = "groq/llama-3.1-70b-versatile"
21+
interpreter.llm.context_window = 110000
22+
interpreter.llm.max_tokens = 4096
23+
interpreter.llm.api_base = "https://api.example.com"
24+
interpreter.llm.api_key = "your_api_key_here"
25+
interpreter.llm.supports_functions = False
26+
interpreter.llm.supports_vision = False
27+
28+
29+
# Interpreter Settings
30+
interpreter.offline = False
31+
interpreter.loop = True
32+
interpreter.auto_run = False
33+
34+
# Toggle OS Mode - https://docs.openinterpreter.com/guides/os-mode
35+
interpreter.os = False
36+
37+
# Import Computer API - https://docs.openinterpreter.com/code-execution/computer-api
38+
interpreter.computer.import_computer_api = True
39+
40+
41+
# Set Custom Instructions to improve your Interpreter's performance at a given task
42+
interpreter.custom_instructions = f"""
43+
Today's date is {today}.
44+
"""

interpreter/terminal_interface/start_terminal_interface.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import argparse
2+
import os
23
import sys
34
import time
45

@@ -289,13 +290,24 @@ def start_terminal_interface(interpreter):
289290
},
290291
]
291292

293+
# i shortcut
292294
if len(sys.argv) > 1 and not sys.argv[1].startswith("-"):
293295
message = " ".join(sys.argv[1:])
294296
interpreter.messages.append(
295297
{"role": "user", "type": "message", "content": "I " + message}
296298
)
297299
sys.argv = sys.argv[:1]
298300

301+
interpreter.custom_instructions = "UPDATED INSTRUCTIONS: You are in ULTRA FAST, ULTRA CERTAIN mode. Do not ask the user any questions or run code to gathet information. Go as quickly as you can. Run code quickly. Do not plan out loud, simply start doing the best thing. The user expects speed. Trust that the user knows best. Just interpret their ambiguous command as quickly and certainly as possible and try to fulfill it IN ONE COMMAND, assuming they have the right information. If they tell you do to something, just do it quickly in one command, DO NOT try to get more information (for example by running `cat` to get a file's infomration— this is probably unecessary!). DIRECTLY DO THINGS AS FAST AS POSSIBLE."
302+
303+
files_in_directory = os.listdir()[:100]
304+
interpreter.custom_instructions += (
305+
"\nThe files in CWD, which THE USER MAY BE REFERRING TO, are: "
306+
+ ", ".join(files_in_directory)
307+
)
308+
309+
# interpreter.debug = True
310+
299311
# Check for deprecated flags before parsing arguments
300312
deprecated_flags = {
301313
"--debug_mode": "--verbose",

0 commit comments

Comments
 (0)