echocache 1.0.0__tar.gz
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.
- echocache-1.0.0/PKG-INFO +82 -0
- echocache-1.0.0/README.md +49 -0
- echocache-1.0.0/echocache/__init__.py +3 -0
- echocache-1.0.0/echocache/cache.py +49 -0
- echocache-1.0.0/echocache/client.py +109 -0
- echocache-1.0.0/echocache/connection.py +40 -0
- echocache-1.0.0/echocache/validate.py +21 -0
- echocache-1.0.0/echocache.egg-info/PKG-INFO +82 -0
- echocache-1.0.0/echocache.egg-info/SOURCES.txt +12 -0
- echocache-1.0.0/echocache.egg-info/dependency_links.txt +1 -0
- echocache-1.0.0/echocache.egg-info/requires.txt +1 -0
- echocache-1.0.0/echocache.egg-info/top_level.txt +1 -0
- echocache-1.0.0/setup.cfg +4 -0
- echocache-1.0.0/setup.py +38 -0
echocache-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: echocache
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for EchoCache — Dynamic Semantic Cache for LLM APIs
|
|
5
|
+
Home-page: https://echocache.dev
|
|
6
|
+
Author: EchoCache Team
|
|
7
|
+
Author-email: echocache322@gmail.com
|
|
8
|
+
Project-URL: Source, https://github.com/echo-cache/echocache-python
|
|
9
|
+
Project-URL: Tracker, https://github.com/echo-cache/echocache-python/issues
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.7
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: requests>=2.25.0
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: project-url
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
33
|
+
|
|
34
|
+
# echocache
|
|
35
|
+
|
|
36
|
+
Official Python SDK for [EchoCache](https://echocache.dev) — The Enterprise Dynamic Semantic Cache for LLM APIs.
|
|
37
|
+
|
|
38
|
+
Reduce LLM API costs by **up to 80%** and accelerate response times from **~1.8s down to <25ms** using vector similarity lookups.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install echocache
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import os
|
|
50
|
+
from echocache import EchoCache
|
|
51
|
+
|
|
52
|
+
# 1. Initialize EchoCache client
|
|
53
|
+
echo = EchoCache(os.environ["ECHOCACHE_API_KEY"])
|
|
54
|
+
|
|
55
|
+
# 2. Wrap your LLM generator call
|
|
56
|
+
def generate_llm_response(prompt: str) -> str:
|
|
57
|
+
# Example using OpenAI Python SDK
|
|
58
|
+
response = openai.chat.completions.create(
|
|
59
|
+
model="gpt-5.6-sol",
|
|
60
|
+
messages=[{"role": "user", "content": prompt}]
|
|
61
|
+
)
|
|
62
|
+
return response.choices[0].message.content
|
|
63
|
+
|
|
64
|
+
# 3. Intercept request (returns cached answer on HIT, or calls generator on MISS)
|
|
65
|
+
prompt = "What is the capital of France?"
|
|
66
|
+
answer = echo.ask(prompt, generate_llm_response)
|
|
67
|
+
|
|
68
|
+
print(answer)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration Options
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
echo = EchoCache(
|
|
75
|
+
"ec_prod_your_api_key_here",
|
|
76
|
+
{"baseUrl": "https://echocache.dev"} # Optional: Custom self-hosted EchoCache endpoint
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT © EchoCache Team
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# echocache
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [EchoCache](https://echocache.dev) — The Enterprise Dynamic Semantic Cache for LLM APIs.
|
|
4
|
+
|
|
5
|
+
Reduce LLM API costs by **up to 80%** and accelerate response times from **~1.8s down to <25ms** using vector similarity lookups.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install echocache
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import os
|
|
17
|
+
from echocache import EchoCache
|
|
18
|
+
|
|
19
|
+
# 1. Initialize EchoCache client
|
|
20
|
+
echo = EchoCache(os.environ["ECHOCACHE_API_KEY"])
|
|
21
|
+
|
|
22
|
+
# 2. Wrap your LLM generator call
|
|
23
|
+
def generate_llm_response(prompt: str) -> str:
|
|
24
|
+
# Example using OpenAI Python SDK
|
|
25
|
+
response = openai.chat.completions.create(
|
|
26
|
+
model="gpt-5.6-sol",
|
|
27
|
+
messages=[{"role": "user", "content": prompt}]
|
|
28
|
+
)
|
|
29
|
+
return response.choices[0].message.content
|
|
30
|
+
|
|
31
|
+
# 3. Intercept request (returns cached answer on HIT, or calls generator on MISS)
|
|
32
|
+
prompt = "What is the capital of France?"
|
|
33
|
+
answer = echo.ask(prompt, generate_llm_response)
|
|
34
|
+
|
|
35
|
+
print(answer)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Configuration Options
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
echo = EchoCache(
|
|
42
|
+
"ec_prod_your_api_key_here",
|
|
43
|
+
{"baseUrl": "https://echocache.dev"} # Optional: Custom self-hosted EchoCache endpoint
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT © EchoCache Team
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
def check_cache(prompt: str, api_key: str, base_url: str, project_id: str = "proj_default") -> dict:
|
|
5
|
+
"""
|
|
6
|
+
Queries the EchoCache backend for a matching cached answer.
|
|
7
|
+
"""
|
|
8
|
+
response = requests.post(
|
|
9
|
+
f"{base_url}/api/cache",
|
|
10
|
+
headers={
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
"Authorization": f"Bearer {api_key}",
|
|
13
|
+
"x-project-id": project_id
|
|
14
|
+
},
|
|
15
|
+
json={"prompt": prompt, "project_id": project_id},
|
|
16
|
+
timeout=5
|
|
17
|
+
)
|
|
18
|
+
if response.status_code != 200:
|
|
19
|
+
raise RuntimeError(f"Cache read failed (HTTP {response.status_code})")
|
|
20
|
+
return response.json()
|
|
21
|
+
|
|
22
|
+
def save_to_cache(prompt: str, llm_response: str, latency_ms: int, api_key: str, base_url: str, project_id: str = "proj_default") -> None:
|
|
23
|
+
"""
|
|
24
|
+
Sends the generated LLM response to EchoCache to be saved for future hits.
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
# Rough token estimation: ~4 characters per token
|
|
28
|
+
tokens_saved = (len(prompt) // 4) + (len(llm_response) // 4)
|
|
29
|
+
response = requests.post(
|
|
30
|
+
f"{base_url}/api/cache/save",
|
|
31
|
+
headers={
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
"Authorization": f"Bearer {api_key}",
|
|
34
|
+
"x-project-id": project_id
|
|
35
|
+
},
|
|
36
|
+
json={
|
|
37
|
+
"prompt": prompt,
|
|
38
|
+
"llm_response": llm_response,
|
|
39
|
+
"status": "miss",
|
|
40
|
+
"latency_ms": latency_ms,
|
|
41
|
+
"tokens_saved": tokens_saved,
|
|
42
|
+
"project_id": project_id
|
|
43
|
+
},
|
|
44
|
+
timeout=10
|
|
45
|
+
)
|
|
46
|
+
if response.status_code != 200:
|
|
47
|
+
print(f"[EchoCache] Background sync returned HTTP {response.status_code}", file=sys.stderr)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"[EchoCache] Background sync failed: {e}", file=sys.stderr)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
import threading
|
|
4
|
+
from typing import Callable, Optional, Union
|
|
5
|
+
|
|
6
|
+
from .connection import parse_connection_string
|
|
7
|
+
from .validate import validate_key
|
|
8
|
+
from .cache import check_cache, save_to_cache
|
|
9
|
+
|
|
10
|
+
class EchoCache:
|
|
11
|
+
def __init__(self, target: Optional[Union[str, dict]] = None, options: Optional[dict] = None):
|
|
12
|
+
api_key = None
|
|
13
|
+
base_url = None
|
|
14
|
+
project_id = "proj_default"
|
|
15
|
+
|
|
16
|
+
if isinstance(target, str):
|
|
17
|
+
if target.startswith("echocache://") or target.startswith("echocaches://") or "@" in target:
|
|
18
|
+
parsed = parse_connection_string(target)
|
|
19
|
+
api_key = parsed["apiKey"]
|
|
20
|
+
base_url = parsed["baseUrl"]
|
|
21
|
+
project_id = parsed["projectId"]
|
|
22
|
+
elif target.startswith("ec_prod_"):
|
|
23
|
+
api_key = target
|
|
24
|
+
options = options or {}
|
|
25
|
+
base_url = options.get("baseUrl") or os.getenv("ECHOCACHE_BASE_URL")
|
|
26
|
+
project_id = options.get("projectId") or "proj_default"
|
|
27
|
+
if not base_url:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
"Missing EchoCache baseUrl. Please pass a full connection string 'echocache://<api_key>@<host>/<project_id>' or set os.environ['ECHOCACHE_CONNECTION_STRING']."
|
|
30
|
+
)
|
|
31
|
+
else:
|
|
32
|
+
raise ValueError(
|
|
33
|
+
f"Invalid EchoCache connection argument: '{target}'. Expected connection string format: 'echocache://ec_prod_xxx@host/proj_default'"
|
|
34
|
+
)
|
|
35
|
+
elif isinstance(target, dict):
|
|
36
|
+
api_key = target.get("apiKey")
|
|
37
|
+
base_url = target.get("baseUrl") or os.getenv("ECHOCACHE_BASE_URL")
|
|
38
|
+
project_id = target.get("projectId") or "proj_default"
|
|
39
|
+
else:
|
|
40
|
+
env_conn = os.getenv("ECHOCACHE_CONNECTION_STRING")
|
|
41
|
+
if env_conn:
|
|
42
|
+
parsed = parse_connection_string(env_conn)
|
|
43
|
+
api_key = parsed["apiKey"]
|
|
44
|
+
base_url = parsed["baseUrl"]
|
|
45
|
+
project_id = parsed["projectId"]
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError(
|
|
48
|
+
"Missing EchoCache connection string. Please pass an explicit connection string 'echocache://<api_key>@<host>/<project_id>' or set os.environ['ECHOCACHE_CONNECTION_STRING']."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if not api_key or not api_key.startswith("ec_prod_"):
|
|
52
|
+
raise ValueError("Invalid EchoCache API Key. Key must start with 'ec_prod_'")
|
|
53
|
+
|
|
54
|
+
self.api_key = api_key
|
|
55
|
+
self.base_url = base_url.rstrip("/")
|
|
56
|
+
self.project_id = project_id
|
|
57
|
+
self.is_validated = False
|
|
58
|
+
|
|
59
|
+
# Validation runs in a background thread to prevent constructor blocking
|
|
60
|
+
self._init_thread = threading.Thread(target=self._init, daemon=True)
|
|
61
|
+
self._init_thread.start()
|
|
62
|
+
|
|
63
|
+
def _init(self):
|
|
64
|
+
self.is_validated = validate_key(self.api_key, self.base_url)
|
|
65
|
+
if self.is_validated:
|
|
66
|
+
print("[EchoCache] Successfully connected to Semantic Cache.")
|
|
67
|
+
|
|
68
|
+
def ask(self, prompt: str, fallback_llm_call: Callable[[str], str]) -> str:
|
|
69
|
+
# Wait for the handshake thread to finish before proceeding queries
|
|
70
|
+
self._init_thread.join()
|
|
71
|
+
|
|
72
|
+
if not self.is_validated:
|
|
73
|
+
# Bypass cache checks if validation failed
|
|
74
|
+
return fallback_llm_call(prompt)
|
|
75
|
+
|
|
76
|
+
start_time = time.time()
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
# 1. Check cache
|
|
80
|
+
cache_data = check_cache(prompt, self.api_key, self.base_url, self.project_id)
|
|
81
|
+
|
|
82
|
+
# 2. Cache HIT
|
|
83
|
+
if cache_data.get("cache") == "HIT":
|
|
84
|
+
latency_ms = int((time.time() - start_time) * 1000)
|
|
85
|
+
score = cache_data.get("score", "Exact")
|
|
86
|
+
print(f"[EchoCache] HIT! ({latency_ms}ms) - Score: {score}")
|
|
87
|
+
return cache_data.get("response")
|
|
88
|
+
|
|
89
|
+
# 3. Cache MISS
|
|
90
|
+
print("[EchoCache] MISS. Calling LLM...")
|
|
91
|
+
# Execute the dev's actual LLM generation
|
|
92
|
+
llm_start = time.time()
|
|
93
|
+
llm_response = fallback_llm_call(prompt)
|
|
94
|
+
miss_latency_ms = int((time.time() - llm_start) * 1000)
|
|
95
|
+
|
|
96
|
+
# 4. Background Sync (runs in background daemon thread)
|
|
97
|
+
sync_thread = threading.Thread(
|
|
98
|
+
target=save_to_cache,
|
|
99
|
+
args=(prompt, llm_response, miss_latency_ms, self.api_key, self.base_url, self.project_id),
|
|
100
|
+
daemon=True
|
|
101
|
+
)
|
|
102
|
+
sync_thread.start()
|
|
103
|
+
|
|
104
|
+
return llm_response
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
# Fallback to LLM on caching server failure
|
|
108
|
+
print(f"[EchoCache] Fallback triggered. Reason: {e}")
|
|
109
|
+
return fallback_llm_call(prompt)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
def parse_connection_string(connection_string: str) -> Dict[str, str]:
|
|
5
|
+
"""
|
|
6
|
+
Parses an EchoCache proprietary connection string.
|
|
7
|
+
Format: echocache://<api_key>@<host>/<project_id>
|
|
8
|
+
Example: echocache://ec_prod_d880430bbc14e293b8716f472c17e867d90f995f29dcc50e@localhost:3000/proj_default
|
|
9
|
+
"""
|
|
10
|
+
if not connection_string or not isinstance(connection_string, str):
|
|
11
|
+
raise ValueError(
|
|
12
|
+
"Missing EchoCache connection string. You must explicitly provide a connection string "
|
|
13
|
+
"(e.g. 'echocache://ec_prod_xxx@localhost:3000/proj_default') or set os.environ['ECHOCACHE_CONNECTION_STRING']."
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
s = connection_string.strip()
|
|
17
|
+
|
|
18
|
+
pattern = r"^(?:echocaches?|https?):\/\/(ec_prod_[^@]+)@([^/]+)(?:\/(.+))?$"
|
|
19
|
+
match = re.match(pattern, s)
|
|
20
|
+
|
|
21
|
+
if not match:
|
|
22
|
+
raise ValueError(
|
|
23
|
+
f"Invalid EchoCache connection string format: \"{connection_string}\". "
|
|
24
|
+
f"Expected format: echocache://<api_key>@<host>/<project_id> "
|
|
25
|
+
f"(e.g. 'echocache://ec_prod_d880430b...@localhost:3000/proj_default')"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
api_key, host, raw_project_id = match.groups()
|
|
29
|
+
project_id = raw_project_id.strip("/") if raw_project_id else "proj_default"
|
|
30
|
+
|
|
31
|
+
is_local = host.startswith("localhost") or host.startswith("127.0.0.1") or host.startswith("0.0.0.0")
|
|
32
|
+
protocol = "http" if s.startswith("http://") or is_local else "https"
|
|
33
|
+
base_url = f"{protocol}://{host}"
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
"apiKey": api_key,
|
|
37
|
+
"baseUrl": base_url,
|
|
38
|
+
"projectId": project_id,
|
|
39
|
+
"connectionString": f"echocache://{api_key}@{host}/{project_id}",
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
def validate_key(api_key: str, base_url: str) -> bool:
|
|
5
|
+
"""
|
|
6
|
+
Validates the EchoCache API key against the server validate route.
|
|
7
|
+
Returns True if valid, False otherwise.
|
|
8
|
+
"""
|
|
9
|
+
try:
|
|
10
|
+
response = requests.post(
|
|
11
|
+
f"{base_url}/api/validate",
|
|
12
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
13
|
+
timeout=5
|
|
14
|
+
)
|
|
15
|
+
if response.status_code != 200:
|
|
16
|
+
print("❌ [EchoCache] Invalid or inactive API Key.", file=sys.stderr)
|
|
17
|
+
return False
|
|
18
|
+
return True
|
|
19
|
+
except Exception as e:
|
|
20
|
+
print(f"⚠️ [EchoCache] Could not reach validation server: {e}", file=sys.stderr)
|
|
21
|
+
return False
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: echocache
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for EchoCache — Dynamic Semantic Cache for LLM APIs
|
|
5
|
+
Home-page: https://echocache.dev
|
|
6
|
+
Author: EchoCache Team
|
|
7
|
+
Author-email: echocache322@gmail.com
|
|
8
|
+
Project-URL: Source, https://github.com/echo-cache/echocache-python
|
|
9
|
+
Project-URL: Tracker, https://github.com/echo-cache/echocache-python/issues
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.7
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: requests>=2.25.0
|
|
23
|
+
Dynamic: author
|
|
24
|
+
Dynamic: author-email
|
|
25
|
+
Dynamic: classifier
|
|
26
|
+
Dynamic: description
|
|
27
|
+
Dynamic: description-content-type
|
|
28
|
+
Dynamic: home-page
|
|
29
|
+
Dynamic: project-url
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
33
|
+
|
|
34
|
+
# echocache
|
|
35
|
+
|
|
36
|
+
Official Python SDK for [EchoCache](https://echocache.dev) — The Enterprise Dynamic Semantic Cache for LLM APIs.
|
|
37
|
+
|
|
38
|
+
Reduce LLM API costs by **up to 80%** and accelerate response times from **~1.8s down to <25ms** using vector similarity lookups.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install echocache
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import os
|
|
50
|
+
from echocache import EchoCache
|
|
51
|
+
|
|
52
|
+
# 1. Initialize EchoCache client
|
|
53
|
+
echo = EchoCache(os.environ["ECHOCACHE_API_KEY"])
|
|
54
|
+
|
|
55
|
+
# 2. Wrap your LLM generator call
|
|
56
|
+
def generate_llm_response(prompt: str) -> str:
|
|
57
|
+
# Example using OpenAI Python SDK
|
|
58
|
+
response = openai.chat.completions.create(
|
|
59
|
+
model="gpt-5.6-sol",
|
|
60
|
+
messages=[{"role": "user", "content": prompt}]
|
|
61
|
+
)
|
|
62
|
+
return response.choices[0].message.content
|
|
63
|
+
|
|
64
|
+
# 3. Intercept request (returns cached answer on HIT, or calls generator on MISS)
|
|
65
|
+
prompt = "What is the capital of France?"
|
|
66
|
+
answer = echo.ask(prompt, generate_llm_response)
|
|
67
|
+
|
|
68
|
+
print(answer)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration Options
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
echo = EchoCache(
|
|
75
|
+
"ec_prod_your_api_key_here",
|
|
76
|
+
{"baseUrl": "https://echocache.dev"} # Optional: Custom self-hosted EchoCache endpoint
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT © EchoCache Team
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
echocache/__init__.py
|
|
4
|
+
echocache/cache.py
|
|
5
|
+
echocache/client.py
|
|
6
|
+
echocache/connection.py
|
|
7
|
+
echocache/validate.py
|
|
8
|
+
echocache.egg-info/PKG-INFO
|
|
9
|
+
echocache.egg-info/SOURCES.txt
|
|
10
|
+
echocache.egg-info/dependency_links.txt
|
|
11
|
+
echocache.egg-info/requires.txt
|
|
12
|
+
echocache.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.25.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
echocache
|
echocache-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from setuptools import setup, find_packages
|
|
3
|
+
|
|
4
|
+
this_directory = os.path.abspath(os.path.dirname(__file__))
|
|
5
|
+
with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
|
|
6
|
+
long_description = f.read()
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name="echocache",
|
|
10
|
+
version="1.0.0",
|
|
11
|
+
description="Official Python SDK for EchoCache — Dynamic Semantic Cache for LLM APIs",
|
|
12
|
+
long_description=long_description,
|
|
13
|
+
long_description_content_type="text/markdown",
|
|
14
|
+
author="EchoCache Team",
|
|
15
|
+
author_email="echocache322@gmail.com",
|
|
16
|
+
url="https://echocache.dev",
|
|
17
|
+
project_urls={
|
|
18
|
+
"Source": "https://github.com/echo-cache/echocache-python",
|
|
19
|
+
"Tracker": "https://github.com/echo-cache/echocache-python/issues",
|
|
20
|
+
},
|
|
21
|
+
packages=find_packages(),
|
|
22
|
+
install_requires=[
|
|
23
|
+
"requests>=2.25.0",
|
|
24
|
+
],
|
|
25
|
+
python_requires=">=3.7",
|
|
26
|
+
classifiers=[
|
|
27
|
+
"Development Status :: 5 - Production/Stable",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3.8",
|
|
32
|
+
"Programming Language :: Python :: 3.9",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
37
|
+
],
|
|
38
|
+
)
|