diff --git a/interpreter/core/async_core.py b/interpreter/core/async_core.py index df56f3725b..7c7fe0d0ed 100644 --- a/interpreter/core/async_core.py +++ b/interpreter/core/async_core.py @@ -533,6 +533,10 @@ async def set_settings(payload: Dict[str, Any]): for key, value in payload.items(): print(f"Updating settings: {key} = {value}") if key in ["llm", "computer"] and isinstance(value, dict): + if key == "auto_run": + return { + "error": f"The setting {key} is not modifiable through the server due to security constraints." + }, 403 if hasattr(async_interpreter, key): for sub_key, sub_value in value.items(): if hasattr(getattr(async_interpreter, key), sub_key): diff --git a/interpreter/core/llm/llm.py b/interpreter/core/llm/llm.py index 04971248b1..8a52ecdcc2 100644 --- a/interpreter/core/llm/llm.py +++ b/interpreter/core/llm/llm.py @@ -15,10 +15,10 @@ from ...terminal_interface.utils.display_markdown_message import ( display_markdown_message, ) -from .run_function_calling_llm import run_function_calling_llm - -# from .run_tool_calling_llm import run_tool_calling_llm from .run_text_llm import run_text_llm + +# from .run_function_calling_llm import run_function_calling_llm +from .run_tool_calling_llm import run_tool_calling_llm from .utils.convert_to_openai_messages import convert_to_openai_messages @@ -287,8 +287,8 @@ def run(self, messages): time.sleep(5) if self.supports_functions: - yield from run_function_calling_llm(self, params) - # yield from run_tool_calling_llm(self, params) + # yield from run_function_calling_llm(self, params) + yield from run_tool_calling_llm(self, params) else: yield from run_text_llm(self, params) diff --git a/interpreter/core/llm/run_function_calling_llm.py b/interpreter/core/llm/run_function_calling_llm.py index 17b59afdc8..46278feb85 100644 --- a/interpreter/core/llm/run_function_calling_llm.py +++ b/interpreter/core/llm/run_function_calling_llm.py @@ -42,6 +42,9 @@ def run_function_calling_llm(llm, request_params): code = "" function_call_detected = False + accumulated_review = "" + review_category = None + for chunk in llm.completions(**request_params): if "choices" not in chunk or len(chunk["choices"]) == 0: # This happens sometimes @@ -54,22 +57,35 @@ def run_function_calling_llm(llm, request_params): if "content" in delta and delta["content"]: if function_call_detected: # More content after a code block? This is a code review by a judge layer. - if delta["content"].strip() == "": - yield {"type": "review", "format": "safe", "content": ""} - elif "" in delta["content"]: - content = ( - delta["content"] - .replace("", "") - .replace("", "") - ) - yield {"type": "review", "format": "unsafe", "content": content} - else: - content = ( - delta["content"] - .replace("", "") - .replace("", "") - ) - yield {"type": "review", "format": "warning", "content": content} + + # print("Code safety review:", delta["content"]) + + if review_category == None: + accumulated_review += delta["content"] + + if "" in accumulated_review: + review_category = "unsafe" + if "" in accumulated_review: + review_category = "warning" + if "" in accumulated_review: + review_category = "safe" + + if review_category != None: + for tag in [ + "", + "", + "", + "", + "", + "", + ]: + delta["content"] = delta["content"].replace(tag, "") + + yield { + "type": "review", + "format": review_category, + "content": delta["content"], + } else: yield {"type": "message", "content": delta["content"]} diff --git a/interpreter/core/llm/run_tool_calling_llm.py b/interpreter/core/llm/run_tool_calling_llm.py index 541c424734..932c3c00ae 100644 --- a/interpreter/core/llm/run_tool_calling_llm.py +++ b/interpreter/core/llm/run_tool_calling_llm.py @@ -36,6 +36,28 @@ def run_tool_calling_llm(llm, request_params): ] request_params["tools"] = [tool_schema] + last_tool_id = 0 + for i, message in enumerate(request_params["messages"]): + if "function_call" in message: + last_tool_id += 1 + function = message.pop("function_call") + message["tool_calls"] = [ + { + "id": "toolu_" + str(last_tool_id), + "type": "function", + "function": function, + } + ] + if message["role"] == "function": + if i != 0 and request_params["messages"][i - 1]["role"] == "tool": + request_params["messages"][i]["content"] += message["content"] + message = None + else: + message["role"] = "tool" + message["tool_call_id"] = "toolu_" + str(last_tool_id) + + request_params["messages"] = [m for m in request_params["messages"] if m != None] + # Add OpenAI's recommended function message # request_params["messages"][0][ # "content" @@ -46,6 +68,9 @@ def run_tool_calling_llm(llm, request_params): accumulated_deltas = {} language = None code = "" + function_call_detected = False + accumulated_review = "" + review_category = None for chunk in llm.completions(**request_params): if "choices" not in chunk or len(chunk["choices"]) == 0: @@ -55,18 +80,57 @@ def run_tool_calling_llm(llm, request_params): delta = chunk["choices"][0]["delta"] # Convert tool call into function call, which we have great parsing logic for below - if "tool_calls" in delta: - if ( - len(delta["tool_calls"]) > 0 - and "function_call" in delta["tool_calls"][0] - ): - delta["function_call"] = delta["tool_calls"][0]["function_call"] + if "tool_calls" in delta and delta["tool_calls"]: + function_call_detected = True + + # import pdb; pdb.set_trace() + if len(delta["tool_calls"]) > 0 and delta["tool_calls"][0].function: + delta = { + # "id": delta["tool_calls"][0], + "function_call": { + "name": delta["tool_calls"][0].function.name, + "arguments": delta["tool_calls"][0].function.arguments, + } + } # Accumulate deltas accumulated_deltas = merge_deltas(accumulated_deltas, delta) if "content" in delta and delta["content"]: - yield {"type": "message", "content": delta["content"]} + if function_call_detected: + # More content after a code block? This is a code review by a judge layer. + + # print("Code safety review:", delta["content"]) + + if review_category == None: + accumulated_review += delta["content"] + + if "" in accumulated_review: + review_category = "unsafe" + if "" in accumulated_review: + review_category = "warning" + if "" in accumulated_review: + review_category = "safe" + + if review_category != None: + for tag in [ + "", + "", + "", + "", + "", + "", + ]: + delta["content"] = delta["content"].replace(tag, "") + + yield { + "type": "review", + "format": review_category, + "content": delta["content"], + } + + else: + yield {"type": "message", "content": delta["content"]} if ( accumulated_deltas.get("function_call") diff --git a/numbers.txt b/numbers.txt new file mode 100644 index 0000000000..01e79c32a8 --- /dev/null +++ b/numbers.txt @@ -0,0 +1,3 @@ +1 +2 +3