fix: Turn off all ensure_ascii of json.dumps (#800)

This commit is contained in:
ifsheldon
2024-01-12 15:54:35 +08:00
committed by GitHub
parent 465f7af847
commit dd2f4fc873
23 changed files with 113 additions and 69 deletions

View File

@@ -34,6 +34,7 @@ from memgpt.constants import (
CORE_MEMORY_PERSONA_CHAR_LIMIT,
LLM_MAX_TOKENS,
CLI_WARNING_PREFIX,
JSON_ENSURE_ASCII,
)
from .errors import LLMError
from .functions.functions import USER_FUNCTIONS_DIR, load_all_function_sets
@@ -66,11 +67,13 @@ def link_functions(function_schemas):
f"Function '{f_name}' was specified in agent.state.functions, but is not in function library:\n{available_functions.keys()}"
)
# Once we find a matching function, make sure the schema is identical
if json.dumps(f_schema) != json.dumps(linked_function["json_schema"]):
if json.dumps(f_schema, ensure_ascii=JSON_ENSURE_ASCII) != json.dumps(
linked_function["json_schema"], ensure_ascii=JSON_ENSURE_ASCII
):
# error_message = (
# f"Found matching function '{f_name}' from agent.state.functions inside function library, but schemas are different."
# + f"\n>>>agent.state.functions\n{json.dumps(f_schema, indent=2)}"
# + f"\n>>>function library\n{json.dumps(linked_function['json_schema'], indent=2)}"
# + f"\n>>>agent.state.functions\n{json.dumps(f_schema, indent=2, ensure_ascii=JSON_ENSURE_ASCII)}"
# + f"\n>>>function library\n{json.dumps(linked_function['json_schema'], indent=2, ensure_ascii=JSON_ENSURE_ASCII)}"
# )
schema_diff = get_schema_diff(f_schema, linked_function["json_schema"])
error_message = (
@@ -441,7 +444,7 @@ class Agent(object):
if "name" in user_message_json:
packed_user_message["name"] = user_message_json["name"]
user_message_json.pop("name", None)
packed_user_message["content"] = json.dumps(user_message_json)
packed_user_message["content"] = json.dumps(user_message_json, ensure_ascii=JSON_ENSURE_ASCII)
except Exception as e:
print(f"{CLI_WARNING_PREFIX}handling of 'name' field failed with: {e}")
input_message_sequence = self.messages + [packed_user_message]

View File

@@ -22,7 +22,7 @@ import memgpt.presets.presets as presets
import memgpt.utils as utils
from memgpt.utils import printd, open_folder_in_explorer, suppress_stdout
from memgpt.config import MemGPTConfig
from memgpt.constants import MEMGPT_DIR, CLI_WARNING_PREFIX
from memgpt.constants import MEMGPT_DIR, CLI_WARNING_PREFIX, JSON_ENSURE_ASCII
from memgpt.agent import Agent
from memgpt.embeddings import embedding_model
from memgpt.server.constants import WS_DEFAULT_PORT, REST_DEFAULT_PORT
@@ -546,8 +546,8 @@ def run(
typer.secho(f"🎉 Created new agent '{agent_state.name}'", fg=typer.colors.GREEN)
# pretty print agent config
# printd(json.dumps(vars(agent_config), indent=4, sort_keys=True))
# printd(json.dumps(agent_init_state), indent=4, sort_keys=True))
# printd(json.dumps(vars(agent_config), indent=4, sort_keys=True, ensure_ascii=JSON_ENSURE_ASCII))
# printd(json.dumps(agent_init_state), indent=4, sort_keys=True, ensure_ascii=JSON_ENSURE_ASCII))
# configure llama index
original_stdout = sys.stdout # unfortunate hack required to suppress confusing print statements from llama index

View File

@@ -102,3 +102,6 @@ FUNCTION_PARAM_TYPE_REQ_HEARTBEAT = "boolean"
FUNCTION_PARAM_DESCRIPTION_REQ_HEARTBEAT = "Request an immediate heartbeat after function execution. Set to 'true' if you want to send a follow-up message or run a follow-up function."
RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE = 5
# GLOBAL SETTINGS FOR `json.dumps()`
JSON_ENSURE_ASCII = False

View File

@@ -4,7 +4,7 @@ import os
import json
import math
from memgpt.constants import MAX_PAUSE_HEARTBEATS, RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE
from memgpt.constants import MAX_PAUSE_HEARTBEATS, RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE, JSON_ENSURE_ASCII
### Functions / tools the agent can use
# All functions should return a response string (or None)
@@ -109,7 +109,7 @@ def conversation_search(self, query: str, page: Optional[int] = 0) -> Optional[s
else:
results_pref = f"Showing {len(results)} of {total} results (page {page}/{num_pages}):"
results_formatted = [f"timestamp: {d['timestamp']}, {d['message']['role']} - {d['message']['content']}" for d in results]
results_str = f"{results_pref} {json.dumps(results_formatted)}"
results_str = f"{results_pref} {json.dumps(results_formatted, ensure_ascii=JSON_ENSURE_ASCII)}"
return results_str
@@ -139,7 +139,7 @@ def conversation_search_date(self, start_date: str, end_date: str, page: Optiona
else:
results_pref = f"Showing {len(results)} of {total} results (page {page}/{num_pages}):"
results_formatted = [f"timestamp: {d['timestamp']}, {d['message']['role']} - {d['message']['content']}" for d in results]
results_str = f"{results_pref} {json.dumps(results_formatted)}"
results_str = f"{results_pref} {json.dumps(results_formatted, ensure_ascii=JSON_ENSURE_ASCII)}"
return results_str
@@ -182,5 +182,5 @@ def archival_memory_search(self, query: str, page: Optional[int] = 0) -> Optiona
else:
results_pref = f"Showing {len(results)} of {total} results (page {page}/{num_pages}):"
results_formatted = [f"timestamp: {d['timestamp']}, memory: {d['content']}" for d in results]
results_str = f"{results_pref} {json.dumps(results_formatted)}"
results_str = f"{results_pref} {json.dumps(results_formatted, ensure_ascii=JSON_ENSURE_ASCII)}"
return results_str

View File

@@ -4,7 +4,12 @@ import json
import requests
from memgpt.constants import MESSAGE_CHATGPT_FUNCTION_MODEL, MESSAGE_CHATGPT_FUNCTION_SYSTEM_MESSAGE, MAX_PAUSE_HEARTBEATS
from memgpt.constants import (
MESSAGE_CHATGPT_FUNCTION_MODEL,
MESSAGE_CHATGPT_FUNCTION_SYSTEM_MESSAGE,
MAX_PAUSE_HEARTBEATS,
JSON_ENSURE_ASCII,
)
from memgpt.openai_tools import create
@@ -118,7 +123,7 @@ def http_request(self, method: str, url: str, payload_json: Optional[str] = None
payload = json.loads(payload_json)
else:
payload = {}
print(f"[HTTP] launching {method} request to {url}, payload=\n{json.dumps(payload, indent=2)}")
print(f"[HTTP] launching {method} request to {url}, payload=\n{json.dumps(payload, indent=2, ensure_ascii=JSON_ENSURE_ASCII)}")
response = requests.request(method, url, json=payload, headers=headers)
return {"status_code": response.status_code, "headers": dict(response.headers), "body": response.text}

View File

@@ -19,7 +19,7 @@ from memgpt.local_llm.utils import get_available_wrappers, count_tokens
from memgpt.local_llm.function_parser import patch_function
from memgpt.prompts.gpt_summarize import SYSTEM as SUMMARIZE_SYSTEM_MESSAGE
from memgpt.errors import LocalLLMConnectionError, LocalLLMError
from memgpt.constants import CLI_WARNING_PREFIX
from memgpt.constants import CLI_WARNING_PREFIX, JSON_ENSURE_ASCII
has_shown_warning = False
@@ -126,7 +126,7 @@ def get_chat_completion(
chat_completion_result = llm_wrapper.output_to_chat_completion_response(result, first_message=first_message)
else:
chat_completion_result = llm_wrapper.output_to_chat_completion_response(result)
printd(json.dumps(chat_completion_result, indent=2))
printd(json.dumps(chat_completion_result, indent=2, ensure_ascii=JSON_ENSURE_ASCII))
except Exception as e:
raise LocalLLMError(f"Failed to parse JSON from local LLM response - error: {str(e)}")
@@ -143,13 +143,13 @@ def get_chat_completion(
usage["prompt_tokens"] = count_tokens(prompt)
# NOTE: we should compute on-the-fly anyways since we might have to correct for errors during JSON parsing
usage["completion_tokens"] = count_tokens(json.dumps(chat_completion_result))
usage["completion_tokens"] = count_tokens(json.dumps(chat_completion_result, ensure_ascii=JSON_ENSURE_ASCII))
"""
if usage["completion_tokens"] is None:
printd(f"usage dict was missing completion_tokens, computing on-the-fly...")
# chat_completion_result is dict with 'role' and 'content'
# token counter wants a string
usage["completion_tokens"] = count_tokens(json.dumps(chat_completion_result))
usage["completion_tokens"] = count_tokens(json.dumps(chat_completion_result, ensure_ascii=JSON_ENSURE_ASCII))
"""
# NOTE: this is the token count that matters most

View File

@@ -1,6 +1,7 @@
import copy
import json
from memgpt.constants import JSON_ENSURE_ASCII
NO_HEARTBEAT_FUNCS = ["send_message", "pause_heartbeats"]
@@ -14,14 +15,14 @@ def insert_heartbeat(message):
params = message_copy.get("function_call").get("arguments")
params = json.loads(params)
params["request_heartbeat"] = True
message_copy["function_call"]["arguments"] = json.dumps(params)
message_copy["function_call"]["arguments"] = json.dumps(params, ensure_ascii=JSON_ENSURE_ASCII)
elif message_copy.get("tool_call"):
# function_name = message.get("tool_calls")[0].get("function").get("name")
params = message_copy.get("tool_calls")[0].get("function").get("arguments")
params = json.loads(params)
params["request_heartbeat"] = True
message_copy["tools_calls"][0]["function"]["arguments"] = json.dumps(params)
message_copy["tools_calls"][0]["function"]["arguments"] = json.dumps(params, ensure_ascii=JSON_ENSURE_ASCII)
return message_copy

View File

@@ -2,6 +2,7 @@ import json
from .wrapper_base import LLMChatCompletionWrapper
from ..json_parser import clean_json
from ...constants import JSON_ENSURE_ASCII
from ...errors import LLMJSONParsingError
@@ -112,7 +113,7 @@ class Airoboros21Wrapper(LLMChatCompletionWrapper):
"function": function_call["name"],
"params": json.loads(function_call["arguments"]),
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# Add a sep for the conversation
if self.include_section_separators:
@@ -202,7 +203,7 @@ class Airoboros21Wrapper(LLMChatCompletionWrapper):
"content": None,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message
@@ -321,7 +322,7 @@ class Airoboros21InnerMonologueWrapper(Airoboros21Wrapper):
**json.loads(function_call["arguments"]),
},
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# Add a sep for the conversation
if self.include_section_separators:
@@ -440,7 +441,7 @@ class Airoboros21InnerMonologueWrapper(Airoboros21Wrapper):
"content": inner_thoughts,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message

View File

@@ -2,6 +2,7 @@ import json
from .wrapper_base import LLMChatCompletionWrapper
from ..json_parser import clean_json
from ...constants import JSON_ENSURE_ASCII
from ...errors import LLMJSONParsingError
@@ -128,7 +129,7 @@ class ChatMLInnerMonologueWrapper(LLMChatCompletionWrapper):
**json.loads(function_call["arguments"]),
},
}
return json.dumps(airo_func_call, indent=self.json_indent)
return json.dumps(airo_func_call, indent=self.json_indent, ensure_ascii=JSON_ENSURE_ASCII)
# NOTE: BOS/EOS chatml tokens are NOT inserted here
def _compile_assistant_message(self, message) -> str:
@@ -160,7 +161,7 @@ class ChatMLInnerMonologueWrapper(LLMChatCompletionWrapper):
# Otherwise just dump the full json
try:
user_msg_json = json.loads(message["content"])
user_msg_str = json.dumps(user_msg_json, indent=self.json_indent)
user_msg_str = json.dumps(user_msg_json, indent=self.json_indent, ensure_ascii=JSON_ENSURE_ASCII)
except:
user_msg_str = message["content"]
@@ -175,7 +176,7 @@ class ChatMLInnerMonologueWrapper(LLMChatCompletionWrapper):
try:
# indent the function replies
function_return_dict = json.loads(message["content"])
function_return_str = json.dumps(function_return_dict, indent=self.json_indent)
function_return_str = json.dumps(function_return_dict, indent=self.json_indent, ensure_ascii=JSON_ENSURE_ASCII)
except:
function_return_str = message["content"]
@@ -312,7 +313,7 @@ class ChatMLInnerMonologueWrapper(LLMChatCompletionWrapper):
"content": inner_thoughts,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message
@@ -380,7 +381,7 @@ class ChatMLOuterInnerMonologueWrapper(ChatMLInnerMonologueWrapper):
**json.loads(function_call["arguments"]),
},
}
return json.dumps(airo_func_call, indent=self.json_indent)
return json.dumps(airo_func_call, indent=self.json_indent, ensure_ascii=JSON_ENSURE_ASCII)
def output_to_chat_completion_response(self, raw_llm_output, first_message=False):
"""NOTE: Modified to expect "inner_thoughts" outside the function
@@ -441,7 +442,7 @@ class ChatMLOuterInnerMonologueWrapper(ChatMLInnerMonologueWrapper):
"content": inner_thoughts,
# "function_call": {
# "name": function_name,
# "arguments": json.dumps(function_parameters),
# "arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
# },
}
@@ -449,7 +450,7 @@ class ChatMLOuterInnerMonologueWrapper(ChatMLInnerMonologueWrapper):
if function_name is not None:
message["function_call"] = {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
}
return message

View File

@@ -2,6 +2,7 @@ import json
from .wrapper_base import LLMChatCompletionWrapper
from ..json_parser import clean_json
from ...constants import JSON_ENSURE_ASCII
from ...errors import LLMJSONParsingError
@@ -125,7 +126,7 @@ class Dolphin21MistralWrapper(LLMChatCompletionWrapper):
"function": function_call["name"],
"params": json.loads(function_call["arguments"]),
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# option (1): from HF README:
# <|im_start|>user
@@ -237,7 +238,7 @@ class Dolphin21MistralWrapper(LLMChatCompletionWrapper):
"content": None,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message

View File

@@ -1,5 +1,6 @@
import json
from .wrapper_base import LLMChatCompletionWrapper
from ...constants import JSON_ENSURE_ASCII
class SimpleSummaryWrapper(LLMChatCompletionWrapper):
@@ -85,7 +86,7 @@ class SimpleSummaryWrapper(LLMChatCompletionWrapper):
"function": function_call["name"],
"params": json.loads(function_call["arguments"]),
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# Add a sep for the conversation
if self.include_section_separators:
@@ -147,7 +148,7 @@ class SimpleSummaryWrapper(LLMChatCompletionWrapper):
"content": raw_llm_output,
# "function_call": {
# "name": function_name,
# "arguments": json.dumps(function_parameters),
# "arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
# },
}
return message

View File

@@ -2,6 +2,7 @@ import json
from .wrapper_base import LLMChatCompletionWrapper
from ..json_parser import clean_json
from ...constants import JSON_ENSURE_ASCII
from ...errors import LLMJSONParsingError
@@ -75,7 +76,7 @@ class ZephyrMistralWrapper(LLMChatCompletionWrapper):
"function": function_call["name"],
"params": json.loads(function_call["arguments"]),
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
for message in messages[1:]:
assert message["role"] in ["user", "assistant", "function"], message
@@ -168,7 +169,7 @@ class ZephyrMistralWrapper(LLMChatCompletionWrapper):
"content": None,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message
@@ -237,7 +238,7 @@ class ZephyrMistralInnerMonologueWrapper(ZephyrMistralWrapper):
**json.loads(function_call["arguments"]),
},
}
return json.dumps(airo_func_call, indent=2)
return json.dumps(airo_func_call, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# Add a sep for the conversation
if self.include_section_separators:
@@ -335,7 +336,7 @@ class ZephyrMistralInnerMonologueWrapper(ZephyrMistralWrapper):
"content": inner_thoughts,
"function_call": {
"name": function_name,
"arguments": json.dumps(function_parameters),
"arguments": json.dumps(function_parameters, ensure_ascii=JSON_ENSURE_ASCII),
},
}
return message

View File

@@ -1,7 +1,7 @@
import json
import os
from memgpt.constants import MEMGPT_DIR
from memgpt.constants import MEMGPT_DIR, JSON_ENSURE_ASCII
from memgpt.local_llm.settings.simple import settings as simple_settings
from memgpt.local_llm.settings.deterministic_mirostat import settings as det_miro_settings
@@ -47,7 +47,9 @@ def get_completions_settings(defaults="simple") -> dict:
with open(settings_file, "r") as file:
user_settings = json.load(file)
if len(user_settings) > 0:
printd(f"Updating base settings with the following user settings:\n{json.dumps(user_settings,indent=2)}")
printd(
f"Updating base settings with the following user settings:\n{json.dumps(user_settings,indent=2, ensure_ascii=JSON_ENSURE_ASCII)}"
)
settings.update(user_settings)
else:
printd(f"'{settings_file}' was empty, ignoring...")

View File

@@ -203,7 +203,9 @@ def run_agent_loop(memgpt_agent, config: MemGPTConfig, first, no_verify=False, c
text = user_input[len("/rewrite ") :].strip()
args = json.loads(memgpt_agent.messages[x].get("function_call").get("arguments"))
args["message"] = text
memgpt_agent.messages[x].get("function_call").update({"arguments": json.dumps(args)})
memgpt_agent.messages[x].get("function_call").update(
{"arguments": json.dumps(args, ensure_ascii=constants.JSON_ENSURE_ASCII)}
)
break
continue

View File

@@ -8,6 +8,8 @@ from enum import Enum
import openai
from memgpt.constants import JSON_ENSURE_ASCII
# from openai import api_requestor, util
# from openai.openai_response import OpenAIResponse
# from openai.util import ApiType
@@ -339,7 +341,7 @@ class OpenAIObject(dict):
def __str__(self):
obj = self.to_dict_recursive()
return json.dumps(obj, sort_keys=True, indent=2)
return json.dumps(obj, sort_keys=True, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
def to_dict(self):
return dict(self)

View File

@@ -7,6 +7,7 @@ from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from memgpt.constants import JSON_ENSURE_ASCII
from memgpt.server.server import SyncServer
from memgpt.server.rest_api.interface import QueuingInterface
import memgpt.utils as utils
@@ -130,7 +131,7 @@ async def user_message(body: UserMessage):
async def formatted_message_generator():
async for message in interface.message_generator():
formatted_message = f"data: {json.dumps(message)}\n\n"
formatted_message = f"data: {json.dumps(message, ensure_ascii=JSON_ENSURE_ASCII)}\n\n"
yield formatted_message
await asyncio.sleep(1)

View File

@@ -371,7 +371,9 @@ class SyncServer(LockingServer):
text = command[len("rewrite ") :].strip()
args = json.loads(memgpt_agent.messages[x].get("function_call").get("arguments"))
args["message"] = text
memgpt_agent.messages[x].get("function_call").update({"arguments": json.dumps(args)})
memgpt_agent.messages[x].get("function_call").update(
{"arguments": json.dumps(args, ensure_ascii=constants.JSON_ENSURE_ASCII)}
)
break
# No skip options

View File

@@ -4,6 +4,7 @@ import json
import websockets
import memgpt.server.ws_api.protocol as protocol
from memgpt.constants import JSON_ENSURE_ASCII
from memgpt.server.constants import WS_DEFAULT_PORT, WS_CLIENT_TIMEOUT
from memgpt.server.utils import condition_to_stop_receiving, print_server_response
@@ -32,7 +33,7 @@ async def send_message_and_print_replies(websocket, user_message, agent_id):
if CLEAN_RESPONSES:
print_server_response(response)
else:
print(f"Server response:\n{json.dumps(response, indent=2)}")
print(f"Server response:\n{json.dumps(response, indent=2, ensure_ascii=JSON_ENSURE_ASCII)}")
# Check for a specific condition to break the loop
if condition_to_stop_receiving(response):
@@ -63,7 +64,7 @@ async def basic_cli_client():
# Wait for the response
response = await websocket.recv()
response = json.loads(response)
print(f"Server response:\n{json.dumps(response, indent=2)}")
print(f"Server response:\n{json.dumps(response, indent=2, ensure_ascii=JSON_ENSURE_ASCII)}")
await asyncio.sleep(1)

View File

@@ -1,5 +1,8 @@
import json
from memgpt.constants import JSON_ENSURE_ASCII
# Server -> client
@@ -9,7 +12,8 @@ def server_error(msg):
{
"type": "server_error",
"message": msg,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -18,7 +22,8 @@ def server_command_response(status):
{
"type": "command_response",
"status": status,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -27,7 +32,8 @@ def server_agent_response_error(msg):
{
"type": "agent_response_error",
"message": msg,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -35,7 +41,8 @@ def server_agent_response_start():
return json.dumps(
{
"type": "agent_response_start",
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -43,7 +50,8 @@ def server_agent_response_end():
return json.dumps(
{
"type": "agent_response_end",
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -53,7 +61,8 @@ def server_agent_internal_monologue(msg):
"type": "agent_response",
"message_type": "internal_monologue",
"message": msg,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -63,7 +72,8 @@ def server_agent_assistant_message(msg):
"type": "agent_response",
"message_type": "assistant_message",
"message": msg,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -73,7 +83,8 @@ def server_agent_function_message(msg):
"type": "agent_response",
"message_type": "function_message",
"message": msg,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -86,7 +97,8 @@ def client_user_message(msg, agent_id=None):
"type": "user_message",
"message": msg,
"agent_id": agent_id,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)
@@ -96,5 +108,6 @@ def client_command_create(config):
"type": "command",
"command": "create_agent",
"config": config,
}
},
ensure_ascii=JSON_ENSURE_ASCII,
)

View File

@@ -6,6 +6,7 @@ from .constants import (
INITIAL_BOOT_MESSAGE_SEND_MESSAGE_THOUGHT,
INITIAL_BOOT_MESSAGE_SEND_MESSAGE_FIRST_MSG,
MESSAGE_SUMMARY_WARNING_STR,
JSON_ENSURE_ASCII,
)
@@ -61,7 +62,7 @@ def get_heartbeat(reason="Automated timer", include_location=False, location_nam
if include_location:
packaged_message["location"] = location_name
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def get_login_event(last_login="Never (first login)", include_location=False, location_name="San Francisco, CA, USA"):
@@ -76,7 +77,7 @@ def get_login_event(last_login="Never (first login)", include_location=False, lo
if include_location:
packaged_message["location"] = location_name
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def package_user_message(user_message, time=None, include_location=False, location_name="San Francisco, CA, USA", name=None):
@@ -94,7 +95,7 @@ def package_user_message(user_message, time=None, include_location=False, locati
if name:
packaged_message["name"] = name
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def package_function_response(was_success, response_string, timestamp=None):
@@ -105,7 +106,7 @@ def package_function_response(was_success, response_string, timestamp=None):
"time": formatted_time,
}
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def package_summarize_message(summary, summary_length, hidden_message_count, total_message_count, timestamp=None):
@@ -121,7 +122,7 @@ def package_summarize_message(summary, summary_length, hidden_message_count, tot
"time": formatted_time,
}
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def package_summarize_message_no_summary(hidden_message_count, timestamp=None, message=None):
@@ -140,7 +141,7 @@ def package_summarize_message_no_summary(hidden_message_count, timestamp=None, m
"time": formatted_time,
}
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)
def get_token_limit_warning():
@@ -151,4 +152,4 @@ def get_token_limit_warning():
"time": formatted_time,
}
return json.dumps(packaged_message)
return json.dumps(packaged_message, ensure_ascii=JSON_ENSURE_ASCII)

View File

@@ -26,6 +26,7 @@ from memgpt.constants import (
CLI_WARNING_PREFIX,
CORE_MEMORY_HUMAN_CHAR_LIMIT,
CORE_MEMORY_PERSONA_CHAR_LIMIT,
JSON_ENSURE_ASCII,
)
from memgpt.openai_backcompat.openai_object import OpenAIObject
@@ -756,7 +757,7 @@ def validate_function_response(function_response_string: any, strict: bool = Fal
# Allow dict through since it will be cast to json.dumps()
try:
# TODO find a better way to do this that won't result in double escapes
function_response_string = json.dumps(function_response_string)
function_response_string = json.dumps(function_response_string, ensure_ascii=JSON_ENSURE_ASCII)
except:
raise ValueError(function_response_string)
@@ -864,8 +865,8 @@ def get_human_text(name: str):
def get_schema_diff(schema_a, schema_b):
# Assuming f_schema and linked_function['json_schema'] are your JSON schemas
f_schema_json = json.dumps(schema_a, indent=2)
linked_function_json = json.dumps(schema_b, indent=2)
f_schema_json = json.dumps(schema_a, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
linked_function_json = json.dumps(schema_b, indent=2, ensure_ascii=JSON_ENSURE_ASCII)
# Compute the difference using difflib
difference = list(difflib.ndiff(f_schema_json.splitlines(keepends=True), linked_function_json.splitlines(keepends=True)))

View File

@@ -1,5 +1,6 @@
import json
from memgpt.constants import JSON_ENSURE_ASCII
from memgpt.local_llm.function_parser import patch_function
import memgpt.system as system
@@ -32,7 +33,7 @@ EXAMPLE_FUNCTION_CALL_CORE_MEMORY_APPEND_MISSING = {
"content": "I'll append to memory.",
"function_call": {
"name": "core_memory_append",
"arguments": json.dumps({"content": "new_stuff"}),
"arguments": json.dumps({"content": "new_stuff"}, ensure_ascii=JSON_ENSURE_ASCII),
},
},
}

View File

@@ -4,6 +4,7 @@ import json
import websockets
import pytest
from memgpt.constants import JSON_ENSURE_ASCII
from memgpt.server.constants import WS_DEFAULT_PORT
from memgpt.server.ws_api.server import WebSocketServer
from memgpt.config import AgentConfig
@@ -36,7 +37,7 @@ async def test_websocket_server():
async with websockets.connect(uri) as websocket:
# Initialize the server with a test config
print("Sending config to server...")
await websocket.send(json.dumps({"type": "initialize", "config": test_config}))
await websocket.send(json.dumps({"type": "initialize", "config": test_config}, ensure_ascii=JSON_ENSURE_ASCII))
# Wait for the response
response = await websocket.recv()
print(f"Response from the agent: {response}")
@@ -45,7 +46,7 @@ async def test_websocket_server():
# Send a message to the agent
print("Sending message to server...")
await websocket.send(json.dumps({"type": "message", "content": "Hello, Agent!"}))
await websocket.send(json.dumps({"type": "message", "content": "Hello, Agent!"}, ensure_ascii=JSON_ENSURE_ASCII))
# Wait for the response
# NOTE: we should be waiting for multiple responses
response = await websocket.recv()