letta-nightly 0.1.7.dev20240924104148__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of letta-nightly might be problematic. Click here for more details.
- letta/__init__.py +24 -0
- letta/__main__.py +3 -0
- letta/agent.py +1427 -0
- letta/agent_store/chroma.py +295 -0
- letta/agent_store/db.py +546 -0
- letta/agent_store/lancedb.py +177 -0
- letta/agent_store/milvus.py +198 -0
- letta/agent_store/qdrant.py +201 -0
- letta/agent_store/storage.py +188 -0
- letta/benchmark/benchmark.py +96 -0
- letta/benchmark/constants.py +14 -0
- letta/cli/cli.py +689 -0
- letta/cli/cli_config.py +1282 -0
- letta/cli/cli_load.py +166 -0
- letta/client/__init__.py +0 -0
- letta/client/admin.py +171 -0
- letta/client/client.py +2360 -0
- letta/client/streaming.py +90 -0
- letta/client/utils.py +61 -0
- letta/config.py +484 -0
- letta/configs/anthropic.json +13 -0
- letta/configs/letta_hosted.json +11 -0
- letta/configs/openai.json +12 -0
- letta/constants.py +134 -0
- letta/credentials.py +140 -0
- letta/data_sources/connectors.py +247 -0
- letta/embeddings.py +218 -0
- letta/errors.py +26 -0
- letta/functions/__init__.py +0 -0
- letta/functions/function_sets/base.py +174 -0
- letta/functions/function_sets/extras.py +132 -0
- letta/functions/functions.py +105 -0
- letta/functions/schema_generator.py +205 -0
- letta/humans/__init__.py +0 -0
- letta/humans/examples/basic.txt +1 -0
- letta/humans/examples/cs_phd.txt +9 -0
- letta/interface.py +314 -0
- letta/llm_api/__init__.py +0 -0
- letta/llm_api/anthropic.py +383 -0
- letta/llm_api/azure_openai.py +155 -0
- letta/llm_api/cohere.py +396 -0
- letta/llm_api/google_ai.py +468 -0
- letta/llm_api/llm_api_tools.py +485 -0
- letta/llm_api/openai.py +470 -0
- letta/local_llm/README.md +3 -0
- letta/local_llm/__init__.py +0 -0
- letta/local_llm/chat_completion_proxy.py +279 -0
- letta/local_llm/constants.py +31 -0
- letta/local_llm/function_parser.py +68 -0
- letta/local_llm/grammars/__init__.py +0 -0
- letta/local_llm/grammars/gbnf_grammar_generator.py +1324 -0
- letta/local_llm/grammars/json.gbnf +26 -0
- letta/local_llm/grammars/json_func_calls_with_inner_thoughts.gbnf +32 -0
- letta/local_llm/groq/api.py +97 -0
- letta/local_llm/json_parser.py +202 -0
- letta/local_llm/koboldcpp/api.py +62 -0
- letta/local_llm/koboldcpp/settings.py +23 -0
- letta/local_llm/llamacpp/api.py +58 -0
- letta/local_llm/llamacpp/settings.py +22 -0
- letta/local_llm/llm_chat_completion_wrappers/__init__.py +0 -0
- letta/local_llm/llm_chat_completion_wrappers/airoboros.py +452 -0
- letta/local_llm/llm_chat_completion_wrappers/chatml.py +470 -0
- letta/local_llm/llm_chat_completion_wrappers/configurable_wrapper.py +387 -0
- letta/local_llm/llm_chat_completion_wrappers/dolphin.py +246 -0
- letta/local_llm/llm_chat_completion_wrappers/llama3.py +345 -0
- letta/local_llm/llm_chat_completion_wrappers/simple_summary_wrapper.py +156 -0
- letta/local_llm/llm_chat_completion_wrappers/wrapper_base.py +11 -0
- letta/local_llm/llm_chat_completion_wrappers/zephyr.py +345 -0
- letta/local_llm/lmstudio/api.py +100 -0
- letta/local_llm/lmstudio/settings.py +29 -0
- letta/local_llm/ollama/api.py +88 -0
- letta/local_llm/ollama/settings.py +32 -0
- letta/local_llm/settings/__init__.py +0 -0
- letta/local_llm/settings/deterministic_mirostat.py +45 -0
- letta/local_llm/settings/settings.py +72 -0
- letta/local_llm/settings/simple.py +28 -0
- letta/local_llm/utils.py +265 -0
- letta/local_llm/vllm/api.py +63 -0
- letta/local_llm/webui/api.py +60 -0
- letta/local_llm/webui/legacy_api.py +58 -0
- letta/local_llm/webui/legacy_settings.py +23 -0
- letta/local_llm/webui/settings.py +24 -0
- letta/log.py +76 -0
- letta/main.py +437 -0
- letta/memory.py +440 -0
- letta/metadata.py +884 -0
- letta/openai_backcompat/__init__.py +0 -0
- letta/openai_backcompat/openai_object.py +437 -0
- letta/persistence_manager.py +148 -0
- letta/personas/__init__.py +0 -0
- letta/personas/examples/anna_pa.txt +13 -0
- letta/personas/examples/google_search_persona.txt +15 -0
- letta/personas/examples/memgpt_doc.txt +6 -0
- letta/personas/examples/memgpt_starter.txt +4 -0
- letta/personas/examples/sam.txt +14 -0
- letta/personas/examples/sam_pov.txt +14 -0
- letta/personas/examples/sam_simple_pov_gpt35.txt +13 -0
- letta/personas/examples/sqldb/test.db +0 -0
- letta/prompts/__init__.py +0 -0
- letta/prompts/gpt_summarize.py +14 -0
- letta/prompts/gpt_system.py +26 -0
- letta/prompts/system/memgpt_base.txt +49 -0
- letta/prompts/system/memgpt_chat.txt +58 -0
- letta/prompts/system/memgpt_chat_compressed.txt +13 -0
- letta/prompts/system/memgpt_chat_fstring.txt +51 -0
- letta/prompts/system/memgpt_doc.txt +50 -0
- letta/prompts/system/memgpt_gpt35_extralong.txt +53 -0
- letta/prompts/system/memgpt_intuitive_knowledge.txt +31 -0
- letta/prompts/system/memgpt_modified_chat.txt +23 -0
- letta/pytest.ini +0 -0
- letta/schemas/agent.py +117 -0
- letta/schemas/api_key.py +21 -0
- letta/schemas/block.py +135 -0
- letta/schemas/document.py +21 -0
- letta/schemas/embedding_config.py +54 -0
- letta/schemas/enums.py +35 -0
- letta/schemas/job.py +38 -0
- letta/schemas/letta_base.py +80 -0
- letta/schemas/letta_message.py +175 -0
- letta/schemas/letta_request.py +23 -0
- letta/schemas/letta_response.py +28 -0
- letta/schemas/llm_config.py +54 -0
- letta/schemas/memory.py +224 -0
- letta/schemas/message.py +727 -0
- letta/schemas/openai/chat_completion_request.py +123 -0
- letta/schemas/openai/chat_completion_response.py +136 -0
- letta/schemas/openai/chat_completions.py +123 -0
- letta/schemas/openai/embedding_response.py +11 -0
- letta/schemas/openai/openai.py +157 -0
- letta/schemas/organization.py +20 -0
- letta/schemas/passage.py +80 -0
- letta/schemas/source.py +62 -0
- letta/schemas/tool.py +143 -0
- letta/schemas/usage.py +18 -0
- letta/schemas/user.py +33 -0
- letta/server/__init__.py +0 -0
- letta/server/constants.py +6 -0
- letta/server/rest_api/__init__.py +0 -0
- letta/server/rest_api/admin/__init__.py +0 -0
- letta/server/rest_api/admin/agents.py +21 -0
- letta/server/rest_api/admin/tools.py +83 -0
- letta/server/rest_api/admin/users.py +98 -0
- letta/server/rest_api/app.py +193 -0
- letta/server/rest_api/auth/__init__.py +0 -0
- letta/server/rest_api/auth/index.py +43 -0
- letta/server/rest_api/auth_token.py +22 -0
- letta/server/rest_api/interface.py +726 -0
- letta/server/rest_api/routers/__init__.py +0 -0
- letta/server/rest_api/routers/openai/__init__.py +0 -0
- letta/server/rest_api/routers/openai/assistants/__init__.py +0 -0
- letta/server/rest_api/routers/openai/assistants/assistants.py +115 -0
- letta/server/rest_api/routers/openai/assistants/schemas.py +121 -0
- letta/server/rest_api/routers/openai/assistants/threads.py +336 -0
- letta/server/rest_api/routers/openai/chat_completions/__init__.py +0 -0
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +131 -0
- letta/server/rest_api/routers/v1/__init__.py +15 -0
- letta/server/rest_api/routers/v1/agents.py +543 -0
- letta/server/rest_api/routers/v1/blocks.py +73 -0
- letta/server/rest_api/routers/v1/jobs.py +46 -0
- letta/server/rest_api/routers/v1/llms.py +28 -0
- letta/server/rest_api/routers/v1/organizations.py +61 -0
- letta/server/rest_api/routers/v1/sources.py +199 -0
- letta/server/rest_api/routers/v1/tools.py +103 -0
- letta/server/rest_api/routers/v1/users.py +109 -0
- letta/server/rest_api/static_files.py +74 -0
- letta/server/rest_api/utils.py +69 -0
- letta/server/server.py +1995 -0
- letta/server/startup.sh +8 -0
- letta/server/static_files/assets/index-0cbf7ad5.js +274 -0
- letta/server/static_files/assets/index-156816da.css +1 -0
- letta/server/static_files/assets/index-486e3228.js +274 -0
- letta/server/static_files/favicon.ico +0 -0
- letta/server/static_files/index.html +39 -0
- letta/server/static_files/memgpt_logo_transparent.png +0 -0
- letta/server/utils.py +46 -0
- letta/server/ws_api/__init__.py +0 -0
- letta/server/ws_api/example_client.py +104 -0
- letta/server/ws_api/interface.py +108 -0
- letta/server/ws_api/protocol.py +100 -0
- letta/server/ws_api/server.py +145 -0
- letta/settings.py +165 -0
- letta/streaming_interface.py +396 -0
- letta/system.py +207 -0
- letta/utils.py +1065 -0
- letta_nightly-0.1.7.dev20240924104148.dist-info/LICENSE +190 -0
- letta_nightly-0.1.7.dev20240924104148.dist-info/METADATA +98 -0
- letta_nightly-0.1.7.dev20240924104148.dist-info/RECORD +189 -0
- letta_nightly-0.1.7.dev20240924104148.dist-info/WHEEL +4 -0
- letta_nightly-0.1.7.dev20240924104148.dist-info/entry_points.txt +3 -0
letta/cli/cli_load.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file contains functions for loading data into Letta's archival storage.
|
|
3
|
+
|
|
4
|
+
Data can be loaded with the following command, once a load function is defined:
|
|
5
|
+
```
|
|
6
|
+
letta load <data-connector-type> --name <dataset-name> [ADDITIONAL ARGS]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import uuid
|
|
12
|
+
from typing import Annotated, List, Optional
|
|
13
|
+
|
|
14
|
+
import typer
|
|
15
|
+
|
|
16
|
+
from letta import create_client
|
|
17
|
+
from letta.data_sources.connectors import DirectoryConnector
|
|
18
|
+
|
|
19
|
+
app = typer.Typer()
|
|
20
|
+
|
|
21
|
+
# NOTE: not supported due to llama-index breaking things (please reach out if you still need it)
|
|
22
|
+
# @app.command("index")
|
|
23
|
+
# def load_index(
|
|
24
|
+
# name: Annotated[str, typer.Option(help="Name of dataset to load.")],
|
|
25
|
+
# dir: Annotated[Optional[str], typer.Option(help="Path to directory containing index.")] = None,
|
|
26
|
+
# user_id: Annotated[Optional[uuid.UUID], typer.Option(help="User ID to associate with dataset.")] = None,
|
|
27
|
+
# ):
|
|
28
|
+
# """Load a LlamaIndex saved VectorIndex into Letta"""
|
|
29
|
+
# if user_id is None:
|
|
30
|
+
# config = LettaConfig.load()
|
|
31
|
+
# user_id = uuid.UUID(config.anon_clientid)
|
|
32
|
+
#
|
|
33
|
+
# try:
|
|
34
|
+
# # load index data
|
|
35
|
+
# storage_context = StorageContext.from_defaults(persist_dir=dir)
|
|
36
|
+
# loaded_index = load_index_from_storage(storage_context)
|
|
37
|
+
#
|
|
38
|
+
# # hacky code to extract out passages/embeddings (thanks a lot, llama index)
|
|
39
|
+
# embed_dict = loaded_index._vector_store._data.embedding_dict
|
|
40
|
+
# node_dict = loaded_index._docstore.docs
|
|
41
|
+
#
|
|
42
|
+
# # create storage connector
|
|
43
|
+
# config = LettaConfig.load()
|
|
44
|
+
# if user_id is None:
|
|
45
|
+
# user_id = uuid.UUID(config.anon_clientid)
|
|
46
|
+
#
|
|
47
|
+
# passages = []
|
|
48
|
+
# for node_id, node in node_dict.items():
|
|
49
|
+
# vector = embed_dict[node_id]
|
|
50
|
+
# node.embedding = vector
|
|
51
|
+
# # assume embedding are the same as config
|
|
52
|
+
# passages.append(
|
|
53
|
+
# Passage(
|
|
54
|
+
# text=node.text,
|
|
55
|
+
# embedding=np.array(vector),
|
|
56
|
+
# embedding_dim=config.default_embedding_config.embedding_dim,
|
|
57
|
+
# embedding_model=config.default_embedding_config.embedding_model,
|
|
58
|
+
# )
|
|
59
|
+
# )
|
|
60
|
+
# assert config.default_embedding_config.embedding_dim == len(
|
|
61
|
+
# vector
|
|
62
|
+
# ), f"Expected embedding dimension {config.default_embedding_config.embedding_dim}, got {len(vector)}"
|
|
63
|
+
#
|
|
64
|
+
# if len(passages) == 0:
|
|
65
|
+
# raise ValueError(f"No passages found in index {dir}")
|
|
66
|
+
#
|
|
67
|
+
# insert_passages_into_source(passages, name, user_id, config)
|
|
68
|
+
# except ValueError as e:
|
|
69
|
+
# typer.secho(f"Failed to load index from provided information.\n{e}", fg=typer.colors.RED)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
default_extensions = ".txt,.md,.pdf"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@app.command("directory")
|
|
76
|
+
def load_directory(
|
|
77
|
+
name: Annotated[str, typer.Option(help="Name of dataset to load.")],
|
|
78
|
+
input_dir: Annotated[Optional[str], typer.Option(help="Path to directory containing dataset.")] = None,
|
|
79
|
+
input_files: Annotated[List[str], typer.Option(help="List of paths to files containing dataset.")] = [],
|
|
80
|
+
recursive: Annotated[bool, typer.Option(help="Recursively search for files in directory.")] = False,
|
|
81
|
+
extensions: Annotated[str, typer.Option(help="Comma separated list of file extensions to load")] = default_extensions,
|
|
82
|
+
user_id: Annotated[Optional[uuid.UUID], typer.Option(help="User ID to associate with dataset.")] = None, # TODO: remove
|
|
83
|
+
description: Annotated[Optional[str], typer.Option(help="Description of the source.")] = None,
|
|
84
|
+
):
|
|
85
|
+
client = create_client()
|
|
86
|
+
|
|
87
|
+
# create connector
|
|
88
|
+
connector = DirectoryConnector(input_files=input_files, input_directory=input_dir, recursive=recursive, extensions=extensions)
|
|
89
|
+
|
|
90
|
+
# create source
|
|
91
|
+
source = client.create_source(name=name)
|
|
92
|
+
|
|
93
|
+
# load data
|
|
94
|
+
try:
|
|
95
|
+
client.load_data(connector, source_name=name)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
typer.secho(f"Failed to load data from provided information.\n{e}", fg=typer.colors.RED)
|
|
98
|
+
client.delete_source(source.id)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# @app.command("webpage")
|
|
102
|
+
# def load_webpage(
|
|
103
|
+
# name: Annotated[str, typer.Option(help="Name of dataset to load.")],
|
|
104
|
+
# urls: Annotated[List[str], typer.Option(help="List of urls to load.")],
|
|
105
|
+
# ):
|
|
106
|
+
# try:
|
|
107
|
+
# from llama_index.readers.web import SimpleWebPageReader
|
|
108
|
+
#
|
|
109
|
+
# docs = SimpleWebPageReader(html_to_text=True).load_data(urls)
|
|
110
|
+
# store_docs(name, docs)
|
|
111
|
+
#
|
|
112
|
+
# except ValueError as e:
|
|
113
|
+
# typer.secho(f"Failed to load webpage from provided information.\n{e}", fg=typer.colors.RED)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@app.command("vector-database")
|
|
117
|
+
def load_vector_database(
|
|
118
|
+
name: Annotated[str, typer.Option(help="Name of dataset to load.")],
|
|
119
|
+
uri: Annotated[str, typer.Option(help="Database URI.")],
|
|
120
|
+
table_name: Annotated[str, typer.Option(help="Name of table containing data.")],
|
|
121
|
+
text_column: Annotated[str, typer.Option(help="Name of column containing text.")],
|
|
122
|
+
embedding_column: Annotated[str, typer.Option(help="Name of column containing embedding.")],
|
|
123
|
+
user_id: Annotated[Optional[uuid.UUID], typer.Option(help="User ID to associate with dataset.")] = None,
|
|
124
|
+
):
|
|
125
|
+
"""Load pre-computed embeddings into Letta from a database."""
|
|
126
|
+
raise NotImplementedError
|
|
127
|
+
# try:
|
|
128
|
+
# config = LettaConfig.load()
|
|
129
|
+
# connector = VectorDBConnector(
|
|
130
|
+
# uri=uri,
|
|
131
|
+
# table_name=table_name,
|
|
132
|
+
# text_column=text_column,
|
|
133
|
+
# embedding_column=embedding_column,
|
|
134
|
+
# embedding_dim=config.default_embedding_config.embedding_dim,
|
|
135
|
+
# )
|
|
136
|
+
# if not user_id:
|
|
137
|
+
# user_id = uuid.UUID(config.anon_clientid)
|
|
138
|
+
|
|
139
|
+
# ms = MetadataStore(config)
|
|
140
|
+
# source = Source(
|
|
141
|
+
# name=name,
|
|
142
|
+
# user_id=user_id,
|
|
143
|
+
# embedding_model=config.default_embedding_config.embedding_model,
|
|
144
|
+
# embedding_dim=config.default_embedding_config.embedding_dim,
|
|
145
|
+
# )
|
|
146
|
+
# ms.create_source(source)
|
|
147
|
+
# passage_storage = StorageConnector.get_storage_connector(TableType.PASSAGES, config, user_id)
|
|
148
|
+
# # TODO: also get document store
|
|
149
|
+
|
|
150
|
+
# # ingest data into passage/document store
|
|
151
|
+
# try:
|
|
152
|
+
# num_passages, num_documents = load_data(
|
|
153
|
+
# connector=connector,
|
|
154
|
+
# source=source,
|
|
155
|
+
# embedding_config=config.default_embedding_config,
|
|
156
|
+
# document_store=None,
|
|
157
|
+
# passage_store=passage_storage,
|
|
158
|
+
# )
|
|
159
|
+
# print(f"Loaded {num_passages} passages and {num_documents} documents from {name}")
|
|
160
|
+
# except Exception as e:
|
|
161
|
+
# typer.secho(f"Failed to load data from provided information.\n{e}", fg=typer.colors.RED)
|
|
162
|
+
# ms.delete_source(source_id=source.id)
|
|
163
|
+
|
|
164
|
+
# except ValueError as e:
|
|
165
|
+
# typer.secho(f"Failed to load VectorDB from provided information.\n{e}", fg=typer.colors.RED)
|
|
166
|
+
# raise
|
letta/client/__init__.py
ADDED
|
File without changes
|
letta/client/admin.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from requests import HTTPError
|
|
5
|
+
|
|
6
|
+
from letta.functions.functions import parse_source_code
|
|
7
|
+
from letta.functions.schema_generator import generate_schema
|
|
8
|
+
from letta.schemas.api_key import APIKey, APIKeyCreate
|
|
9
|
+
from letta.schemas.organization import Organization, OrganizationCreate
|
|
10
|
+
from letta.schemas.user import User, UserCreate
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Admin:
|
|
14
|
+
"""
|
|
15
|
+
Admin client allows admin-level operations on the Letta server.
|
|
16
|
+
- Creating users
|
|
17
|
+
- Generating user keys
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
base_url: str,
|
|
23
|
+
token: str,
|
|
24
|
+
api_prefix: str = "v1",
|
|
25
|
+
):
|
|
26
|
+
self.base_url = base_url
|
|
27
|
+
self.api_prefix = api_prefix
|
|
28
|
+
self.token = token
|
|
29
|
+
self.headers = {"accept": "application/json", "content-type": "application/json", "authorization": f"Bearer {token}"}
|
|
30
|
+
|
|
31
|
+
def get_users(self, cursor: Optional[str] = None, limit: Optional[int] = 50) -> List[User]:
|
|
32
|
+
params = {}
|
|
33
|
+
if cursor:
|
|
34
|
+
params["cursor"] = str(cursor)
|
|
35
|
+
if limit:
|
|
36
|
+
params["limit"] = limit
|
|
37
|
+
response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/users", params=params, headers=self.headers)
|
|
38
|
+
if response.status_code != 200:
|
|
39
|
+
raise HTTPError(response.json())
|
|
40
|
+
return [User(**user) for user in response.json()]
|
|
41
|
+
|
|
42
|
+
def create_key(self, user_id: str, key_name: Optional[str] = None) -> APIKey:
|
|
43
|
+
request = APIKeyCreate(user_id=user_id, name=key_name)
|
|
44
|
+
response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/users/keys", headers=self.headers, json=request.model_dump())
|
|
45
|
+
if response.status_code != 200:
|
|
46
|
+
raise HTTPError(response.json())
|
|
47
|
+
return APIKey(**response.json())
|
|
48
|
+
|
|
49
|
+
def get_keys(self, user_id: str) -> List[APIKey]:
|
|
50
|
+
params = {"user_id": str(user_id)}
|
|
51
|
+
response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/users/keys", params=params, headers=self.headers)
|
|
52
|
+
if response.status_code != 200:
|
|
53
|
+
raise HTTPError(response.json())
|
|
54
|
+
return [APIKey(**key) for key in response.json()]
|
|
55
|
+
|
|
56
|
+
def delete_key(self, api_key: str) -> APIKey:
|
|
57
|
+
params = {"api_key": api_key}
|
|
58
|
+
response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/users/keys", params=params, headers=self.headers)
|
|
59
|
+
if response.status_code != 200:
|
|
60
|
+
raise HTTPError(response.json())
|
|
61
|
+
return APIKey(**response.json())
|
|
62
|
+
|
|
63
|
+
def create_user(self, name: Optional[str] = None, org_id: Optional[str] = None) -> User:
|
|
64
|
+
request = UserCreate(name=name, org_id=org_id)
|
|
65
|
+
response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/users", headers=self.headers, json=request.model_dump())
|
|
66
|
+
if response.status_code != 200:
|
|
67
|
+
raise HTTPError(response.json())
|
|
68
|
+
response_json = response.json()
|
|
69
|
+
return User(**response_json)
|
|
70
|
+
|
|
71
|
+
def delete_user(self, user_id: str) -> User:
|
|
72
|
+
params = {"user_id": str(user_id)}
|
|
73
|
+
response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/users", params=params, headers=self.headers)
|
|
74
|
+
if response.status_code != 200:
|
|
75
|
+
raise HTTPError(response.json())
|
|
76
|
+
return User(**response.json())
|
|
77
|
+
|
|
78
|
+
def create_organization(self, name: Optional[str] = None) -> Organization:
|
|
79
|
+
request = OrganizationCreate(name=name)
|
|
80
|
+
response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/orgs", headers=self.headers, json=request.model_dump())
|
|
81
|
+
if response.status_code != 200:
|
|
82
|
+
raise HTTPError(response.json())
|
|
83
|
+
response_json = response.json()
|
|
84
|
+
return Organization(**response_json)
|
|
85
|
+
|
|
86
|
+
def delete_organization(self, org_id: str) -> Organization:
|
|
87
|
+
params = {"org_id": str(org_id)}
|
|
88
|
+
response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/orgs", params=params, headers=self.headers)
|
|
89
|
+
if response.status_code != 200:
|
|
90
|
+
raise HTTPError(response.json())
|
|
91
|
+
return Organization(**response.json())
|
|
92
|
+
|
|
93
|
+
def get_organizations(self, cursor: Optional[str] = None, limit: Optional[int] = 50) -> List[Organization]:
|
|
94
|
+
params = {}
|
|
95
|
+
if cursor:
|
|
96
|
+
params["cursor"] = str(cursor)
|
|
97
|
+
if limit:
|
|
98
|
+
params["limit"] = limit
|
|
99
|
+
response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/orgs", params=params, headers=self.headers)
|
|
100
|
+
if response.status_code != 200:
|
|
101
|
+
raise HTTPError(response.json())
|
|
102
|
+
return [Organization(**org) for org in response.json()]
|
|
103
|
+
|
|
104
|
+
def _reset_server(self):
|
|
105
|
+
# DANGER: this will delete all users and keys
|
|
106
|
+
# clear all state associated with users
|
|
107
|
+
# TODO: clear out all agents, presets, etc.
|
|
108
|
+
users = self.get_users()
|
|
109
|
+
for user in users:
|
|
110
|
+
keys = self.get_keys(user.id)
|
|
111
|
+
for key in keys:
|
|
112
|
+
self.delete_key(key.key)
|
|
113
|
+
self.delete_user(user.id)
|
|
114
|
+
|
|
115
|
+
# tools
|
|
116
|
+
def create_tool(
|
|
117
|
+
self,
|
|
118
|
+
func,
|
|
119
|
+
name: Optional[str] = None,
|
|
120
|
+
update: Optional[bool] = True, # TODO: actually use this
|
|
121
|
+
tags: Optional[List[str]] = None,
|
|
122
|
+
):
|
|
123
|
+
"""Create a tool
|
|
124
|
+
Args:
|
|
125
|
+
func (callable): The function to create a tool for.
|
|
126
|
+
tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
|
|
127
|
+
update (bool, optional): Update the tool if it already exists. Defaults to True.
|
|
128
|
+
Returns:
|
|
129
|
+
Tool object
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
# TODO: check if tool already exists
|
|
133
|
+
# TODO: how to load modules?
|
|
134
|
+
# parse source code/schema
|
|
135
|
+
source_code = parse_source_code(func)
|
|
136
|
+
json_schema = generate_schema(func, name)
|
|
137
|
+
source_type = "python"
|
|
138
|
+
json_schema["name"]
|
|
139
|
+
|
|
140
|
+
if "memory" in tags:
|
|
141
|
+
# special modifications to memory functions
|
|
142
|
+
# self.memory -> self.memory.memory, since Agent.memory.memory needs to be modified (not BaseMemory.memory)
|
|
143
|
+
source_code = source_code.replace("self.memory", "self.memory.memory")
|
|
144
|
+
|
|
145
|
+
# create data
|
|
146
|
+
data = {"source_code": source_code, "source_type": source_type, "tags": tags, "json_schema": json_schema}
|
|
147
|
+
CreateToolRequest(**data) # validate
|
|
148
|
+
|
|
149
|
+
# make REST request
|
|
150
|
+
response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/tools", json=data, headers=self.headers)
|
|
151
|
+
if response.status_code != 200:
|
|
152
|
+
raise ValueError(f"Failed to create tool: {response.text}")
|
|
153
|
+
return ToolModel(**response.json())
|
|
154
|
+
|
|
155
|
+
def list_tools(self):
|
|
156
|
+
response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/tools", headers=self.headers)
|
|
157
|
+
return ListToolsResponse(**response.json()).tools
|
|
158
|
+
|
|
159
|
+
def delete_tool(self, name: str):
|
|
160
|
+
response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/tools/{name}", headers=self.headers)
|
|
161
|
+
if response.status_code != 200:
|
|
162
|
+
raise ValueError(f"Failed to delete tool: {response.text}")
|
|
163
|
+
return response.json()
|
|
164
|
+
|
|
165
|
+
def get_tool(self, name: str):
|
|
166
|
+
response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/tools/{name}", headers=self.headers)
|
|
167
|
+
if response.status_code == 404:
|
|
168
|
+
return None
|
|
169
|
+
elif response.status_code != 200:
|
|
170
|
+
raise ValueError(f"Failed to get tool: {response.text}")
|
|
171
|
+
return ToolModel(**response.json())
|