Skip to content

Commit c07e391

Browse files
authored
Merge pull request #10 from AnswerDotAI/feat/9-multipart-requests
add multipart request support
2 parents d458f63 + d7f0336 commit c07e391

File tree

4 files changed

+244
-12
lines changed

4 files changed

+244
-12
lines changed

cachy.jsonl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@
1919
{"key": "d4142886", "response": "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\": [\n {\n \"text\": \"Concurrency\\n\"\n }\n ],\n \"role\": \"model\"\n },\n \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.29076665639877319\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 10,\n \"candidatesTokenCount\": 2,\n \"totalTokenCount\": 12,\n \"promptTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 10\n }\n ],\n \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 2\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash\",\n \"responseId\": \"1gvIaLDAGe2kvdIPsY6--Q0\"\n}\n"}
2020
{"key": "fe23aa62", "response": "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"Concurrency\"}],\"role\": \"model\"}}],\"usageMetadata\": {\"promptTokenCount\": 12,\"totalTokenCount\": 12,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 12}]},\"modelVersion\": \"gemini-2.0-flash\",\"responseId\": \"1gvIaKSQOt3h1PIPwJO12Ac\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\\n\"}],\"role\": \"model\"},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 11,\"candidatesTokenCount\": 2,\"totalTokenCount\": 13,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 11}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 2}]},\"modelVersion\": \"gemini-2.0-flash\",\"responseId\": \"1gvIaKSQOt3h1PIPwJO12Ac\"}\r\n\r\n"}
2121
{"key": "c90feca2", "response": "{\"id\":\"msg_01HpiQTg22STqarE33JnuHdt\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-sonnet-4-20250514\",\"content\":[{\"type\":\"tool_use\",\"id\":\"toolu_0182nVBg1pTYTadKxS5qgCt4\",\"name\":\"get_current_weather\",\"input\":{\"location\":\"Reims\"}}],\"stop_reason\":\"tool_use\",\"stop_sequence\":null,\"usage\":{\"input_tokens\":427,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":57,\"service_tier\":\"standard\"}}"}
22+
{"key": "79d28180", "response": "{\n \"id\": \"resp_0d29a574150b40b200692da5070d2c81a19a42ec84f97314ef\",\n \"object\": \"response\",\n \"created_at\": 1764599047,\n \"status\": \"completed\",\n \"background\": false,\n \"billing\": {\n \"payer\": \"developer\"\n },\n \"error\": null,\n \"incomplete_details\": null,\n \"instructions\": null,\n \"max_output_tokens\": null,\n \"max_tool_calls\": null,\n \"model\": \"gpt-4.1-2025-04-14\",\n \"output\": [\n {\n \"id\": \"msg_0d29a574150b40b200692da507957081a19436f848296dfbb9\",\n \"type\": \"message\",\n \"status\": \"completed\",\n \"content\": [\n {\n \"type\": \"output_text\",\n \"annotations\": [],\n \"logprobs\": [],\n \"text\": \"Hey! How can I help you today? \\ud83d\\ude0a\"\n }\n ],\n \"role\": \"assistant\"\n }\n ],\n \"parallel_tool_calls\": true,\n \"previous_response_id\": null,\n \"prompt_cache_key\": null,\n \"prompt_cache_retention\": null,\n \"reasoning\": {\n \"effort\": null,\n \"summary\": null\n },\n \"safety_identifier\": null,\n \"service_tier\": \"default\",\n \"store\": true,\n \"temperature\": 1.0,\n \"text\": {\n \"format\": {\n \"type\": \"text\"\n },\n \"verbosity\": \"medium\"\n },\n \"tool_choice\": \"auto\",\n \"tools\": [],\n \"top_logprobs\": 0,\n \"top_p\": 1.0,\n \"truncation\": \"disabled\",\n \"usage\": {\n \"input_tokens\": 9,\n \"input_tokens_details\": {\n \"cached_tokens\": 0\n },\n \"output_tokens\": 11,\n \"output_tokens_details\": {\n \"reasoning_tokens\": 0\n },\n \"total_tokens\": 20\n },\n \"user\": null,\n \"metadata\": {}\n}"}
23+
{"key": "bccdd394", "response": "{\"type\":\"file\",\"id\":\"file_011CVgC7NxcXFGnoqb8FSb6A\",\"size_bytes\":11,\"created_at\":\"2025-12-01T15:19:40.864000Z\",\"filename\":\"ex.txt\",\"mime_type\":\"text/plain\",\"downloadable\":false}"}

cachy/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
'syms': { 'cachy.core': { 'cachy.core._apply_async_patch': ('core.html#_apply_async_patch', 'cachy/core.py'),
99
'cachy.core._apply_sync_patch': ('core.html#_apply_sync_patch', 'cachy/core.py'),
1010
'cachy.core._cache': ('core.html#_cache', 'cachy/core.py'),
11+
'cachy.core._content': ('core.html#_content', 'cachy/core.py'),
1112
'cachy.core._key': ('core.html#_key', 'cachy/core.py'),
1213
'cachy.core._should_cache': ('core.html#_should_cache', 'cachy/core.py'),
1314
'cachy.core._write_cache': ('core.html#_write_cache', 'cachy/core.py'),

cachy/core.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ def _cache(key, cfp):
2525
def _write_cache(key, content, cfp):
2626
with open(cfp, "a") as f: f.write(json.dumps({"key":key, "response": content})+"\n")
2727

28+
# %% ../nbs/00_core.ipynb
29+
def _content(r):
30+
"Extract content from request."
31+
if not hasattr(r, '_content'): r.read()
32+
boundary = httpx._multipart.get_multipart_boundary_from_content_type(r.headers.get("Content-Type", "").encode())
33+
return r.content.replace(boundary, b"cachy-boundary") if boundary else r.content
34+
2835
# %% ../nbs/00_core.ipynb
2936
def _key(r, is_stream=False):
3037
"Create a unique, deterministic id from the request `r`."
31-
return hashlib.sha256(f"{r.url.host}{is_stream}".encode() + r.content).hexdigest()[:8]
38+
return hashlib.sha256(f"{r.url.host}{is_stream}".encode() + _content(r)).hexdigest()[:8]
3239

3340
# %% ../nbs/00_core.ipynb
3441
def _apply_async_patch(cfp, doms):

0 commit comments

Comments
 (0)