From 3a0692a2f1d9f53c168b6c2e1923132e858abe3c Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 20 Mar 2024 15:11:00 -0700 Subject: [PATCH 1/8] fix file upload route --- memgpt/server/rest_api/sources/index.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/memgpt/server/rest_api/sources/index.py b/memgpt/server/rest_api/sources/index.py index c5ce812648..e23a5b32c2 100644 --- a/memgpt/server/rest_api/sources/index.py +++ b/memgpt/server/rest_api/sources/index.py @@ -157,6 +157,10 @@ async def upload_file_to_source( # write the file to a temporary directory (deleted after the context manager exits) with tempfile.TemporaryDirectory() as tmpdirname: +<<<<<<< HEAD +======= + print("TEMPORARY DIRECTORY", tmpdirname) +>>>>>>> 25b1ac3 (fix file upload route) file_path = os.path.join(tmpdirname, file.filename) with open(file_path, "wb") as buffer: buffer.write(file.file.read()) From ba64d28614ed73d455fd8cb147f16053efb92f37 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Thu, 21 Mar 2024 10:52:59 -0700 Subject: [PATCH 2/8] actually merge --- memgpt/server/rest_api/sources/index.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/memgpt/server/rest_api/sources/index.py b/memgpt/server/rest_api/sources/index.py index e23a5b32c2..c5ce812648 100644 --- a/memgpt/server/rest_api/sources/index.py +++ b/memgpt/server/rest_api/sources/index.py @@ -157,10 +157,6 @@ async def upload_file_to_source( # write the file to a temporary directory (deleted after the context manager exits) with tempfile.TemporaryDirectory() as tmpdirname: -<<<<<<< HEAD -======= - print("TEMPORARY DIRECTORY", tmpdirname) ->>>>>>> 25b1ac3 (fix file upload route) file_path = os.path.join(tmpdirname, file.filename) with open(file_path, "wb") as buffer: buffer.write(file.file.read()) From 5ed3889a430e0a365913d4fa5cedb6fc65565c38 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Fri, 5 Apr 2024 15:21:17 -0700 Subject: [PATCH 3/8] upgrade llama-index-embeddings-huggingface package and fix bug with local embeddings --- memgpt/cli/cli_config.py | 89 +++++++++++++++------------------------- 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/memgpt/cli/cli_config.py b/memgpt/cli/cli_config.py index a061b93ebd..5647629c05 100644 --- a/memgpt/cli/cli_config.py +++ b/memgpt/cli/cli_config.py @@ -268,9 +268,7 @@ def configure_llm_endpoint(config: MemGPTConfig, credentials: MemGPTCredentials) provider = "cohere" else: # local models - # backend_options_old = ["webui", "webui-legacy", "llamacpp", "koboldcpp", "ollama", "lmstudio", "lmstudio-legacy", "vllm", "openai"] - backend_options = builtins.list(DEFAULT_ENDPOINTS.keys()) - # assert backend_options_old == backend_options, (backend_options_old, backend_options) + backend_options = ["webui", "webui-legacy", "llamacpp", "koboldcpp", "ollama", "lmstudio", "lmstudio-legacy", "vllm", "openai"] default_model_endpoint_type = None if config.default_llm_config and config.default_llm_config.model_endpoint_type in backend_options: # set from previous config @@ -388,12 +386,8 @@ def get_model_options( else: # Attempt to do OpenAI endpoint style model fetching - # TODO support local auth with api-key header - if credentials.openllm_auth_type == "bearer_token": - api_key = credentials.openllm_key - else: - api_key = None - fetched_model_options_response = openai_get_model_list(url=model_endpoint, api_key=api_key, fix_url=True) + # TODO support local auth + fetched_model_options_response = openai_get_model_list(url=model_endpoint, api_key=None) model_options = [obj["id"] for obj in fetched_model_options_response["data"]] # NOTE no filtering of local model options @@ -550,44 +544,6 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ raise KeyboardInterrupt else: # local models - - # ask about local auth - if model_endpoint_type in ["groq"]: # TODO all llm engines under 'local' that will require api keys - use_local_auth = True - local_auth_type = "bearer_token" - local_auth_key = questionary.password( - "Enter your Groq API key:", - ).ask() - if local_auth_key is None: - raise KeyboardInterrupt - credentials.openllm_auth_type = local_auth_type - credentials.openllm_key = local_auth_key - credentials.save() - else: - use_local_auth = questionary.confirm( - "Is your LLM endpoint authenticated? (default no)", - default=False, - ).ask() - if use_local_auth is None: - raise KeyboardInterrupt - if use_local_auth: - local_auth_type = questionary.select( - "What HTTP authentication method does your endpoint require?", - choices=SUPPORTED_AUTH_TYPES, - default=SUPPORTED_AUTH_TYPES[0], - ).ask() - if local_auth_type is None: - raise KeyboardInterrupt - local_auth_key = questionary.password( - "Enter your authentication key:", - ).ask() - if local_auth_key is None: - raise KeyboardInterrupt - # credentials = MemGPTCredentials.load() - credentials.openllm_auth_type = local_auth_type - credentials.openllm_key = local_auth_key - credentials.save() - # ollama also needs model type if model_endpoint_type == "ollama": default_model = ( @@ -608,7 +564,7 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ ) # vllm needs huggingface model tag - if model_endpoint_type in ["vllm", "groq"]: + if model_endpoint_type == "vllm": try: # Don't filter model list for vLLM since model list is likely much smaller than OpenAI/Azure endpoint # + probably has custom model names @@ -663,6 +619,31 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ if model_wrapper is None: raise KeyboardInterrupt + # ask about local auth + use_local_auth = questionary.confirm( + "Is your LLM endpoint authenticated? (default no)", + default=False, + ).ask() + if use_local_auth is None: + raise KeyboardInterrupt + if use_local_auth: + local_auth_type = questionary.select( + "What HTTP authentication method does your endpoint require?", + choices=SUPPORTED_AUTH_TYPES, + default=SUPPORTED_AUTH_TYPES[0], + ).ask() + if local_auth_type is None: + raise KeyboardInterrupt + local_auth_key = questionary.password( + "Enter your authentication key:", + ).ask() + if local_auth_key is None: + raise KeyboardInterrupt + # credentials = MemGPTCredentials.load() + credentials.openllm_auth_type = local_auth_type + credentials.openllm_key = local_auth_key + credentials.save() + # set: context_window if str(model) not in LLM_MAX_TOKENS: @@ -862,6 +843,7 @@ def configure_embedding_endpoint(config: MemGPTConfig, credentials: MemGPTCreden embedding_endpoint = None embedding_model = "BAAI/bge-small-en-v1.5" embedding_dim = 384 + embedding_model = "BAAI/bge-small-en-v1.5" return embedding_endpoint_type, embedding_endpoint, embedding_dim, embedding_model @@ -1078,7 +1060,7 @@ def list(arg: Annotated[ListChoice, typer.Argument]): """List all data sources""" # create table - table.field_names = ["Name", "Description", "Embedding Model", "Embedding Dim", "Created At", "Agents"] + table.field_names = ["Name", "Embedding Model", "Embedding Dim", "Created At", "Agents"] # TODO: eventually look accross all storage connections # TODO: add data source stats # TODO: connect to agents @@ -1091,14 +1073,7 @@ def list(arg: Annotated[ListChoice, typer.Argument]): agent_names = [agent_state.name for agent_state in agent_states if agent_state is not None] table.add_row( - [ - source.name, - source.description, - source.embedding_model, - source.embedding_dim, - utils.format_datetime(source.created_at), - ",".join(agent_names), - ] + [source.name, source.embedding_model, source.embedding_dim, utils.format_datetime(source.created_at), ",".join(agent_names)] ) print(table) From aac9610bceb4ae759ecf6bc29b36b0798d65acf1 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Sat, 6 Apr 2024 13:56:31 -0700 Subject: [PATCH 4/8] fix merge --- memgpt/cli/cli_config.py | 89 +++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/memgpt/cli/cli_config.py b/memgpt/cli/cli_config.py index 5647629c05..a061b93ebd 100644 --- a/memgpt/cli/cli_config.py +++ b/memgpt/cli/cli_config.py @@ -268,7 +268,9 @@ def configure_llm_endpoint(config: MemGPTConfig, credentials: MemGPTCredentials) provider = "cohere" else: # local models - backend_options = ["webui", "webui-legacy", "llamacpp", "koboldcpp", "ollama", "lmstudio", "lmstudio-legacy", "vllm", "openai"] + # backend_options_old = ["webui", "webui-legacy", "llamacpp", "koboldcpp", "ollama", "lmstudio", "lmstudio-legacy", "vllm", "openai"] + backend_options = builtins.list(DEFAULT_ENDPOINTS.keys()) + # assert backend_options_old == backend_options, (backend_options_old, backend_options) default_model_endpoint_type = None if config.default_llm_config and config.default_llm_config.model_endpoint_type in backend_options: # set from previous config @@ -386,8 +388,12 @@ def get_model_options( else: # Attempt to do OpenAI endpoint style model fetching - # TODO support local auth - fetched_model_options_response = openai_get_model_list(url=model_endpoint, api_key=None) + # TODO support local auth with api-key header + if credentials.openllm_auth_type == "bearer_token": + api_key = credentials.openllm_key + else: + api_key = None + fetched_model_options_response = openai_get_model_list(url=model_endpoint, api_key=api_key, fix_url=True) model_options = [obj["id"] for obj in fetched_model_options_response["data"]] # NOTE no filtering of local model options @@ -544,6 +550,44 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ raise KeyboardInterrupt else: # local models + + # ask about local auth + if model_endpoint_type in ["groq"]: # TODO all llm engines under 'local' that will require api keys + use_local_auth = True + local_auth_type = "bearer_token" + local_auth_key = questionary.password( + "Enter your Groq API key:", + ).ask() + if local_auth_key is None: + raise KeyboardInterrupt + credentials.openllm_auth_type = local_auth_type + credentials.openllm_key = local_auth_key + credentials.save() + else: + use_local_auth = questionary.confirm( + "Is your LLM endpoint authenticated? (default no)", + default=False, + ).ask() + if use_local_auth is None: + raise KeyboardInterrupt + if use_local_auth: + local_auth_type = questionary.select( + "What HTTP authentication method does your endpoint require?", + choices=SUPPORTED_AUTH_TYPES, + default=SUPPORTED_AUTH_TYPES[0], + ).ask() + if local_auth_type is None: + raise KeyboardInterrupt + local_auth_key = questionary.password( + "Enter your authentication key:", + ).ask() + if local_auth_key is None: + raise KeyboardInterrupt + # credentials = MemGPTCredentials.load() + credentials.openllm_auth_type = local_auth_type + credentials.openllm_key = local_auth_key + credentials.save() + # ollama also needs model type if model_endpoint_type == "ollama": default_model = ( @@ -564,7 +608,7 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ ) # vllm needs huggingface model tag - if model_endpoint_type == "vllm": + if model_endpoint_type in ["vllm", "groq"]: try: # Don't filter model list for vLLM since model list is likely much smaller than OpenAI/Azure endpoint # + probably has custom model names @@ -619,31 +663,6 @@ def configure_model(config: MemGPTConfig, credentials: MemGPTCredentials, model_ if model_wrapper is None: raise KeyboardInterrupt - # ask about local auth - use_local_auth = questionary.confirm( - "Is your LLM endpoint authenticated? (default no)", - default=False, - ).ask() - if use_local_auth is None: - raise KeyboardInterrupt - if use_local_auth: - local_auth_type = questionary.select( - "What HTTP authentication method does your endpoint require?", - choices=SUPPORTED_AUTH_TYPES, - default=SUPPORTED_AUTH_TYPES[0], - ).ask() - if local_auth_type is None: - raise KeyboardInterrupt - local_auth_key = questionary.password( - "Enter your authentication key:", - ).ask() - if local_auth_key is None: - raise KeyboardInterrupt - # credentials = MemGPTCredentials.load() - credentials.openllm_auth_type = local_auth_type - credentials.openllm_key = local_auth_key - credentials.save() - # set: context_window if str(model) not in LLM_MAX_TOKENS: @@ -843,7 +862,6 @@ def configure_embedding_endpoint(config: MemGPTConfig, credentials: MemGPTCreden embedding_endpoint = None embedding_model = "BAAI/bge-small-en-v1.5" embedding_dim = 384 - embedding_model = "BAAI/bge-small-en-v1.5" return embedding_endpoint_type, embedding_endpoint, embedding_dim, embedding_model @@ -1060,7 +1078,7 @@ def list(arg: Annotated[ListChoice, typer.Argument]): """List all data sources""" # create table - table.field_names = ["Name", "Embedding Model", "Embedding Dim", "Created At", "Agents"] + table.field_names = ["Name", "Description", "Embedding Model", "Embedding Dim", "Created At", "Agents"] # TODO: eventually look accross all storage connections # TODO: add data source stats # TODO: connect to agents @@ -1073,7 +1091,14 @@ def list(arg: Annotated[ListChoice, typer.Argument]): agent_names = [agent_state.name for agent_state in agent_states if agent_state is not None] table.add_row( - [source.name, source.embedding_model, source.embedding_dim, utils.format_datetime(source.created_at), ",".join(agent_names)] + [ + source.name, + source.description, + source.embedding_model, + source.embedding_dim, + utils.format_datetime(source.created_at), + ",".join(agent_names), + ] ) print(table) From e51ea2290d87c2b6201b29a8fd48459077a89c2e Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 17 Apr 2024 17:47:12 -0700 Subject: [PATCH 5/8] remove utc validation --- memgpt/server/rest_api/agents/message.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/memgpt/server/rest_api/agents/message.py b/memgpt/server/rest_api/agents/message.py index 3c1d0b67a2..3ea0d2f30d 100644 --- a/memgpt/server/rest_api/agents/message.py +++ b/memgpt/server/rest_api/agents/message.py @@ -34,13 +34,22 @@ class UserMessageRequest(BaseModel): description="Timestamp to tag the message with (in ISO format). If null, timestamp will be created server-side on receipt of message.", ) - @validator("timestamp") - def validate_timestamp(cls, value: Any) -> Any: - if value.tzinfo is None or value.tzinfo.utcoffset(value) is None: - raise ValueError("Timestamp must include timezone information.") - if value.tzinfo.utcoffset(value) != datetime.fromtimestamp(timezone.utc).utcoffset(): - raise ValueError("Timestamp must be in UTC.") - return value + # @validator("timestamp", pre=True, always=True) + # def validate_timestamp(cls, value: Optional[datetime]) -> Optional[datetime]: + # if value is None: + # return value # If the timestamp is None, just return None, implying default handling to set server-side + + # if not isinstance(value, datetime): + # raise TypeError("Timestamp must be a datetime object with timezone information.") + + # if value.tzinfo is None or value.tzinfo.utcoffset(value) is None: + # raise ValueError("Timestamp must be timezone-aware.") + + # # Convert timestamp to UTC if it's not already in UTC + # if value.tzinfo.utcoffset(value) != timezone.utc.utcoffset(value): + # value = value.astimezone(timezone.utc) + + # return value class UserMessageResponse(BaseModel): From 2be1dbd80c5082353f9cffb282451e174e652bf7 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 17 Apr 2024 17:56:05 -0700 Subject: [PATCH 6/8] add -d flag --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b5ee398fd7..67afc874ff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -47,7 +47,7 @@ jobs: MEMGPT_SERVER_PASS: test_server_token MEMGPT_CONFIG_PATH: configs/server_config.yaml - run: docker compose up & + run: docker compose up -d - name: Run server tests env: From f41381df20c26a31b6b41885f4b55f0dbc40474c Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 17 Apr 2024 18:09:45 -0700 Subject: [PATCH 7/8] remove unnecessary try catch --- memgpt/server/rest_api/agents/index.py | 35 +++++++++++--------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/memgpt/server/rest_api/agents/index.py b/memgpt/server/rest_api/agents/index.py index d71df7b70b..1a86b1a305 100644 --- a/memgpt/server/rest_api/agents/index.py +++ b/memgpt/server/rest_api/agents/index.py @@ -57,26 +57,21 @@ def create_agent( interface.clear() try: - try: - # print("YYY", request.config) - agent_state = server.create_agent( - user_id=user_id, - # **request.config - # TODO turn into a pydantic model - name=request.config["name"], - preset=request.config["preset"] if "preset" in request.config else None, - persona_name=request.config["persona_name"] if "persona_name" in request.config else None, - human_name=request.config["human_name"] if "human_name" in request.config else None, - persona=request.config["persona"] if "persona" in request.config else None, - human=request.config["human"] if "human" in request.config else None, - # llm_config=LLMConfigModel( - # model=request.config['model'], - # ) - function_names=request.config["function_names"].split(",") if "function_names" in request.config else None, - ) - except: - print(f"Failed to create agent from provided config:\n{request.config}") - raise + agent_state = server.create_agent( + user_id=user_id, + # **request.config + # TODO turn into a pydantic model + name=request.config["name"], + preset=request.config["preset"] if "preset" in request.config else None, + persona_name=request.config["persona_name"] if "persona_name" in request.config else None, + human_name=request.config["human_name"] if "human_name" in request.config else None, + persona=request.config["persona"] if "persona" in request.config else None, + human=request.config["human"] if "human" in request.config else None, + # llm_config=LLMConfigModel( + # model=request.config['model'], + # ) + function_names=request.config["function_names"].split(",") if "function_names" in request.config else None, + ) llm_config = LLMConfigModel(**vars(agent_state.llm_config)) embedding_config = EmbeddingConfigModel(**vars(agent_state.embedding_config)) From 9a1b637d94af9620ed95f69f1d7fda3a80fcd2b4 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 17 Apr 2024 18:58:10 -0700 Subject: [PATCH 8/8] remove docker tests --- tests/test_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_client.py b/tests/test_client.py index 945419ab4f..ff739033df 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -106,7 +106,7 @@ def run_server(): @pytest.fixture( params=[ {"base_url": local_service_url}, - {"base_url": docker_compose_url}, # TODO: add when docker compose added to tests + # {"base_url": docker_compose_url}, # TODO: add when docker compose added to tests # {"base_url": None} # TODO: add when implemented ], scope="module",