diff --git a/docs/engram/_includes/architecture.png b/docs/engram/_includes/architecture.png new file mode 100644 index 000000000..a7b4eb30a Binary files /dev/null and b/docs/engram/_includes/architecture.png differ diff --git a/docs/engram/_includes/check_run_status.py b/docs/engram/_includes/check_run_status.py new file mode 100644 index 000000000..3d4acf78c --- /dev/null +++ b/docs/engram/_includes/check_run_status.py @@ -0,0 +1,38 @@ +import os +import time +import uuid +from engram import EngramClient + +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) + +test_user_id = f"test-{uuid.uuid4().hex[:8]}" + +# Setup: store a memory to get a run_id +run = client.memories.add( + "The user prefers dark mode", + user_id=test_user_id, + group="default", +) + +# START PollRun +status = client.runs.wait(run.run_id) + +print(status.run_id) +print(status.status) +print(status.committed_operations) +# END PollRun + +assert status.status == "completed" +assert status.committed_operations is not None +assert len(status.memories_created) >= 1 + +time.sleep(2) # Allow tenant indexing to complete + +# Cleanup +_all = client.memories.search(query="dark mode", user_id=test_user_id, group="default") +for _m in _all: + client.memories.delete(_m.id, user_id=test_user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/check_run_status.sh b/docs/engram/_includes/check_run_status.sh new file mode 100755 index 000000000..8f8a98d57 --- /dev/null +++ b/docs/engram/_includes/check_run_status.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -euo pipefail + +BASE_URL="${ENGRAM_BASE_URL:-https://api.engram.weaviate.io}" +USER_ID="test-curl-$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8)" + +: <<'DOCSNIPPETS' +# START PollRun +curl https://api.engram.weaviate.io/v1/runs/{run-id} \ + -H "Authorization: Bearer $ENGRAM_API_KEY" +# END PollRun +DOCSNIPPETS + +# --- Test execution below --- + +# Create a memory to get a run_id +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and uses VS Code." + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +echo "Run ID: $RUN_ID" + +# Poll until completed +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + echo "Status: $STATUS" + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: run did not complete"; exit 1; } + +# Verify committed_operations +CREATED_COUNT=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq '.committed_operations.created | length') +[ "$CREATED_COUNT" -ge 1 ] || { echo "FAIL: expected at least 1 created memory"; exit 1; } +echo "Created memories: $CREATED_COUNT" + +# Cleanup +for i in $(seq 1 10); do + WARMUP=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "dark mode", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 1}}') + WARMUP_COUNT=$(echo "$WARMUP" | jq '.memories | length' 2>/dev/null || echo "0") + [ "$WARMUP_COUNT" -ge 1 ] 2>/dev/null && break + sleep 3 +done + +curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "user", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 100}}' \ + | jq -r '.memories[]? | .id // empty' | while read -r MID; do + curl -s -X DELETE "$BASE_URL/v1/memories/$MID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" > /dev/null + done + +echo "PASS" diff --git a/docs/engram/_includes/cleanup_memories.py b/docs/engram/_includes/cleanup_memories.py new file mode 100644 index 000000000..7271ec8ac --- /dev/null +++ b/docs/engram/_includes/cleanup_memories.py @@ -0,0 +1,25 @@ +import os +from engram import EngramClient + +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) + +user_id = os.environ.get("ENGRAM_USER_ID", "user-uuid") +group = os.environ.get("ENGRAM_GROUP", "default") + +deleted = 0 +for _ in range(20): + results = client.memories.search(query="user", user_id=user_id, group=group) + if len(results) == 0: + break + for m in results: + try: + client.memories.delete(m.id, topic=m.topic, user_id=user_id) + deleted += 1 + except Exception: + pass + +print(f"Deleted {deleted} memories for user_id={user_id}, group={group}") + +client.close() diff --git a/docs/engram/_includes/concepts.png b/docs/engram/_includes/concepts.png new file mode 100644 index 000000000..085d7eb99 Binary files /dev/null and b/docs/engram/_includes/concepts.png differ diff --git a/docs/engram/_includes/manage_memories.py b/docs/engram/_includes/manage_memories.py new file mode 100644 index 000000000..1cdb5bf1a --- /dev/null +++ b/docs/engram/_includes/manage_memories.py @@ -0,0 +1,58 @@ +import os +import uuid +from engram import EngramClient, APIError + +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) + +test_user_id = f"test-{uuid.uuid4().hex[:8]}" + +# Setup: store a memory so we can get and delete it +run = client.memories.add( + "The user prefers dark mode", + user_id=test_user_id, + group="default", +) +status = client.runs.wait(run.run_id) +assert status.status == "completed" +assert status.committed_operations is not None +assert len(status.memories_created) >= 1 + +memory_id = status.memories_created[0].memory_id + +# START GetMemory +memory = client.memories.get( + memory_id, + user_id=test_user_id, + group="default", +) + +print(memory.content) +print(memory.topic) +# END GetMemory + +assert memory.id == memory_id +assert "dark mode" in memory.content + +# START DeleteMemory +client.memories.delete( + memory_id, + user_id=test_user_id, + group="default", +) +# END DeleteMemory + +# Verify the memory was deleted +try: + client.memories.get(memory_id, user_id=test_user_id, group="default") + assert False, "Expected memory to be deleted" +except APIError: + pass # Memory no longer exists + +# Cleanup +_all = client.memories.search(query="dark mode", user_id=test_user_id, group="default") +for _m in _all: + client.memories.delete(_m.id, user_id=test_user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/manage_memories.sh b/docs/engram/_includes/manage_memories.sh new file mode 100755 index 000000000..c429daf01 --- /dev/null +++ b/docs/engram/_includes/manage_memories.sh @@ -0,0 +1,90 @@ +#!/bin/bash +set -euo pipefail + +BASE_URL="${ENGRAM_BASE_URL:-https://api.engram.weaviate.io}" +USER_ID="test-curl-$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8)" + +: <<'DOCSNIPPETS' +# START GetMemory +curl https://api.engram.weaviate.io/v1/memories/{memory-id}?user_id=user-uuid&group=default \ + -H "Authorization: Bearer $ENGRAM_API_KEY" +# END GetMemory + +# START DeleteMemory +curl -X DELETE https://api.engram.weaviate.io/v1/memories/{memory-id}?user_id=user-uuid&group=default \ + -H "Authorization: Bearer $ENGRAM_API_KEY" +# END DeleteMemory +DOCSNIPPETS + +# --- Test execution below --- + +# Seed a memory to manage +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and uses VS Code." + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: seed run did not complete"; exit 1; } + +# Wait for indexing +for i in $(seq 1 10); do + WARMUP=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "dark mode VS Code", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 1}}') + WARMUP_COUNT=$(echo "$WARMUP" | jq '.memories | length' 2>/dev/null || echo "0") + [ "$WARMUP_COUNT" -ge 1 ] 2>/dev/null && break + sleep 3 +done + +# Find a memory ID +MEMORY_ID=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "dark mode", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 5}}' \ + | jq -r '.memories[0].id') + +[ "$MEMORY_ID" != "null" ] || { echo "FAIL: no memory found to manage"; exit 1; } +echo "Memory ID: $MEMORY_ID" + +# Test get memory +GOT_ID=$(curl -s "$BASE_URL/v1/memories/$MEMORY_ID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.id') +[ "$GOT_ID" = "$MEMORY_ID" ] || { echo "FAIL: get returned wrong memory"; exit 1; } +echo "Get memory: OK" + +# Test delete memory +curl -s -X DELETE "$BASE_URL/v1/memories/$MEMORY_ID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" +echo "Delete memory: OK" + +# Verify deletion +HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ + "$BASE_URL/v1/memories/$MEMORY_ID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY") +[ "$HTTP_CODE" = "404" ] || echo "Warning: expected 404 after delete, got $HTTP_CODE" + +# Cleanup remaining +curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "user", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 100}}' \ + | jq -r '.memories[]? | .id // empty' | while read -r MID; do + curl -s -X DELETE "$BASE_URL/v1/memories/$MID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" > /dev/null + done + +echo "PASS" diff --git a/docs/engram/_includes/quickstart.py b/docs/engram/_includes/quickstart.py new file mode 100644 index 000000000..4ecdf4891 --- /dev/null +++ b/docs/engram/_includes/quickstart.py @@ -0,0 +1,66 @@ +import os +import time +import uuid +from engram import EngramClient + +# START Connect +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) +# END Connect + +test_user_id = f"test-{uuid.uuid4().hex[:8]}" + +# START AddMemory +run = client.memories.add( + "The user prefers dark mode and uses VS Code as their primary editor.", + user_id=test_user_id, +) + +print(run.run_id) +print(run.status) +# END AddMemory + +assert run.run_id is not None + +# START CheckRun +status = client.runs.wait(run.run_id) + +print(status.status) +# END CheckRun + +assert status.status == "completed" +assert status.committed_operations is not None +assert len(status.memories_created) >= 1 + +from engram.errors import APIError + +# Warm up tenant — retry until search succeeds (tenant may still be initializing) +for _retry in range(5): + try: + client.memories.search(query="test", user_id=test_user_id, group="default") + break + except APIError: + time.sleep(3) + +# START SearchMemory +results = client.memories.search( + query="What editor does the user prefer?", + user_id=test_user_id, +) + +for memory in results: + print(memory.content) +# END SearchMemory + +assert len(results) >= 1 +assert any("VS Code" in m.content or "editor" in m.content or "dark mode" in m.content for m in results) + +# Cleanup +for _m in results: + try: + client.memories.delete(_m.id, user_id=test_user_id, group="default") + except Exception: + pass + +client.close() diff --git a/docs/engram/_includes/quickstart.sh b/docs/engram/_includes/quickstart.sh new file mode 100755 index 000000000..310c391b6 --- /dev/null +++ b/docs/engram/_includes/quickstart.sh @@ -0,0 +1,100 @@ +#!/bin/bash +set -euo pipefail + +BASE_URL="${ENGRAM_BASE_URL:-https://api.engram.weaviate.io}" +USER_ID="test-curl-$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8)" + +: <<'DOCSNIPPETS' +# START AddMemory +curl -X POST https://api.engram.weaviate.io/v1/memories \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and uses VS Code as their primary editor." + }, + "user_id": "user-uuid" + }' +# END AddMemory + +# START CheckRun +curl https://api.engram.weaviate.io/v1/runs/{run-id} \ + -H "Authorization: Bearer $ENGRAM_API_KEY" +# END CheckRun + +# START SearchMemory +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What editor does the user prefer?", + "user_id": "user-uuid", + "retrieval_config": { + "retrieval_type": "hybrid", + "limit": 5 + } + }' +# END SearchMemory +DOCSNIPPETS + +# --- Test execution below --- + +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and uses VS Code as their primary editor." + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +echo "Run ID: $RUN_ID" + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + echo "Status: $STATUS" + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: run did not complete"; exit 1; } + +# Wait for indexing +for i in $(seq 1 10); do + WARMUP=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "dark mode editor", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 1}}') + WARMUP_COUNT=$(echo "$WARMUP" | jq '.memories | length' 2>/dev/null || echo "0") + [ "$WARMUP_COUNT" -ge 1 ] 2>/dev/null && break + sleep 3 +done + +RESULTS=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What editor does the user prefer?", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": { + "retrieval_type": "hybrid", + "limit": 5 + } + }') + +COUNT=$(echo "$RESULTS" | jq '.memories | length') +echo "Search returned $COUNT memories" +[ "$COUNT" -ge 1 ] || { echo "FAIL: expected at least 1 result"; exit 1; } + +# Cleanup +echo "$RESULTS" | jq -r '.memories[]? | .id // empty' | while read -r MID; do + curl -s -X DELETE "$BASE_URL/v1/memories/$MID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" > /dev/null +done + +echo "PASS" diff --git a/docs/engram/_includes/search_memories.py b/docs/engram/_includes/search_memories.py new file mode 100644 index 000000000..2cc85cc24 --- /dev/null +++ b/docs/engram/_includes/search_memories.py @@ -0,0 +1,92 @@ +import os +import uuid +from engram import EngramClient, RetrievalConfig + +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) + +test_user_id = f"test-{uuid.uuid4().hex[:8]}" + +# Setup: store a memory so we have data to search +run = client.memories.add( + "The user prefers dark mode and works primarily in Python. They are building a RAG application.", + user_id=test_user_id, + group="default", +) +status = client.runs.wait(run.run_id) +assert status.status == "completed" +assert len(status.memories_created) >= 1 + +# START BasicSearch +results = client.memories.search( + query="What programming language does the user prefer?", + user_id=test_user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) + +for memory in results: + print(memory.content) +# END BasicSearch + +assert len(results) >= 1 + +# START VectorSearch +results = client.memories.search( + query="What programming language does the user prefer?", + user_id=test_user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="vector", limit=10), +) +# END VectorSearch + +assert len(results) >= 1 + +# START BM25Search +results = client.memories.search( + query="What programming language does the user prefer?", + user_id=test_user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="bm25", limit=10), +) +# END BM25Search + +assert len(results) >= 1 + +# START HybridSearch +results = client.memories.search( + query="What programming language does the user prefer?", + user_id=test_user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=10), +) +# END HybridSearch + +assert len(results) >= 1 + +# Discover actual topic name from existing results +topic = results[0].topic + +# START TopicFilter +results = client.memories.search( + query="user preferences", + topics=[topic], + user_id=test_user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=10), +) + +for memory in results: + print(memory.content) +# END TopicFilter + +assert len(results) >= 1 +assert all(m.topic == topic for m in results) + +# Cleanup +_all = client.memories.search(query="user", user_id=test_user_id, group="default") +for _m in _all: + client.memories.delete(_m.id, user_id=test_user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/search_memories.sh b/docs/engram/_includes/search_memories.sh new file mode 100755 index 000000000..14a738c1a --- /dev/null +++ b/docs/engram/_includes/search_memories.sh @@ -0,0 +1,209 @@ +#!/bin/bash +set -euo pipefail + +BASE_URL="${ENGRAM_BASE_URL:-https://api.engram.weaviate.io}" +USER_ID="test-curl-$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8)" + +: <<'DOCSNIPPETS' +# START BasicSearch +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "user-uuid", + "group": "default", + "retrieval_config": { + "retrieval_type": "hybrid", + "limit": 5 + } + }' +# END BasicSearch + +# START VectorSearch +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "user-uuid", + "group": "default", + "retrieval_config": { + "retrieval_type": "vector", + "limit": 10 + } + }' +# END VectorSearch + +# START BM25Search +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "Python", + "user_id": "user-uuid", + "group": "default", + "retrieval_config": { + "retrieval_type": "bm25", + "limit": 10 + } + }' +# END BM25Search + +# START HybridSearch +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "user-uuid", + "group": "default", + "retrieval_config": { + "retrieval_type": "hybrid", + "limit": 10 + } + }' +# END HybridSearch + +# START TopicFilter +curl -X POST https://api.engram.weaviate.io/v1/memories/search \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "user preferences", + "topics": ["UserKnowledge"], + "user_id": "user-uuid", + "group": "default", + "retrieval_config": { + "retrieval_type": "hybrid", + "limit": 10 + } + }' +# END TopicFilter +DOCSNIPPETS + +# --- Test execution below --- + +# Seed memories for search tests +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user works primarily in Python and prefers dark mode. They are building a RAG application with FastAPI." + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: seed run did not complete"; exit 1; } + +# Wait for indexing +for i in $(seq 1 10); do + WARMUP=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "Python dark mode", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 1}}') + WARMUP_COUNT=$(echo "$WARMUP" | jq '.memories | length' 2>/dev/null || echo "0") + [ "$WARMUP_COUNT" -ge 1 ] 2>/dev/null && break + sleep 3 +done + +# Test basic search +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "hybrid", "limit": 5} + }' | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: basic search returned 0 results"; exit 1; } +echo "Basic search: $COUNT results" + +# Test vector search +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "vector", "limit": 10} + }' | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: vector search returned 0 results"; exit 1; } +echo "Vector search: $COUNT results" + +# Test BM25 search +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "Python", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "bm25", "limit": 10} + }' | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: BM25 search returned 0 results"; exit 1; } +echo "BM25 search: $COUNT results" + +# Test hybrid search +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "What programming language does the user prefer?", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "hybrid", "limit": 10} + }' | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: hybrid search returned 0 results"; exit 1; } +echo "Hybrid search: $COUNT results" + +# Test topic filter search — dynamically discover topic name from existing memories +TOPIC_RESPONSE=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "user preferences", + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "hybrid", "limit": 5} + }') +FIRST_TOPIC=$(echo "$TOPIC_RESPONSE" | jq -r '.memories[0].topic // empty' 2>/dev/null) +if [ -n "$FIRST_TOPIC" ]; then + COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "query": "user preferences", + "topics": ["'"$FIRST_TOPIC"'"], + "user_id": "'"$USER_ID"'", + "group": "default", + "retrieval_config": {"retrieval_type": "hybrid", "limit": 10} + }' | jq '.memories | length') + [ "$COUNT" -ge 1 ] || { echo "FAIL: topic filter search returned 0 results"; exit 1; } + echo "Topic filter search (topic=$FIRST_TOPIC): $COUNT results" +else + echo "Topic filter search: skipped (no topics found)" +fi + +# Cleanup +curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "user", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 100}}' \ + | jq -r '.memories[]? | .id // empty' | while read -r MID; do + curl -s -X DELETE "$BASE_URL/v1/memories/$MID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" > /dev/null + done + +echo "PASS" diff --git a/docs/engram/_includes/store_memories.py b/docs/engram/_includes/store_memories.py new file mode 100644 index 000000000..ec21ee2e9 --- /dev/null +++ b/docs/engram/_includes/store_memories.py @@ -0,0 +1,93 @@ +import os +import time +import uuid +from engram import EngramClient, PreExtractedContent + +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) + +test_user_id = f"test-{uuid.uuid4().hex[:8]}" + +# START StoreString +run = client.memories.add( + "The user prefers dark mode and works primarily in Python. They are building a RAG application.", + user_id=test_user_id, + group="default", +) + +print(run.run_id) +print(run.status) +# END StoreString + +assert run.run_id is not None +status = client.runs.wait(run.run_id) +assert status.status == "completed" +assert len(status.memories_created) >= 1 + +from engram.errors import APIError + +# Warm up tenant — retry until search succeeds (tenant may still be initializing) +for _retry in range(5): + try: + client.memories.search(query="test", user_id=test_user_id, group="default") + break + except APIError: + time.sleep(3) + +results = client.memories.search(query="Python RAG dark mode", user_id=test_user_id, group="default") +assert len(results) >= 1 +assert any("Python" in m.content or "dark mode" in m.content or "RAG" in m.content for m in results) + +"""TODO[g-despot] Needs topic + +# START StorePreExtracted +run = client.memories.add( + PreExtractedContent( + content="User prefers dark mode", + ), + user_id=test_user_id, + group="default", +) + +print(run.run_id) +print(run.status) +# END StorePreExtracted + +assert run.run_id is not None +status = client.runs.wait(run.run_id) +assert status.status == "completed" + +results = client.memories.search(query="dark mode preference", user_id=test_user_id, group="default") +assert len(results) >= 1 +assert any("dark mode" in m.content for m in results) +""" +# START StoreConversation +run = client.memories.add( + [ + {"role": "user", "content": "I just moved to Berlin and I am looking for a good coffee shop."}, + {"role": "assistant", "content": "Welcome to Berlin! Here are some popular coffee shops in the city..."}, + {"role": "user", "content": "I prefer specialty coffee, not chains."}, + ], + user_id=test_user_id, + group="default", +) + +print(run.run_id) +print(run.status) +# END StoreConversation + +assert run.run_id is not None +status = client.runs.wait(run.run_id) +assert status.status == "completed" + +results = client.memories.search(query="Berlin coffee specialty", user_id=test_user_id, group="default") +assert len(results) >= 1 +assert any("Berlin" in m.content or "coffee" in m.content for m in results) + +# Cleanup +_all = client.memories.search(query="user", user_id=test_user_id, group="default") +for _m in _all: + client.memories.delete(_m.id, user_id=test_user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/store_memories.sh b/docs/engram/_includes/store_memories.sh new file mode 100755 index 000000000..a52d3a7ae --- /dev/null +++ b/docs/engram/_includes/store_memories.sh @@ -0,0 +1,186 @@ +#!/bin/bash +set -euo pipefail + +BASE_URL="${ENGRAM_BASE_URL:-https://api.engram.weaviate.io}" +USER_ID="test-curl-$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8)" +CONVERSATION_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') + +: <<'DOCSNIPPETS' +# START StoreString +curl -X POST https://api.engram.weaviate.io/v1/memories \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and works primarily in Python. They are building a RAG application." + }, + "user_id": "user-uuid", + "group": "default" + }' +# END StoreString + +# START StorePreExtracted +curl -X POST https://api.engram.weaviate.io/v1/memories \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "pre_extracted", + "content": "User prefers dark mode", + "topic": "preferences" + }, + "user_id": "user-uuid", + "group": "default" + }' +# END StorePreExtracted + +# START StoreConversation +curl -X POST https://api.engram.weaviate.io/v1/memories \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "conversation", + "conversation": { + "messages": [ + { + "role": "user", + "content": "I just moved to Berlin and I am looking for a good coffee shop." + }, + { + "role": "assistant", + "content": "Welcome to Berlin! Here are some popular coffee shops in the city..." + }, + { + "role": "user", + "content": "I prefer specialty coffee, not chains." + } + ] + } + }, + "user_id": "user-uuid", + "group": "default" + }' +# END StoreConversation +DOCSNIPPETS + +# --- Test execution below --- + +# Store string content +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "string", + "content": "The user prefers dark mode and works primarily in Python. They are building a RAG application." + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: string store run did not complete"; exit 1; } + +# Wait for indexing +for i in $(seq 1 10); do + WARMUP=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "Python dark mode", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 1}}') + WARMUP_COUNT=$(echo "$WARMUP" | jq '.memories | length' 2>/dev/null || echo "0") + [ "$WARMUP_COUNT" -ge 1 ] 2>/dev/null && break + sleep 3 +done + +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "Python RAG dark mode", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 5}}' \ + | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: expected at least 1 result for string store"; exit 1; } +echo "String store: $COUNT memories" + +# Store pre-extracted content +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "pre_extracted", + "content": "User prefers dark mode", + "topic": "preferences" + }, + "user_id": "'"$USER_ID"'", + "group": "default" + }' | jq -r '.run_id') + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: pre-extracted store run did not complete"; exit 1; } + +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "dark mode preference", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 5}}' \ + | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: expected at least 1 result for pre-extracted store"; exit 1; } +echo "Pre-extracted store: $COUNT memories" + +# Store conversation content +RUN_ID=$(curl -s -X POST "$BASE_URL/v1/memories" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "content": { + "type": "conversation", + "conversation": { + "messages": [ + {"role": "user", "content": "I just moved to Berlin and I am looking for a good coffee shop."}, + {"role": "assistant", "content": "Welcome to Berlin! Here are some popular coffee shops in the city..."}, + {"role": "user", "content": "I prefer specialty coffee, not chains."} + ] + } + }, + "user_id": "'"$USER_ID"'", + "conversation_id": "'"$CONVERSATION_ID"'", + "group": "default" + }' | jq -r '.run_id') + +for i in $(seq 1 30); do + STATUS=$(curl -s "$BASE_URL/v1/runs/$RUN_ID" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" | jq -r '.status') + [ "$STATUS" = "completed" ] && break + sleep 2 +done +[ "$STATUS" = "completed" ] || { echo "FAIL: conversation store run did not complete"; exit 1; } + +COUNT=$(curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "Berlin coffee specialty", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 5}}' \ + | jq '.memories | length') +[ "$COUNT" -ge 1 ] || { echo "FAIL: expected at least 1 result for conversation store"; exit 1; } +echo "Conversation store: $COUNT memories" + +# Cleanup +curl -s -X POST "$BASE_URL/v1/memories/search" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "user", "user_id": "'"$USER_ID"'", "group": "default", "retrieval_config": {"retrieval_type": "hybrid", "limit": 100}}' \ + | jq -r '.memories[]? | .id // empty' | while read -r MID; do + curl -s -X DELETE "$BASE_URL/v1/memories/$MID?user_id=$USER_ID&group=default" \ + -H "Authorization: Bearer $ENGRAM_API_KEY" > /dev/null + done + +echo "PASS" diff --git a/docs/engram/_includes/tutorial_context_window_mgmt.py b/docs/engram/_includes/tutorial_context_window_mgmt.py new file mode 100644 index 000000000..ed8705d19 --- /dev/null +++ b/docs/engram/_includes/tutorial_context_window_mgmt.py @@ -0,0 +1,301 @@ +import os +import time +import uuid +from engram import EngramClient, RetrievalConfig + +# START Setup +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) +user_id = f"tutorial-context-{uuid.uuid4().hex[:8]}" +# END Setup + + +# START NaiveChatAnthropic +def naive_chat_anthropic(): + """Naive approach: send full conversation history every time.""" + import anthropic + + anthropic_client = anthropic.Anthropic() + messages = [] + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + messages.append({"role": "user", "content": user_input}) + + # Every call sends the ENTIRE conversation history + response = anthropic_client.messages.create( + model="claude-sonnet-4-5-20250929", + max_tokens=1024, + system="You are a helpful assistant.", + messages=messages, # This list grows with every turn + ) + assistant_message = response.content[0].text + messages.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}") + print(f"Messages in context: {len(messages)}\n") + + +# END NaiveChatAnthropic + + +# START NaiveChatOpenAI +def naive_chat_openai(): + """Naive approach: send full conversation history every time.""" + from openai import OpenAI + + openai_client = OpenAI() + messages = [{"role": "system", "content": "You are a helpful assistant."}] + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + messages.append({"role": "user", "content": user_input}) + + # Every call sends the ENTIRE conversation history + response = openai_client.chat.completions.create( + model="gpt-4o", + messages=messages, # This list grows with every turn + ) + assistant_message = response.choices[0].message.content + messages.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}") + print(f"Messages in context: {len(messages)}\n") + + +# END NaiveChatOpenAI + + +# START TokenCount +def count_tokens(text): + """Approximate token count (1 token ~ 4 characters).""" + return len(text) // 4 + + +# Simulate a 50-turn conversation +total_tokens = 0 +for i in range(50): + user_msg = f"Turn {i}: I'd like to discuss my Python project and get advice on architecture." + assistant_msg = f"Turn {i}: Here are some suggestions for your Python project architecture and best practices to follow." + total_tokens += count_tokens(user_msg) + count_tokens(assistant_msg) + +print(f"50-turn conversation: ~{total_tokens:,} tokens per request") +print(f"At $3/1M input tokens: ~${total_tokens * 3 / 1_000_000:.4f} per request") +# END TokenCount + +# START StoreMemories +conversation = [ + {"role": "user", "content": "I'm a software engineer working on a Python web app."}, + { + "role": "assistant", + "content": "That sounds interesting! What framework are you using?", + }, + { + "role": "user", + "content": "I'm using FastAPI with PostgreSQL. I prefer async patterns.", + }, + { + "role": "assistant", + "content": "Great choices! FastAPI's async support works well with PostgreSQL.", + }, + { + "role": "user", + "content": "I also use Redis for caching and Celery for background tasks.", + }, + { + "role": "assistant", + "content": "That's a solid stack. Redis and Celery pair nicely with FastAPI.", + }, +] + +run = client.memories.add( + conversation, + user_id=user_id, + group="default", +) + +status = client.runs.wait(run.run_id) +print(f"Run status: {status.status}") +print(f"Memories created: {len(status.memories_created)}") +# END StoreMemories + +assert status.status == "completed" + +time.sleep(5) # Allow tenant indexing to complete + + +# START MemoryAugmentedChatAnthropic +def memory_augmented_chat_anthropic(): + """Memory-augmented approach: use Engram instead of full history.""" + import anthropic + + engram = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"], + ) + anthropic_client = anthropic.Anthropic() + user_id = "user-123" + recent_messages = [] # Keep only last few exchanges + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + # Search Engram for relevant memories + results = engram.memories.search( + query=user_input, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + memory_context = "\n".join(f"- {m.content}" for m in results) + + system_prompt = f"""You are a helpful assistant. + +Relevant context from previous conversations: +{memory_context}""" + + recent_messages.append({"role": "user", "content": user_input}) + + # Send only recent messages + memory context (not full history) + response = anthropic_client.messages.create( + model="claude-sonnet-4-5-20250929", + max_tokens=1024, + system=system_prompt, + messages=recent_messages[-6:], # Last 3 exchanges only + ) + assistant_message = response.content[0].text + recent_messages.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}") + print(f"Messages in context: {min(len(recent_messages), 6)}\n") + + # Store the exchange as a memory + run = engram.memories.add( + [recent_messages[-2], recent_messages[-1]], + user_id=user_id, + group="default", + ) + engram.runs.wait(run.run_id) + + engram.close() + + +# END MemoryAugmentedChatAnthropic + + +# START MemoryAugmentedChatOpenAI +def memory_augmented_chat_openai(): + """Memory-augmented approach: use Engram instead of full history.""" + from openai import OpenAI + + engram = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"], + ) + openai_client = OpenAI() + user_id = "user-123" + recent_messages = [] + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + # Search Engram for relevant memories + results = engram.memories.search( + query=user_input, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + memory_context = "\n".join(f"- {m.content}" for m in results) + + system_prompt = f"""You are a helpful assistant. + +Relevant context from previous conversations: +{memory_context}""" + + recent_messages.append({"role": "user", "content": user_input}) + + # Send only recent messages + memory context (not full history) + response = openai_client.chat.completions.create( + model="gpt-4o", + messages=[ + {"role": "system", "content": system_prompt}, + *recent_messages[-6:], # Last 3 exchanges only + ], + ) + assistant_message = response.choices[0].message.content + recent_messages.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}") + print(f"Messages in context: {min(len(recent_messages), 6)}\n") + + # Store the exchange as a memory + run = engram.memories.add( + [recent_messages[-2], recent_messages[-1]], + user_id=user_id, + group="default", + ) + engram.runs.wait(run.run_id) + + engram.close() + + +# END MemoryAugmentedChatOpenAI + +# START SideBySide +avg_user_tokens = 25 +avg_assistant_tokens = 100 +avg_memory_tokens = 50 # ~5 retrieved memories at ~10 tokens each +recent_window = 6 # Keep last 3 exchanges (6 messages) + +print(f"{'Turn':<6} {'Naive (tokens)':<18} {'Memory (tokens)':<18} {'Savings'}") +print("-" * 58) + +for turn in [1, 5, 10, 20, 50]: + # Naive: token count grows linearly with conversation length + naive_tokens = turn * (avg_user_tokens + avg_assistant_tokens) + + # Memory-augmented: fixed recent window + memory search results + recent_count = min(turn, recent_window // 2) + memory_tokens = ( + recent_count * (avg_user_tokens + avg_assistant_tokens) + avg_memory_tokens + ) + + savings = (1 - memory_tokens / naive_tokens) * 100 if naive_tokens > 0 else 0 + print(f"{turn:<6} {naive_tokens:<18,} {memory_tokens:<18,} {savings:.0f}%") +# END SideBySide + +from engram.errors import APIError + +# Warm up tenant — retry until search succeeds (tenant may still be initializing) +for _retry in range(5): + try: + client.memories.search(query="test", user_id=user_id, group="default") + break + except APIError: + time.sleep(3) + +# START TopicFiltering +results = client.memories.search( + query="What tech stack does the user prefer?", + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) + +for memory in results: + print(f"- {memory.content} (topic: {memory.topic})") +# END TopicFiltering + +assert len(results) >= 1 + +# Cleanup +for _m in results: + client.memories.delete(_m.id, user_id=user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/tutorial_memory_chat_app.py b/docs/engram/_includes/tutorial_memory_chat_app.py new file mode 100644 index 000000000..73f84042f --- /dev/null +++ b/docs/engram/_includes/tutorial_memory_chat_app.py @@ -0,0 +1,330 @@ +import os +import uuid +from engram import EngramClient, RetrievalConfig + +# START Setup +client = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) +user_id = f"tutorial-chat-{uuid.uuid4().hex[:8]}" +# END Setup + + +# START ChatFunctionAnthropic +def chat_anthropic( + user_message, conversation_history, system_prompt="You are a helpful assistant." +): + import anthropic + + conversation_history.append({"role": "user", "content": user_message}) + response = anthropic.Anthropic().messages.create( + model="claude-sonnet-4-5-20250929", + max_tokens=1024, + system=system_prompt, + messages=conversation_history, + ) + assistant_message = response.content[0].text + conversation_history.append({"role": "assistant", "content": assistant_message}) + return assistant_message + + +# END ChatFunctionAnthropic + +# Validate chat_anthropic builds conversation history correctly +_test_history = [] +_test_response = chat_anthropic("Hello, my name is Alice.", _test_history) +assert ( + len(_test_history) == 2 +), f"Expected 2 messages in history, got {len(_test_history)}" +assert _test_history[0]["role"] == "user" +assert _test_history[0]["content"] == "Hello, my name is Alice." +assert _test_history[1]["role"] == "assistant" +assert isinstance(_test_response, str) and len(_test_response) > 0 + +_test_response_2 = chat_anthropic("What is my name?", _test_history) +assert ( + len(_test_history) == 4 +), f"Expected 4 messages in history, got {len(_test_history)}" +assert _test_history[2]["role"] == "user" +assert _test_history[3]["role"] == "assistant" +assert isinstance(_test_response_2, str) and len(_test_response_2) > 0 + + +# START ChatFunctionOpenAI +def chat_openai( + user_message, conversation_history, system_prompt="You are a helpful assistant." +): + from openai import OpenAI + + conversation_history.append({"role": "user", "content": user_message}) + response = OpenAI().chat.completions.create( + model="gpt-4o", + messages=[{"role": "system", "content": system_prompt}] + conversation_history, + ) + assistant_message = response.choices[0].message.content + conversation_history.append({"role": "assistant", "content": assistant_message}) + return assistant_message + + +# END ChatFunctionOpenAI + +# Validate chat_openai builds conversation history correctly +_test_history_oai = [] +_test_response_oai = chat_openai("Hello, my name is Bob.", _test_history_oai) +assert ( + len(_test_history_oai) == 2 +), f"Expected 2 messages in history, got {len(_test_history_oai)}" +assert _test_history_oai[0]["role"] == "user" +assert _test_history_oai[0]["content"] == "Hello, my name is Bob." +assert _test_history_oai[1]["role"] == "assistant" +assert isinstance(_test_response_oai, str) and len(_test_response_oai) > 0 + +_test_response_oai_2 = chat_openai("What is my name?", _test_history_oai) +assert ( + len(_test_history_oai) == 4 +), f"Expected 4 messages in history, got {len(_test_history_oai)}" +assert _test_history_oai[2]["role"] == "user" +assert _test_history_oai[3]["role"] == "assistant" +assert isinstance(_test_response_oai_2, str) and len(_test_response_oai_2) > 0 + +# START StoreConversation +conversation = [ + { + "role": "user", + "content": "I just moved to Berlin and I'm looking for a good coffee shop.", + }, + { + "role": "assistant", + "content": "Welcome to Berlin! Here are some popular coffee shops in the city...", + }, + {"role": "user", "content": "I prefer specialty coffee, not chains."}, +] + +run = client.memories.add( + conversation, + user_id=user_id, +) + +print(f"Run ID: {run.run_id}") +print(f"Status: {run.status}") +# END StoreConversation + +status = client.runs.wait(run.run_id) +assert status.status == "completed" + +import time + +from engram.errors import APIError + +# Warm up tenant — retry until search succeeds (tenant may still be initializing) +for _retry in range(5): + try: + client.memories.search(query="test", user_id=user_id, group="default") + break + except APIError: + time.sleep(3) + +# START SearchMemories +results = client.memories.search( + query="What kind of coffee does the user like?", + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) + +memory_context = "\n".join(f"- {m.content}" for m in results) + +system_prompt = f"""You are a helpful assistant with memory of past conversations. + +Here is what you remember about this user: +{memory_context} + +Use these memories to personalize your responses.""" + +print(system_prompt) +# END SearchMemories + +assert len(results) >= 1 +assert any( + "Berlin" in m.content or "coffee" in m.content or "specialty" in m.content + for m in results +) + + +# START FullLoopAnthropic +def memory_chat_loop_anthropic(): + """Complete chat loop with Engram memory and Anthropic.""" + import anthropic + + engram = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"], + ) + anthropic_client = anthropic.Anthropic() + user_id = "user-123" + conversation_history = [] + + print("Chat with memory (type 'quit' to exit)\n") + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + # Retrieve relevant memories + results = engram.memories.search( + query=user_input, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + memory_context = "\n".join(f"- {m.content}" for m in results) + system_prompt = f"""You are a helpful assistant with memory of past conversations. + +Here is what you remember about this user: +{memory_context} + +Use these memories to personalize your responses.""" + + # Get response from Claude + conversation_history.append({"role": "user", "content": user_input}) + response = anthropic_client.messages.create( + model="claude-sonnet-4-5-20250929", + max_tokens=1024, + system=system_prompt, + messages=conversation_history, + ) + assistant_message = response.content[0].text + conversation_history.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}\n") + + # Store the conversation turn as a memory (fire-and-forget) + engram.memories.add( + [conversation_history[-2], conversation_history[-1]], + user_id=user_id, + ) + + engram.close() + + +if __name__ == "__main__": + memory_chat_loop_anthropic() +# END FullLoopAnthropic + + +# START FullLoopOpenAI +def memory_chat_loop_openai(): + """Complete chat loop with Engram memory and OpenAI.""" + from openai import OpenAI + + engram = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"], + ) + openai_client = OpenAI() + user_id = "user-123" + conversation_history = [] + + print("Chat with memory (type 'quit' to exit)\n") + + while True: + user_input = input("You: ") + if user_input.lower() == "quit": + break + + # Retrieve relevant memories + results = engram.memories.search( + query=user_input, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + memory_context = "\n".join(f"- {m.content}" for m in results) + system_prompt = f"""You are a helpful assistant with memory of past conversations. + +Here is what you remember about this user: +{memory_context} + +Use these memories to personalize your responses.""" + + # Get response from OpenAI + conversation_history.append({"role": "user", "content": user_input}) + response = openai_client.chat.completions.create( + model="gpt-4o", + messages=[{"role": "system", "content": system_prompt}] + + conversation_history, + ) + assistant_message = response.choices[0].message.content + conversation_history.append({"role": "assistant", "content": assistant_message}) + print(f"Assistant: {assistant_message}\n") + + # Store the conversation turn as a memory (fire-and-forget) + engram.memories.add( + [conversation_history[-2], conversation_history[-1]], + user_id=user_id, + ) + + engram.close() + + +# END FullLoopOpenAI + +# Validate memory_chat_loop_anthropic runs end-to-end +from unittest.mock import patch + +# Seed a memory for user-123 so the tenant exists before the loop searches +_seed_run = client.memories.add( + "Seed memory for testing.", + user_id="user-123", + group="default", +) +client.runs.wait(_seed_run.run_id) +time.sleep(3) + +with patch("builtins.input", side_effect=["I love hiking in the mountains.", "quit"]): + memory_chat_loop_anthropic() + +# Wait for fire-and-forget memories to be committed +time.sleep(10) + +# Verify the loop stored a memory +_loop_results = client.memories.search( + query="hiking mountains", + user_id="user-123", + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) +assert ( + len(_loop_results) >= 1 +), "memory_chat_loop_anthropic should have stored at least one memory" + +# Clean up loop memories +for _m in _loop_results: + client.memories.delete(_m.id, user_id="user-123", group="default") + +# Validate memory_chat_loop_openai runs end-to-end +with patch( + "builtins.input", side_effect=["I enjoy reading science fiction books.", "quit"] +): + memory_chat_loop_openai() + +# Wait for fire-and-forget memories to be committed +time.sleep(10) + +_loop_results_oai = client.memories.search( + query="science fiction books", + user_id="user-123", + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) +assert ( + len(_loop_results_oai) >= 1 +), "memory_chat_loop_openai should have stored at least one memory" + +# Clean up loop memories +for _m in _loop_results_oai: + client.memories.delete(_m.id, user_id="user-123", group="default") + +# Cleanup +for _m in results: + client.memories.delete(_m.id, user_id=user_id, group="default") + +client.close() diff --git a/docs/engram/_includes/tutorial_personalized_rag.py b/docs/engram/_includes/tutorial_personalized_rag.py new file mode 100644 index 000000000..d80c63ac6 --- /dev/null +++ b/docs/engram/_includes/tutorial_personalized_rag.py @@ -0,0 +1,323 @@ +import os +import uuid +import asyncio +from engram import EngramClient, AsyncEngramClient, RetrievalConfig, PreExtractedContent + +# START SetupClients +engram = EngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) +# END SetupClients + +_test_suffix = uuid.uuid4().hex[:8] + + +# START PopulateKB +def populate_knowledge_base(weaviate_client): + """Create a Weaviate collection and insert sample product documentation.""" + collection = weaviate_client.collections.create( + name="ProductDocs", + description="Product documentation for the Acme platform", + ) + + docs = [ + "Acme API supports REST and GraphQL endpoints for data access.", + "The Acme dashboard provides real-time analytics and custom reports.", + "Acme's Python SDK supports async operations with asyncio.", + "Acme pricing: Free tier up to 1K requests/day, Pro at $49/month for 100K requests/day.", + "Acme supports SSO with SAML and OIDC for enterprise customers.", + ] + + with collection.batch.dynamic() as batch: + for doc in docs: + batch.add_object(properties={"content": doc}) + + return collection + + +# END PopulateKB + +# START StoreUserContext +# Store preferences for Alice (Python developer) +run_a = engram.memories.add( + "I'm a Python developer. I prefer concise code examples. I'm building a FastAPI microservice.", + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", +) +status_a = engram.runs.wait(run_a.run_id) +print(f"Alice: {status_a.status}, {len(status_a.memories_created)} memories") + +# Store preferences for Bob (JavaScript developer) +run_b = engram.memories.add( + "I'm a JavaScript developer. I prefer detailed explanations with context. I'm building a React dashboard.", + user_id=f"tutorial-rag-bob-{_test_suffix}", + group="default", +) +status_b = engram.runs.wait(run_b.run_id) +print(f"Bob: {status_b.status}, {len(status_b.memories_created)} memories") +# END StoreUserContext + +assert status_a.status == "completed" +assert status_b.status == "completed" + +import time +from engram.errors import APIError + +# Warm up tenants — retry until search succeeds (tenant may still be initializing) +for _retry in range(5): + try: + engram.memories.search(query="test", user_id=f"tutorial-rag-alice-{_test_suffix}", group="default") + break + except APIError: + time.sleep(3) + +for _retry in range(5): + try: + engram.memories.search(query="test", user_id=f"tutorial-rag-bob-{_test_suffix}", group="default") + break + except APIError: + time.sleep(3) + + +# START DualSearch +def dual_search(query, user_id, kb_results=None): + """Search both a knowledge base and Engram user memory.""" + # Search Engram for user-specific memories + user_memories = engram.memories.search( + query=query, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + + return { + "knowledge_base": kb_results or [], + "user_memories": user_memories, + } + + +# END DualSearch + +# Verify dual search works +alice_results = dual_search("programming language", f"tutorial-rag-alice-{_test_suffix}") +assert len(alice_results["user_memories"]) >= 1 + + +# START BuildPromptAnthropic +def build_prompt_anthropic(query, kb_docs, user_memories): + """Build a personalized prompt combining KB docs and user memory.""" + import anthropic + + kb_context = "\n".join(f"- {doc}" for doc in kb_docs) + memory_context = "\n".join(f"- {m.content}" for m in user_memories) + + system_prompt = f"""You are a helpful product assistant. + +Product documentation: +{kb_context} + +What you know about this user: +{memory_context} + +Tailor your response to the user's background and preferences.""" + + response = anthropic.Anthropic().messages.create( + model="claude-sonnet-4-5-20250929", + max_tokens=1024, + system=system_prompt, + messages=[{"role": "user", "content": query}], + ) + return response.content[0].text + + +# END BuildPromptAnthropic + + +# START BuildPromptOpenAI +def build_prompt_openai(query, kb_docs, user_memories): + """Build a personalized prompt combining KB docs and user memory.""" + from openai import OpenAI + + kb_context = "\n".join(f"- {doc}" for doc in kb_docs) + memory_context = "\n".join(f"- {m.content}" for m in user_memories) + + system_prompt = f"""You are a helpful product assistant. + +Product documentation: +{kb_context} + +What you know about this user: +{memory_context} + +Tailor your response to the user's background and preferences.""" + + response = OpenAI().chat.completions.create( + model="gpt-4o", + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": query}, + ], + ) + return response.choices[0].message.content + + +# END BuildPromptOpenAI + +# START TwoUserDemo +query = "How do I access the API?" + +# Alice's personalized search +alice_memories = engram.memories.search( + query=query, + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) +print("Alice's context:") +for m in alice_memories: + print(f" - {m.content}") + +# Bob's personalized search +bob_memories = engram.memories.search( + query=query, + user_id=f"tutorial-rag-bob-{_test_suffix}", + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), +) +print("\nBob's context:") +for m in bob_memories: + print(f" - {m.content}") +# END TwoUserDemo + +assert len(alice_memories) >= 1 +assert len(bob_memories) >= 1 + +# Verify personalized RAG produces different answers for each user +kb_docs = [ + "Acme API supports REST and GraphQL endpoints for data access.", + "Acme's Python SDK supports async operations with asyncio.", +] + +alice_answer = build_prompt_anthropic(query, kb_docs, alice_memories) +bob_answer = build_prompt_anthropic(query, kb_docs, bob_memories) +assert isinstance(alice_answer, str) and len(alice_answer) > 0 +assert isinstance(bob_answer, str) and len(bob_answer) > 0 +assert alice_answer != bob_answer, "Personalized answers should differ for Alice and Bob" +print(f"Alice (Anthropic): {alice_answer[:100]}...") +print(f"Bob (Anthropic): {bob_answer[:100]}...") + +alice_answer_oai = build_prompt_openai(query, kb_docs, alice_memories) +bob_answer_oai = build_prompt_openai(query, kb_docs, bob_memories) +assert isinstance(alice_answer_oai, str) and len(alice_answer_oai) > 0 +assert isinstance(bob_answer_oai, str) and len(bob_answer_oai) > 0 +assert alice_answer_oai != bob_answer_oai, "Personalized answers should differ for Alice and Bob" +print(f"Alice (OpenAI): {alice_answer_oai[:100]}...") +print(f"Bob (OpenAI): {bob_answer_oai[:100]}...") + +# START UserIsolation +# Alice searches for Bob's topics — should get no relevant results +alice_cross_search = engram.memories.search( + query="React dashboard JavaScript", + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", +) +print(f"Alice searching for Bob's topics: {len(alice_cross_search)} results") + +# Bob searches for Alice's topics — should get no relevant results +bob_cross_search = engram.memories.search( + query="FastAPI Python microservice", + user_id=f"tutorial-rag-bob-{_test_suffix}", + group="default", +) +print(f"Bob searching for Alice's topics: {len(bob_cross_search)} results") +# END UserIsolation + +# Alice's results should only contain her own memories, not Bob's +for m in alice_cross_search: + assert "JavaScript" not in m.content and "React" not in m.content, ( + f"Alice should not see Bob's memories, got: {m.content}" + ) + +# Bob's results should only contain his own memories, not Alice's +for m in bob_cross_search: + assert "FastAPI" not in m.content and "Python" not in m.content, ( + f"Bob should not see Alice's memories, got: {m.content}" + ) + +# START AsyncSetup +async_client = AsyncEngramClient( + api_key=os.environ["ENGRAM_API_KEY"] +) +# END AsyncSetup + +# START ConcurrentUsers +async def search_for_user(async_engram, user_id, query): + """Search memories for a single user.""" + results = await async_engram.memories.search( + query=query, + user_id=user_id, + group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + return user_id, results + + +async def handle_concurrent_users(): + """Handle multiple users concurrently.""" + tasks = [ + search_for_user(async_client, f"tutorial-rag-alice-{_test_suffix}", "programming preferences"), + search_for_user(async_client, f"tutorial-rag-bob-{_test_suffix}", "programming preferences"), + ] + results = await asyncio.gather(*tasks) + + for uid, memories in results: + print(f"\n{uid}:") + for m in memories: + print(f" - {m.content}") + + await async_client.aclose() + return results + + +concurrent_results = asyncio.run(handle_concurrent_users()) +# END ConcurrentUsers + +assert len(concurrent_results) == 2 + +# START UserDataManagement +# Retrieve a specific memory by ID +alice_memories = engram.memories.search( + query="Python developer", + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", +) + +if alice_memories: + memory = engram.memories.get( + alice_memories[0].id, + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", + ) + print(f"Retrieved: {memory.content}") + +# Delete all of a user's memories (e.g. GDPR right-to-deletion) +for m in alice_memories: + engram.memories.delete(m.id, user_id=f"tutorial-rag-alice-{_test_suffix}", group="default") + print(f"Deleted: {m.id}") + +# Verify deletion +remaining = engram.memories.search( + query="Python developer", + user_id=f"tutorial-rag-alice-{_test_suffix}", + group="default", +) +print(f"Remaining memories for Alice: {len(remaining)}") +# END UserDataManagement + +assert len(remaining) == 0, f"All Alice memories should be deleted, got {len(remaining)}" + +# Cleanup: delete Bob's memories +for _m in bob_memories: + engram.memories.delete(_m.id, user_id=f"tutorial-rag-bob-{_test_suffix}", group="default") + +engram.close() diff --git a/docs/engram/concepts/groups.md b/docs/engram/concepts/groups.md new file mode 100644 index 000000000..f74caa076 --- /dev/null +++ b/docs/engram/concepts/groups.md @@ -0,0 +1,49 @@ +--- +title: Groups +sidebar_position: 2 +description: "Groups in Engram: containers of topics and pipelines that map 1:1 to use cases." +--- + +A group is a container of [topics](topics.md) and a [pipeline](pipelines.md) definition — a bundle of configuration that maps 1:1 to a use case. If you have multiple use cases (e.g. personalization and continual learning), create separate groups for each. + +Each project can have multiple named groups, but most use cases only need the `default` group. + +## What groups provide + +- A stable UUID identifier for the pipeline configuration +- Topic definitions that control what gets extracted +- Pipeline steps that define the processing flow +- Topic name isolation — different groups can have topics with the same name without collision (e.g. two agents can each have a `user_preferences` topic in separate groups) + +## Default groups + +When you create a project, Engram sets up two default groups: + +- **`default_personalisation`** — [User-scoped](scopes.md). Requires a `user_id` when storing and searching. Use this for per-user preferences, facts, and context. +- **`default_continual_learning`** — Project-wide. No `user_id` needed. Use this for things an agent learns about how to perform a task, regardless of which user it's working with. + +## When to create additional groups + +Create additional groups when you have distinct use cases that need different topic definitions or pipeline configurations. For example, a customer support agent might have one group for tracking user preferences and another for learning resolution patterns. + +## Examples + +A **customer support agent** could use two groups: + +- **`default_personalisation`** (user-scoped) — Stores per-user facts like "prefers email over phone" or "has a Pro subscription". Requires a `user_id` on every store and search so each user's memories stay separate. +- **`default_continual_learning`** (project-wide) — Stores knowledge the agent learns about how to do its job, like "always check the billing FAQ before escalating refund requests". No `user_id` needed — these memories are shared across all users. + +When the agent handles a support ticket, it searches the personalization group with the user's ID to recall their history, and searches the continual learning group to recall best practices. + +A **multi-product company** might create a separate group per product: + +- **`product_a_support`** — Topics and pipeline tuned for Product A (e.g. topics like `"known_issues"`, `"feature_requests"`) +- **`product_b_support`** — Different topics for Product B, possibly with a different pipeline configuration + +This keeps topic names isolated — both groups can have a `"known_issues"` topic without collision — and lets each product team configure extraction independently. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/index.md b/docs/engram/concepts/index.md new file mode 100644 index 000000000..217f3e54e --- /dev/null +++ b/docs/engram/concepts/index.md @@ -0,0 +1,35 @@ +--- +title: Concepts +sidebar_position: 2 +description: "Core concepts in Engram: memories, topics, groups, scoping, pipelines, retrieval types, and runs." +--- + +Engram organizes and processes memories for your AI applications. Here's how the core concepts work together. + +| Concept | Description | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Memories](memories.md) | Discrete pieces of information stored in Engram, automatically embedded as vectors for semantic search. | +| [Groups](groups.md) | A named configuration bundle. Each group contains topics (what to remember) and a pipeline (how to process). Most projects start with a single group. | +| [Topics](topics.md) | A category of memory within a group. Each topic defines what kind of information to extract, like `UserKnowledge` or `ConversationSummary`. | +| [Scopes](scopes.md) | Controls memory visibility. Every memory belongs to a project. Topics can additionally require a user ID (user-scoped) or conversation ID (conversation-scoped). | +| [Input data types](input-data-types.md) | The three content formats Engram accepts: `string`, `pre-extracted`, and `conversation`. | +| [Pipelines](pipelines.md) | The processing flow that turns raw input into stored memories. Steps include extracting facts, transforming with context, and committing to storage. _Will be configurable in the future._ | +| [Search](search.md) | Search retrieval strategies for finding memories: vector, BM25, and hybrid. | + +## How concepts relate + +Below is an overview of Engram's key concepts and how they relate to each other: + +![Weaviate Engram Concepts](../_includes/concepts.png "Weaviate Engram Concepts") + +- You send [**input data**](input-data-types.md) (text, a conversation, or pre-extracted facts) along with [**scope**](scopes.md) parameters (`user_id`, `conversation_id`) that identify who the memories belong to. +- The input is routed to a [**group**](groups.md), which bundles [**topics**](topics.md) with a [**pipeline**](pipelines.md) — one group per use case. +- **Topics** tell the pipeline what kinds of information to extract (e.g. `UserKnowledge`, `ConversationSummary`) and which **scopes** are required. +- The **pipeline** extracts facts from the input, deduplicates and merges them with existing data, and commits the results to storage. +- The output is a set of [**memories**](memories.md) — vector-embedded, categorized by topic, and isolated by scope so each user's data stays separate. + +## Questions and feedback + +import DocsFeedback from '/\_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/input-data-types.md b/docs/engram/concepts/input-data-types.md new file mode 100644 index 000000000..ba81942ce --- /dev/null +++ b/docs/engram/concepts/input-data-types.md @@ -0,0 +1,31 @@ +--- +title: Input data types +sidebar_position: 5 +description: "The three content types Engram accepts: string, pre-extracted, and conversation." +--- + +Engram accepts three types of input content when storing memories: + +| Type | Description | Use case | +|------|-------------|----------| +| `string` | Raw text | Free-form notes, agent observations | +| `pre_extracted` | Already-structured content | When you've done your own extraction | +| `conversation` | Multi-turn messages with roles | Chat transcripts, agent conversations | + +## String + +Send raw text and let Engram's [pipeline](pipelines.md) extract structured memories from it. This is the simplest input type — suitable for free-form notes, agent observations, or any unstructured text. + +## Pre-extracted + +Send already-structured content when you've done your own extraction or want to bypass Engram's extraction step. The content is passed through directly to the transform and commit stages. + +## Conversation + +Send multi-turn messages with roles (e.g. `user`, `assistant`) for chat transcripts and agent conversations. The pipeline uses conversation-aware extraction to pull memories from the dialogue context. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/memories.md b/docs/engram/concepts/memories.md new file mode 100644 index 000000000..16b8a8f64 --- /dev/null +++ b/docs/engram/concepts/memories.md @@ -0,0 +1,28 @@ +--- +title: Memories +sidebar_position: 1 +description: "What memories are in Engram: content, topic, group, scope, and vector embeddings." +--- + +A memory is a discrete piece of information stored in Engram. Each memory has: + +| Field | Description | +|-------|-------------| +| `id` | Unique identifier for the memory | +| `content` | The text of the memory (e.g. "The user prefers dark mode") | +| [`topic`](topics.md) | The category it belongs to (e.g. `UserKnowledge`) | +| [`group`](groups.md) | The memory group that defines how it was processed | +| `project_id` | The project this memory belongs to | +| [`user_id`](scopes.md) | The user this memory is scoped to (if user-scoped) | +| [`conversation_id`](scopes.md) | The conversation this memory is scoped to (if conversation-scoped) | +| `created_at` | When the memory was created (RFC 3339) | +| `updated_at` | When the memory was last updated (RFC 3339) | +| `score` | Relevance score (only present in search results) | + +Memories are automatically embedded as vectors, making them [searchable by meaning](search.md). + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/pipelines.md b/docs/engram/concepts/pipelines.md new file mode 100644 index 000000000..a248099bc --- /dev/null +++ b/docs/engram/concepts/pipelines.md @@ -0,0 +1,47 @@ +--- +title: Pipelines and runs +sidebar_position: 6 +description: "Engram's async processing pipelines: extract, transform, and commit steps, plus run tracking." +--- + +When you send content to Engram, it runs through an asynchronous pipeline that extracts, transforms, and commits memories. Pipelines are defined as a directed acyclic graph (DAG) of steps — different [input content types](input-data-types.md) enter the DAG at different extraction steps, but downstream steps like transform and commit are shared. + +:::info Pipeline configuration + +Pipelines will be configurable in the future. + +::: + +## Pipeline steps + +Each pipeline is a DAG with multiple entrypoints — one per content type — that converge into shared downstream steps: + +1. **Extract** — The entrypoint into the pipeline. Each [content type](input-data-types.md) has its own extraction step (`ExtractFromString`, `ExtractFromConversation`, or `ExtractFromPreExtracted`), but they all feed into the same downstream transform and commit steps. +2. **Transform** — Refines extracted memories using existing context. Steps like `TransformWithContext` and `TransformOperations` deduplicate, merge, and resolve conflicts with existing memories. +3. **Buffer** — Pauses the pipeline and accumulates memories until a trigger fires (e.g. a time interval). Buffers can appear anywhere in the pipeline, not just at the start. Memories from different content types that route into the same buffer are aggregated together. +4. **Commit** — Finalizes the operations (create, update, delete) and persists them to storage. + +A pipeline can chain these steps in different ways. For example, a pipeline for aggregated daily summaries might look like: + +`[extract] → [transform] → [commit] → [buffer] → [transform] → [commit]` + +In this case, memories are immediately extracted, transformed, and committed. They then enter a buffer that accumulates all memories added with the same [scope](scopes.md) (user or conversation). When the buffer triggers (e.g. after 24 hours), the accumulated batch continues through a second transform step — which could combine everything into a single "daily activity" memory — followed by a second commit. + +## Runs + +Each call to [store memories](../guides/store-memories.md) creates a **run** — a trackable unit of pipeline execution. Runs have four possible states: + +| Status | Meaning | +|--------|---------| +| `running` | Pipeline is actively processing | +| `in_buffer` | Run is paused at a buffer step, waiting for a trigger to continue | +| `completed` | All operations committed successfully | +| `failed` | An error occurred during processing | + +When a run completes, its [`committed_operations`](../guides/check-run-status.md) field shows exactly which memories were created, updated, or deleted. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/scopes.md b/docs/engram/concepts/scopes.md new file mode 100644 index 000000000..37468ccd4 --- /dev/null +++ b/docs/engram/concepts/scopes.md @@ -0,0 +1,40 @@ +--- +title: Scopes +sidebar_position: 4 +description: "Engram's multi-level scoping system: project, user, and conversation isolation for memories." +--- + +Engram uses a multi-level scoping system to isolate memories: + +- **Project** — Always required. Every memory belongs to a project, identified by the API key. +- **User** — Required for user-scoped topics. Memories are strictly isolated between users. +- **Conversation** — Required when storing to conversation-scoped topics. Optional when searching (see below). + +Which scopes are required depends on the [topic](topics.md) configuration. + +## User-scoped topics + +User-scoped topics store memories that belong to an individual user, such as preferences or personal details. Memories are strictly isolated between users — a query for one `user_id` never returns another user's memories. Both storing and searching require the `user_id`. + +## Project-wide topics + +Topics that are not user-scoped are shared across the entire project. These are useful for procedural memory — things an agent learns about how to perform a task, regardless of which user it is working with. No `user_id` is needed for storing or searching. + +## Conversation-scoped topics + +Conversation-scoped topics associate memories with a specific conversation. When **storing**, you must provide the `conversation_id`. When **searching**, the `conversation_id` is optional: + +- **With `conversation_id`** — Returns only memories from that conversation (e.g. to get a summary of a specific chat). +- **Without `conversation_id`** — Returns memories across all conversations (e.g. to find everything a user has discussed). + +Conversation-scoped topics are typically also user-scoped (e.g. conversation summaries are private to a user). + +## Multiple topics in one request + +A single request can interact with multiple topics. When it does, the required scope parameters are the union of each topic's requirements. For example, if one topic requires `user_id` and another requires `conversation_id`, the request must include both. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/search.md b/docs/engram/concepts/search.md new file mode 100644 index 000000000..316a69079 --- /dev/null +++ b/docs/engram/concepts/search.md @@ -0,0 +1,21 @@ +--- +title: Search +sidebar_position: 7 +description: "Engram search retrieval types: vector, BM25, and hybrid search strategies." +--- + +Engram supports three search strategies for finding relevant memories: + +| Type | Description | Best for | +|------|-------------|----------| +| `vector` | Pure semantic search using embeddings | Finding conceptually related memories | +| `bm25` | Full-text keyword search | Exact term matching | +| `hybrid` | Combination of vector and BM25 | General-purpose search (recommended) | + +You specify the search retrieval type in the `retrieval_config` when [searching](../guides/search-memories.md). + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/concepts/topics.md b/docs/engram/concepts/topics.md new file mode 100644 index 000000000..0baf34ce7 --- /dev/null +++ b/docs/engram/concepts/topics.md @@ -0,0 +1,47 @@ +--- +title: Topics +sidebar_position: 3 +description: "Topics in Engram: named categories within a group that control extraction and scoping." +--- + +Topics are named categories within a [group](groups.md). They tell Engram what kinds of information to extract and how to scope it. + +Each topic has: + +| Property | Description | +|----------|-------------| +| `name` | Unique identifier within the group (e.g. `user_facts`) | +| `description` | Natural language description used in LLM prompts during extraction (e.g. "What food the user likes to eat") | + +The topic `description` is important — it's what the extraction [pipeline](pipelines.md) uses to decide how to categorize information. For example, a travel agent might have separate topics with descriptions like "The places the user would like to visit" and "What food the user likes to eat" so the pipeline can route extracted facts to the right topic. + +:::info + +Topics are defined at project creation time as part of a group's configuration. When you create a project, Engram sets up a default group with a default topic automatically. To use custom topics, define them in the group configuration when creating the project. + +::: + +## Examples + +A **travel agent** might define three topics within a single group: + +- `"destinations"` — description: *"Places the user wants to visit or has visited"* +- `"food_preferences"` — description: *"What food the user likes to eat"* +- `"travel_style"` — description: *"How the user prefers to travel (budget, luxury, solo, group)"* + +When a user says *"I love sushi and visit Tokyo every spring"*, the extraction pipeline reads each topic's description and routes the facts accordingly — "loves sushi" goes to `food_preferences` and "visits Tokyo every spring" goes to `destinations`. + +At search time, you can restrict results to specific topics. Searching with `topics: ["food_preferences"]` only returns food-related memories, while omitting `topics` searches across all topics in the group. + +A **coding assistant** might use topics differently: + +- `"UserKnowledge"` — *"Anything relating to the user personally: their personal details, preferences, what they've done or plan to do"* +- `"tech_stack"` — *"Programming languages, frameworks, and libraries the user works with"* + +This lets the assistant retrieve just the user's tech stack when helping with a code review, or just their personal context when configuring a new environment. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/guides/check-run-status.md b/docs/engram/guides/check-run-status.md new file mode 100644 index 000000000..f248ca044 --- /dev/null +++ b/docs/engram/guides/check-run-status.md @@ -0,0 +1,108 @@ +--- +title: Check run status +sidebar_position: 4 +description: "How to poll pipeline run status and interpret committed operations in Engram." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/check_run_status.py'; +import CurlCode from '!!raw-loader!../_includes/check_run_status.sh'; + +When you [store memories](store-memories.md), Engram processes them asynchronously through a [pipeline](../concepts/pipelines.md). Each request returns a `run_id` that you can use to track progress. + +## Poll a run + + + + + + + + + + + + + + +### Response + +```json +{ + "run_id": "run-uuid", + "status": "completed", + "group_id": "group-uuid", + "user_id": "user-uuid", + "starting_step": 1, + "input_type": "string", + "committed_operations": { + "created": [ + { + "memory_id": "memory-uuid-1", + "committed_at": "2025-01-01T00:00:01Z" + } + ] + }, + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T00:00:01Z" +} +``` + +## Run statuses + +| Status | Meaning | +|--------|---------| +| `running` | Pipeline is actively processing the content | +| `in_buffer` | Run is paused at a buffer step, waiting for a trigger to continue | +| `completed` | All operations have been committed successfully | +| `failed` | An error occurred during processing | + +## Committed operations + +When a run completes, the `committed_operations` field tells you exactly what changed: + +- **`created`** — New memories that were added to storage. +- **`updated`** — Existing memories that were modified (e.g. merged or refined). +- **`deleted`** — Memories that were removed (e.g. superseded by an update). + +Each entry includes the `memory_id` and a `committed_at` timestamp. + +## Handling failures + +If a run fails, the `error` field contains a description of what went wrong. + +```json +{ + "run_id": "run-uuid", + "status": "failed", + "group_id": "group-uuid", + "user_id": "user-uuid", + "starting_step": 1, + "input_type": "string", + "error": "extraction failed: invalid input format", + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T00:00:01Z" +} +``` + +:::tip +In most cases, you don't need to poll for completion — memories are eventually consistent and will be available for search once the pipeline finishes. Check the initial response from `memories.add` to catch immediate errors. Use `runs.get` only when you need to confirm that a specific run has completed, such as during testing or debugging. +::: + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/guides/index.md b/docs/engram/guides/index.md new file mode 100644 index 000000000..af1094dfd --- /dev/null +++ b/docs/engram/guides/index.md @@ -0,0 +1,20 @@ +--- +title: Guides +sidebar_position: 3 +description: "Step-by-step guides for storing, searching, and managing memories in Engram." +--- + +These guides cover common Engram operations with detailed examples. + +## Available guides + +- **[Store memories](store-memories.md)** — Send string, pre-extracted, or conversation content to Engram. +- **[Search memories](search-memories.md)** — Query memories using vector, BM25, or hybrid search with filtering and scoping. +- **[Manage memories](manage-memories.md)** — Get and delete individual memories by ID. +- **[Check run status](check-run-status.md)** — Poll pipeline runs and interpret committed operations. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/guides/manage-memories.md b/docs/engram/guides/manage-memories.md new file mode 100644 index 000000000..bf4da4c7f --- /dev/null +++ b/docs/engram/guides/manage-memories.md @@ -0,0 +1,102 @@ +--- +title: Manage memories +sidebar_position: 3 +description: "How to get and delete individual memories in Engram by ID." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/manage_memories.py'; +import CurlCode from '!!raw-loader!../_includes/manage_memories.sh'; + +You can retrieve and delete individual [memories](../concepts/memories.md) using their ID. + +## Get a memory + +Retrieve a single memory by its ID. + + + + + + + + + + + + + + +### Query parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `user_id` | string | User [scope](../concepts/scopes.md) (required if the topic is user-scoped) | +| `conversation_id` | string | Conversation [scope](../concepts/scopes.md) (required if the topic is conversation-scoped) | +| `group` | string | The memory [group](../concepts/groups.md) name | + +### Response + +```json +{ + "id": "memory-uuid", + "project_id": "project-uuid", + "user_id": "user-uuid", + "content": "The user prefers dark mode.", + "topic": "UserKnowledge", + "group": "default", + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T00:00:00Z" +} +``` + +## Delete a memory + +Remove a memory permanently by its ID. + + + + + + + + + + + + + + +The query parameters are the same as for the get request. You must provide the correct scoping parameters to identify the memory. + +:::warning +Deleting a memory is permanent and cannot be undone. +::: + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/guides/search-memories.md b/docs/engram/guides/search-memories.md new file mode 100644 index 000000000..28648e9ad --- /dev/null +++ b/docs/engram/guides/search-memories.md @@ -0,0 +1,191 @@ +--- +title: Search memories +sidebar_position: 2 +description: "How to search memories in Engram using vector, BM25, and hybrid retrieval with filtering and scoping." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/search_memories.py'; +import CurlCode from '!!raw-loader!../_includes/search_memories.sh'; + +You can retrieve stored memories using different search techniques. + +## Basic search + +Provide a query and Engram returns the most relevant memories. + + + + + + + + + + + + + + +```json +{ + "memories": [ + { + "id": "memory-uuid", + "project_id": "project-uuid", + "user_id": "user-uuid", + "content": "The user works primarily in Python.", + "topic": "UserKnowledge", + "group": "default", + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T00:00:00Z", + "score": 0.89 + } + ], + "total": 1 +} +``` + +## Retrieval types + +Specify the [retrieval type](../concepts/search.md) in `retrieval_config`: + +### Vector search + +Pure semantic search using embeddings. Finds memories that are conceptually similar to your query, even without matching keywords. + + + + + + + + + + + + + + +### BM25 search + +Full-text keyword search. Best for finding memories that contain specific terms. + + + + + + + + + + + + + + +### Hybrid search + +Combines vector and BM25 for the best of both approaches. This is the recommended retrieval type for most use cases. + + + + + + + + + + + + + + +## Filter by topic + +Restrict your search to specific [topics](../concepts/topics.md) by providing a `topics` array. + + + + + + + + + + + + + + +If you omit `topics`, Engram searches across all topics in the group. + +## Scoping + +Search results are [scoped](../concepts/scopes.md) to match the parameters you provide: + +- **`user_id`** — Required for user-scoped topics. Only returns memories for this user. +- **`conversation_id`** — Optional for conversation-scoped topics. Include it to filter to a single conversation, or omit it to search across all conversations. +- **`group`** — Search within this group. Defaults to `default`. + +:::tip +For user-scoped topics, always include the `user_id` you used when storing the memories. For conversation-scoped topics, you can omit `conversation_id` to search across all conversations at once. +::: + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/guides/store-memories.md b/docs/engram/guides/store-memories.md new file mode 100644 index 000000000..26fb311d9 --- /dev/null +++ b/docs/engram/guides/store-memories.md @@ -0,0 +1,130 @@ +--- +title: Store memories +sidebar_position: 1 +description: "How to store memories in Engram using string, pre-extracted, or conversation content types." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/store_memories.py'; +import CurlCode from '!!raw-loader!../_includes/store_memories.sh'; + +Engram supports three [content types](../concepts/input-data-types.md) for storing memories. Each content type is a different entrypoint into the same [pipeline](../concepts/pipelines.md). + +## String content + +Send raw text and let Engram extract structured memories from it. + + + + + + + + + + + + + + +The pipeline extracts individual facts from the text (e.g. "prefers dark mode", "works in Python") and stores them as separate memories. + +## Pre-extracted content + +If you've already extracted structured content, send it directly. This bypasses the LLM extraction step, but the content still passes through the transform and commit pipeline stages. + + + + + + + + + + + + + + +## Conversation content + +Send a multi-turn conversation and let Engram extract memories from the full exchange. + + + + + + + + + + + + + + +The pipeline analyzes the full conversation and extracts relevant facts (e.g. "lives in Berlin", "prefers specialty coffee"). + +## Response + +All three content types return the same response format: + +```json +{ + "run_id": "run-uuid", + "status": "running" +} +``` + +A successful response means the pipeline has started, not that the memories have been committed. Use the `run_id` to [check the pipeline status](check-run-status.md) and confirm when processing is complete. + +## Optional parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `user_id` | string | [Scope](../concepts/scopes.md) the memory to a specific user | +| `conversation_id` | string (UUID) | [Scope](../concepts/scopes.md) the memory to a specific conversation. Must be a valid UUID. | +| `group` | string | Memory [group](../concepts/groups.md) name (defaults to `default`) | +| `root` | string | Pipeline root name (for advanced pipeline configurations) | + +:::info +Which parameters are required depends on the topic's [scoping](../concepts/scopes.md) configuration, not the content type. If a topic is user-scoped, you must include `user_id`. If a topic is conversation-scoped, you must include `conversation_id` when storing (it is optional when searching). These scoping parameters apply equally to all three content types — for example, you can include `conversation_id` with string content, or omit it with conversation content, depending on the topic configuration. +::: + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/index.md b/docs/engram/index.md new file mode 100644 index 000000000..1bd6a52c8 --- /dev/null +++ b/docs/engram/index.md @@ -0,0 +1,48 @@ +--- +title: Engram +sidebar_label: Introduction +sidebar_position: 0 +description: "Engram is a memory server for LLM agents and applications that provides persistent, semantically searchable memory through a REST API." +--- + +Engram is a memory server for LLM agents and applications. It provides a [REST API](/engram/api/rest) and [Python SDK](https://github.com/weaviate/engram-python-sdk) that automatically extracts, transforms, and stores memories using vector embeddings and LLM-powered processing. + +Use Engram to give your agents persistent memory that they can write to and search across conversations, users, and [topics](concepts/topics.md). + +## Key capabilities + +- **Automatic memory extraction** — Send raw text, pre-extracted facts, or full conversations. Engram's [pipeline](concepts/pipelines.md) extracts and stores structured [memories](concepts/memories.md) automatically. +- **Semantic search** — Find relevant memories using vector similarity, BM25 keyword search, or [hybrid retrieval](concepts/search.md). +- **Scoped memory** — Organize memories by project, user, and conversation. [Topics](concepts/topics.md) let you categorize memories within a [group](concepts/groups.md) (e.g. `UserKnowledge`, `ConversationSummary`). +- **Async processing** — Memory storage runs asynchronously through a pipeline. Poll [run status](guides/check-run-status.md) to track when memories are committed. + +## How it works + +Below is an overview of Engram's architecture and information flow: + +![Weaviate Engram](./_includes/architecture.png "Weaviate Engram") + +Your app communicates with Engram through the REST API or Python SDK. + +**[Storing memories](guides/store-memories.md):** You send content (text, a conversation, or pre-extracted facts) to the API. Engram immediately returns a `run_id` and processes the content asynchronously through a [pipeline](concepts/pipelines.md): + +1. **Extract** — Pull individual facts from the input. +2. **Transform** — Deduplicate and merge with existing [memories](concepts/memories.md). +3. **Commit** — Persist the results to the memory store. + +You can poll the [`run_id`](guides/check-run-status.md) to check when processing is complete. + +**[Searching memories](guides/search-memories.md):** You send a query to the API with a [retrieval type](concepts/search.md) (vector, BM25, or hybrid). Engram searches the memory store and returns ranked results. + +## Get started + +- **[Quickstart](quickstart.md)** — Create a project, get an API key, store your first memory, and search it. +- **[Concepts](concepts/index.md)** — Understand memories, topics, groups, scoping, and pipelines. +- **[Guides](guides/index.md)** — Step-by-step instructions for storing, searching, and managing memories. +- **[REST API reference](/engram/api/rest)** — Full endpoint documentation with request and response schemas. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/quickstart.md b/docs/engram/quickstart.md new file mode 100644 index 000000000..3e4fa9ef5 --- /dev/null +++ b/docs/engram/quickstart.md @@ -0,0 +1,274 @@ +--- +title: Quickstart +sidebar_position: 1 +description: "Get started with Engram by creating a project, generating an API key, storing a memory, and searching it." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!./_includes/quickstart.py'; +import CurlCode from '!!raw-loader!./_includes/quickstart.sh'; + +Engram is a memory server for LLM agents and applications. It automatically extracts, transforms, and stores memories using vector embeddings and LLM-powered processing. + +This guide walks you through the core Engram workflow: create a project, get an API key, store a memory, and search for it. + +## Prerequisites + +- A [Weaviate Cloud](https://console.weaviate.cloud) account +- `curl` or install the [Python SDK](https://pypi.org/project/weaviate-engram/): + + + + +```bash +pip install weaviate-engram +``` + + + + +```bash +uv add weaviate-engram +``` + + + + +## Step 1: Create a project + +Every memory in Engram belongs to a project. Create one in the [Weaviate Cloud console](https://console.weaviate.cloud). + +You can select a predefined template when creating a project. For this tutorial, use the **Personalization template**. + +The template provides you with a default [group](concepts/groups.md) called `personalization` and a default [topic](concepts/topics.md) called `UserKnowledge` (description: *"Anything relating to the user personally: their personal details (name, age, interpersonal relationships, etc.), their preferences, what they've done or plan to do, etc., i.e., any generic information about the user."*). This is enough to get started. + +The template also lets you optionally add a `ConversationSummary` topic, which maintains a single summary for each conversation ID containing the entire history of that conversation. Enabling this option makes `conversation_id` required when adding memories, which is why it's disabled by default. + +
+ +Concepts to learn + +Here are the key concepts: + +- **[Topics](concepts/topics.md)** — Named categories that control what kinds of information Engram extracts. The topic's description guides the LLM during extraction. +- **[Groups](concepts/groups.md)** — Containers of topics. Each group maps to a use case (e.g. personalization, continual learning). +- **[Scopes](concepts/scopes.md)** — Control who memories belong to. The default topic `UserKnowledge` is user-scoped, meaning you must provide a `user_id` so each user's memories stay separate. + +Visit the [concepts section](concepts/index.md) to learn more about how these work together. + +
+ +## Step 2: Create an API key + +Generate an API key for your project in the Weaviate Cloud console. The full key is only shown once — save it securely. + + +Set it as an environment variable for the examples below: + +```bash +export ENGRAM_API_KEY="eng_abcdef123456..." +``` + +:::warning + +Copy and store the API key immediately. You cannot retrieve it again after it is displayed. + +::: + +## Step 3: Connect to Engram + + + + +Initialize the client with your API key. + + + + + + +All `curl` commands authenticate via the `Authorization` header with a Bearer token: + +```bash +-H "Authorization: Bearer $ENGRAM_API_KEY" +``` + + + + +## Step 4: Store a memory + +Send content to Engram using the memory API. This example sends a plain text string. + + + + + + + + + + + + + +Engram processes memories asynchronously. The response includes a `run_id` you can use to check the pipeline status. + +
+ +Example response + +```json +{ + "run_id": "run-uuid", + "status": "running" +} +``` + +
+ +## Step 5: Check run status + +Poll the run endpoint to confirm your memory has been committed. + + + + + + + + + + + + + + +
+ +Example response + +```json +{ + "run_id": "run-uuid", + "status": "completed", + "group_id": "group-uuid", + "user_id": "user-uuid", + "starting_step": 1, + "input_type": "string", + "committed_operations": { + "created": [ + { + "memory_id": "memory-uuid", + "committed_at": "2025-01-01T00:00:01Z" + } + ] + }, + "created_at": "2025-01-01T00:00:00Z", + "updated_at": "2025-01-01T00:00:01Z" +} +``` + +
+ +## Step 6: Search memories + +Search for relevant memories using a natural language query. + + + + + + + + + + + + + + +
+ +Example response + +```json +{ + "memories": [ + { + "id": "memory-uuid", + "project_id": "project-uuid", + "user_id": "user-uuid", + "content": "The user prefers dark mode.", + "topic": "UserKnowledge", + "group": "default", + "created_at": "2025-01-01T00:00:01Z", + "updated_at": "2025-01-01T00:00:01Z", + "score": 1 + }, + { + "id": "memory-uuid-2", + "project_id": "project-uuid", + "user_id": "user-uuid", + "content": "The user uses VS Code as their primary editor.", + "topic": "UserKnowledge", + "group": "default", + "created_at": "2025-01-01T00:00:01Z", + "updated_at": "2025-01-01T00:00:01Z", + "score": 1 + } + ], + "total": 2 +} +``` + +
+ +## Next steps + +- Learn about [core concepts](concepts/index.md) like topics, groups, and pipelines. +- Explore different ways to [store memories](guides/store-memories.md), including conversations and pre-extracted data. +- See all [search options](guides/search-memories.md) including vector, BM25, and hybrid retrieval. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/tutorials/context-window-management.md b/docs/engram/tutorials/context-window-management.md new file mode 100644 index 000000000..790d73d89 --- /dev/null +++ b/docs/engram/tutorials/context-window-management.md @@ -0,0 +1,171 @@ +--- +title: "Context Window Management" +sidebar_position: 2 +description: "Reduce LLM token usage and cost by replacing full conversation history with Engram memory search." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/tutorial_context_window_mgmt.py'; + +Every time you call an LLM, you pay for every token in the request — including the full conversation history. As conversations grow, so does your cost and latency. A 50-turn conversation can easily exceed 10,000 input tokens per request. + +Engram solves this by extracting discrete facts from conversations and storing them as searchable memories. Instead of sending the entire history, you search for relevant memories and send only those — keeping context size flat regardless of conversation length. + +This tutorial builds on the [Memory Chat App](memory-chat-app.md) pattern and shows you how to: +- Measure the token cost of sending full conversation history +- Replace history with memory search for constant-size context +- Compare the two approaches side-by-side + +## Prerequisites + +- An Engram project with an API key ([Quickstart](../quickstart.md)) +- An [Anthropic](https://console.anthropic.com/) or [OpenAI](https://platform.openai.com/) API key +- Python packages: `pip install weaviate-engram anthropic openai` + +## Step 1: The naive approach + +The most common pattern is to append every message to a list and send the full list with each API call. This works for short conversations but becomes expensive fast. + + + + + + + + + + + + + + +The `messages` list grows by two entries every turn (user + assistant). By turn 50, you're sending 100 messages in every request. Token usage grows linearly with the naive approach and you're paying for the same messages over and over. Turn 1's messages are re-sent at turn 2, 3, 4, and every subsequent turn. + +## Step 2: Store conversations as memories + +Instead of keeping messages in a growing list, send them to Engram after each exchange. Engram extracts discrete facts and stores them as searchable memories. + + + +From a 6-message conversation, Engram might extract memories like: +- "The user is a software engineer" +- "The user works primarily in Python" +- "The user uses FastAPI with PostgreSQL" +- "The user prefers async patterns" +- "The user uses Redis for caching and Celery for background tasks" + +Each fact is stored once and retrieved only when relevant. + +## Step 3: Replace history with memory search + +Instead of sending the full conversation history, search Engram for relevant memories and keep only the last 2-3 exchanges for conversational continuity. + + + + + + + + + + + + + + +The context window now contains: +- **System prompt**: ~5 retrieved memories (~50 tokens) +- **Recent messages**: Last 2-3 exchanges (~4-6 messages, ~500-750 tokens) +- **Total**: ~800 tokens — flat, regardless of conversation length + +## Step 4: Compare side-by-side + +Here's a comparison of token usage as conversation length grows: + +```text +Turn Naive (tokens) Memory (tokens) Savings +---------------------------------------------------------- +1 125 175 -40% +5 625 425 32% +10 1,250 425 66% +20 2,500 425 83% +50 6,250 425 93% +``` + +At turn 1, the memory approach has slight overhead from the search. By turn 10, it saves 66%. By turn 50, it saves 93% of input tokens. + +## Step 5: Advanced patterns + +### Topic filtering + +If your project has multiple topics, filter search results to specific topics for more precise retrieval: + + + +### Hybrid search tuning + +Adjust the `retrieval_config` to control how memories are ranked: + +```python +# Pure semantic search — best for conceptual similarity +RetrievalConfig(retrieval_type="vector", limit=5) + +# Keyword search — best for exact terms +RetrievalConfig(retrieval_type="bm25", limit=5) + +# Hybrid (recommended) — combines both approaches +RetrievalConfig(retrieval_type="hybrid", limit=10) +``` + +### Dual-memory pattern + +For the best balance of continuity and context, combine both approaches: + +1. **Recent messages** (last 2-3 exchanges) — Maintains conversational flow +2. **Engram memory search** — Provides relevant historical context + +This is the pattern used in Step 4. The recent messages handle references like "that" and "it", while Engram provides the long-term context that makes the assistant feel like it truly remembers. + +## Next steps + +- **[Memory Chat App](memory-chat-app.md)** — The foundational tutorial for integrating Engram with a chat app. +- **[Personalized RAG](personalized-rag-multi-tenant.md)** — Add a knowledge base alongside per-user memory. +- **[Store memories](../guides/store-memories.md)** — Learn about all three content types (string, conversation, pre-extracted). + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/tutorials/index.md b/docs/engram/tutorials/index.md new file mode 100644 index 000000000..ff66dc1f8 --- /dev/null +++ b/docs/engram/tutorials/index.md @@ -0,0 +1,19 @@ +--- +title: Tutorials +sidebar_position: 4 +description: "End-to-end tutorials for building AI applications with Engram memory." +--- + +These tutorials walk you through building real AI applications with Engram, from a simple memory-enabled chatbot to a production-ready personalized RAG system. + +## Available tutorials + +- **[Memory Chat App](memory-chat-app.md)** — Add long-term memory to a chatbot using Anthropic or OpenAI. +- **[Context Window Management](context-window-management.md)** — Replace growing conversation history with memory search to reduce token usage and cost. +- **[Personalized RAG with Multi-Tenant Memory](personalized-rag-multi-tenant.md)** — Combine a Weaviate knowledge base with per-user Engram memory for personalized, isolated responses. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/tutorials/memory-chat-app.md b/docs/engram/tutorials/memory-chat-app.md new file mode 100644 index 000000000..c463dd192 --- /dev/null +++ b/docs/engram/tutorials/memory-chat-app.md @@ -0,0 +1,166 @@ +--- +title: "Add Long-Term Memory to a Chat App" +sidebar_position: 1 +description: "Build a chatbot with persistent memory across sessions using Engram with Anthropic or OpenAI." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/tutorial_memory_chat_app.py'; + +LLMs are stateless — every API call starts from scratch with no memory of past conversations. Engram adds persistent memory so your chatbot can remember user preferences, past discussions, and context across sessions. + +In this tutorial, you'll build a chat app that: +- Stores conversations as memories after each exchange +- Retrieves relevant memories before generating a response +- Personalizes responses based on what it remembers about the user + +## Prerequisites + +- An Engram project with an API key ([Quickstart](../quickstart.md)) +- An [Anthropic](https://console.anthropic.com/) or [OpenAI](https://platform.openai.com/) API key +- Python packages: `pip install weaviate-engram anthropic openai` + +Set your environment variables: + +```bash +export ENGRAM_API_KEY="eng_..." +export ANTHROPIC_API_KEY="sk-ant-..." # or OPENAI_API_KEY +``` + +## Step 1: Set up the Engram client + +Initialize the Engram client with your API key. The `user_id` parameter scopes all memories to a specific user, so different users get isolated memory stores. + + + +## Step 2: Create a chat completion function + +Create a helper function that sends messages to your LLM provider and returns the response. This function accepts a `system_prompt` parameter — you'll use it later to inject memory context. + + + + + + + + + + + + + + +## Step 3: Store conversations as memories + +After each conversation, send the messages to Engram. The pipeline extracts discrete facts (e.g. "lives in Berlin", "prefers specialty coffee") and stores them as individual memories. + + + +`memories.add()` accepts a list of message dicts with `role` and `content` keys — the same format used by Anthropic and OpenAI. The call returns immediately with a `run_id` — there's no need to wait for the pipeline to complete before continuing. Memories are eventually consistent and will be available for search once processing finishes. + +This is fine in practice because memories are most useful across sessions or from much earlier in a conversation. The most recent messages are still in the LLM's context window, so you don't need to wait for them to be stored as memories before generating the next response. + +## Step 4: Retrieve relevant memories + +Before generating a response, search Engram for memories relevant to the user's current message. Format the results into a system prompt that gives the LLM context about the user. + + + +Hybrid search combines semantic similarity with keyword matching, so it finds relevant memories even when the wording doesn't match exactly. + +## Step 5: Build the full chat loop + +Here's the complete script that ties everything together. Each iteration of the loop: + +1. Searches Engram for memories relevant to the user's input +2. Builds a system prompt with the retrieved context +3. Sends the message to the LLM with memory-augmented context +4. Stores the new exchange as a memory for future retrieval + + + + + + + + + + + + + + +## Step 6: Test it + +Run the script and have a multi-turn conversation. Then stop and restart it — the assistant remembers context from the previous session. + +**Session 1:** + +```text +You: I just moved to Berlin and I'm looking for a good coffee shop. +Assistant: Welcome to Berlin! Here are some popular spots... + +You: I prefer specialty coffee, not chains. +Assistant: Great taste! For specialty coffee in Berlin, check out... + +You: quit +``` + +**Session 2 (after restart):** + +```text +You: Any new coffee recommendations? +Assistant: Since you mentioned preferring specialty coffee in Berlin, +I'd suggest checking out... +``` + +The assistant remembers the user's location and coffee preferences from the previous session because those facts were extracted and stored as memories in Engram. + +## Next steps + +- **[Context Window Management](context-window-management.md)** — Learn how memory search replaces full conversation history to reduce token costs. +- **[Personalized RAG](personalized-rag-multi-tenant.md)** — Combine a Weaviate knowledge base with per-user memory for personalized responses. +- **[Search memories](../guides/search-memories.md)** — Explore vector, BM25, and hybrid retrieval options. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docs/engram/tutorials/personalized-rag-multi-tenant.md b/docs/engram/tutorials/personalized-rag-multi-tenant.md new file mode 100644 index 000000000..5efd28baa --- /dev/null +++ b/docs/engram/tutorials/personalized-rag-multi-tenant.md @@ -0,0 +1,209 @@ +--- +title: "Personalized RAG with Per-User Memory" +sidebar_position: 3 +description: "Build a multi-tenant RAG application that combines a Weaviate knowledge base with per-user Engram memory for personalized responses." +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import FilteredTextBlock from '@site/src/components/Documentation/FilteredTextBlock'; +import PyCode from '!!raw-loader!../_includes/tutorial_personalized_rag.py'; + +Standard RAG retrieves the same documents for every user. But a Python developer and a JavaScript developer asking "How do I use the API?" should get different answers — tailored to their language, experience level, and preferences. + +This tutorial combines a **Weaviate knowledge base** (shared product documentation) with **Engram per-user memory** (individual preferences and context) to build a personalized, multi-tenant RAG assistant. + +You'll learn how to: +- Search both a knowledge base and user memory in parallel +- Build prompts that merge shared knowledge with personal context +- Isolate memory between users with `user_id` scoping +- Handle concurrent users with `AsyncEngramClient` +- Manage user data for privacy compliance + +## Prerequisites + +- An Engram project with an API key ([Quickstart](../quickstart.md)) +- A [Weaviate Cloud](https://console.weaviate.cloud) instance +- An [Anthropic](https://console.anthropic.com/) or [OpenAI](https://platform.openai.com/) API key +- Python packages: `pip install weaviate-engram weaviate-client anthropic openai` + +## Step 1: Set up both clients + +Initialize the Engram client for user memory and the Weaviate client for your knowledge base. + + + +```python +import weaviate + +weaviate_client = weaviate.connect_to_weaviate_cloud( + cluster_url=os.environ["WEAVIATE_URL"], + auth_credentials=weaviate.auth.AuthApiKey(os.environ["WEAVIATE_API_KEY"]), +) +``` + +## Step 2: Populate the knowledge base + +Create a Weaviate collection with sample product documentation. This represents your shared knowledge base — the same docs are available to all users. + + + +## Step 3: Store user context in Engram + +Store different preferences and facts for different users. Engram extracts discrete facts and scopes them to each `user_id`. + + + +Alice and Bob now have separate memory stores. Alice's memories include facts like "Python developer" and "prefers concise examples", while Bob's include "JavaScript developer" and "prefers detailed explanations". + +## Step 4: Build the dual-search function + +Create a function that searches both the Weaviate knowledge base and Engram user memory. The knowledge base provides the factual content; Engram provides the personalization context. + + + +In production, you'd also search Weaviate here: + +```python +def dual_search(query, user_id, weaviate_collection): + # Search knowledge base + kb_results = weaviate_collection.query.hybrid(query=query, limit=5) + kb_docs = [obj.properties["content"] for obj in kb_results.objects] + + # Search user memory + user_memories = engram.memories.search( + query=query, user_id=user_id, group="default", + retrieval_config=RetrievalConfig(retrieval_type="hybrid", limit=5), + ) + + return {"knowledge_base": kb_docs, "user_memories": user_memories} +``` + +## Step 5: Construct a personalized prompt + +Merge the knowledge base results and user memories into a single prompt. The LLM uses the shared docs for accuracy and the user context for personalization. + + + + + + + + + + + + + + +With this prompt structure, the same question produces different responses: +- **Alice** gets a concise Python example using the SDK's async features +- **Bob** gets a detailed explanation with JavaScript/REST examples + +## Step 6: Demo with two users + +Both users ask the same question, but each gets a personalized response based on their stored context. + + + +Alice's search returns memories about Python and FastAPI. Bob's returns memories about JavaScript and React. The LLM uses this context to tailor its answer. + +## Step 7: Add user isolation + +Engram's `user_id` scoping ensures strict memory isolation. User A's memories are never returned when searching as User B, even if the query matches. + + + +Alice searching for "React dashboard JavaScript" finds nothing — those memories belong to Bob. And vice versa. This isolation is enforced at the storage layer, not just filtered in application code. + +:::info +User isolation is automatic when you use `user_id` with user-scoped topics. You don't need additional access control logic — Engram handles it. +::: + +## Step 8: Scale with async + +For production applications handling multiple concurrent users, switch to `AsyncEngramClient`. It uses the same API but supports `async`/`await` for non-blocking operations. + + + +Use `asyncio.gather()` to handle multiple user requests concurrently: + + + +Both searches run in parallel, reducing total latency compared to sequential calls. + +## Step 9: User data management + +For privacy compliance (e.g. GDPR right to deletion), you can retrieve and delete individual memories or all memories for a user. + + + +Use `memories.search()` to find all memories for a user, then `memories.delete()` each one. After deletion, subsequent searches return no results for that user. + +## Next steps + +- **[Memory Chat App](memory-chat-app.md)** — The foundational tutorial for integrating Engram with a chat app. +- **[Context Window Management](context-window-management.md)** — Reduce token costs by replacing conversation history with memory. +- **[Manage memories](../guides/manage-memories.md)** — API reference for get and delete operations. +- **[Core concepts](../concepts/index.md)** — Learn about topics, groups, scoping, and pipelines. + +## Questions and feedback + +import DocsFeedback from '/_includes/docs-feedback.mdx'; + + diff --git a/docusaurus.config.js b/docusaurus.config.js index a0340dfb9..949b5bb2b 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -60,6 +60,20 @@ const config = { }, }, ], + [ + "@scalar/docusaurus", + { + id: "engram-api", + label: "", + route: "/engram/api/rest", + configuration: { + spec: { + url: "/specs/engram-openapi.json", + }, + hideModels: true, + }, + }, + ], [ "@signalwire/docusaurus-plugin-llms-txt", { @@ -213,7 +227,7 @@ const config = { prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula, - additionalLanguages: ["java", "csharp"], + additionalLanguages: ["java", "csharp", "bash"], }, docs: { sidebar: { diff --git a/package.json b/package.json index 5952f11b1..faef31962 100644 --- a/package.json +++ b/package.json @@ -69,5 +69,6 @@ }, "engines": { "node": ">=18.0" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/pyproject.toml b/pyproject.toml index e39ede1e5..6b2f55f42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "weaviate-docs" version = "0.1.0" description = "Weaviate documentation test suite" readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.11" dependencies = [ "datasets>=4.0.0", "ijson>=3.3.0", @@ -15,4 +15,7 @@ dependencies = [ "weaviate-agents>=1.1.0", "weaviate-client>=4.19.0", "weaviate-demo-datasets>=0.7.0", + "weaviate-engram>=0.3.0", + "anthropic>=0.40.0", + "openai>=1.50.0", ] diff --git a/pytest.ini b/pytest.ini index 49b6f1f5e..7512d4703 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,6 +4,9 @@ norecursedirs = _* .github .idea* .pytest_cache .venv venv* blog developers down markers = pyv4: groups tests by language for v4 client only (python) agents: group tests for Weaviate Agents + engram: group tests for Weaviate Engram + engram_curl: group tests for Weaviate Engram using cURL + engram_python: group tests for Weaviate Engram using Python client ts: groups tests by language (typescript) java_v6: groups tests by language (java v6 client) csharp: groups tests by language (c#) diff --git a/secondaryNavbar.js b/secondaryNavbar.js index 54a3db3c9..8e450266a 100644 --- a/secondaryNavbar.js +++ b/secondaryNavbar.js @@ -107,6 +107,15 @@ const secondaryNavbarItems = { }, ], }, + engram: { + title: "Engram", + icon: "fa fa-brain", + description: "Persistent memory for LLM agents and applications", + link: "/engram", + links: [ + { label: "Documentation", link: "/engram", sidebar: "engramSidebar" }, + ], + }, integrations: { title: "Integrations", icon: "fa fa-puzzle-piece", diff --git a/sidebars.js b/sidebars.js index ffaee5946..d0c05bae1 100644 --- a/sidebars.js +++ b/sidebars.js @@ -1566,6 +1566,57 @@ const sidebars = { "cloud/platform/multi-factor-auth", "cloud/platform/users-and-organizations", ], + engramSidebar: [ + { type: "doc", id: "engram/index", label: "Introduction" }, + "engram/quickstart", + { + type: "category", + label: "Concepts", + link: { type: "doc", id: "engram/concepts/index" }, + collapsed: true, + items: [ + "engram/concepts/memories", + "engram/concepts/groups", + "engram/concepts/topics", + "engram/concepts/scopes", + "engram/concepts/input-data-types", + "engram/concepts/pipelines", + "engram/concepts/search", + ], + }, + { type: "html", value: "" }, + { + type: "category", + label: "Guides", + className: "sidebar-main-category", + collapsible: false, + link: { type: "doc", id: "engram/guides/index" }, + items: [ + "engram/guides/store-memories", + "engram/guides/search-memories", + "engram/guides/manage-memories", + "engram/guides/check-run-status", + ], + }, + { + type: "category", + label: "Tutorials", + className: "sidebar-main-category", + collapsible: false, + link: { type: "doc", id: "engram/tutorials/index" }, + items: [ + "engram/tutorials/memory-chat-app", + "engram/tutorials/context-window-management", + "engram/tutorials/personalized-rag-multi-tenant", + ], + }, + { type: "html", value: "" }, + { + type: "link", + label: "REST API reference", + href: "/engram/api/rest", + }, + ], }; module.exports = sidebars; diff --git a/src/theme/Navbar/hooks/useNavbarState.js b/src/theme/Navbar/hooks/useNavbarState.js index 3f828a2c3..3db3770e3 100644 --- a/src/theme/Navbar/hooks/useNavbarState.js +++ b/src/theme/Navbar/hooks/useNavbarState.js @@ -7,6 +7,14 @@ const DEFAULT_OPTION = Object.keys(secondaryNavOptions)[0]; const sidebars = require("/sidebars.js"); const routeBasePath = "/docs"; +// Fallback: match the URL path prefix against secondary nav option link paths. +// This handles pages not in any sidebar (e.g. /engram/api/rest). +function findOptionByPathPrefix(currentPath) { + return Object.entries(secondaryNavOptions).find( + ([, value]) => value.link && currentPath.startsWith(value.link.slice(1)) + ); +} + export default function useNavbarState(location) { // Compute the initial secondaryNavbar state based on the current location synchronously. const initialState = useMemo(() => { @@ -29,7 +37,10 @@ export default function useNavbarState(location) { const matchedOption = Object.entries(secondaryNavOptions).find( ([, value]) => value.links.some((link) => link.sidebar === foundSidebar) ); - const selectedOption = matchedOption ? matchedOption[0] : DEFAULT_OPTION; + // Fallback to path prefix matching for pages not in any sidebar (e.g. /engram/api/rest). + const selectedOption = matchedOption + ? matchedOption[0] + : (findOptionByPathPrefix(currentPath)?.[0] || DEFAULT_OPTION); return { selectedOption, activeLink: foundSidebar }; }, [location.pathname]); @@ -60,7 +71,10 @@ export default function useNavbarState(location) { const matchedOption = Object.entries(secondaryNavOptions).find( ([, value]) => value.links.some((link) => link.sidebar === foundSidebar) ); - setSelectedOption(matchedOption ? matchedOption[0] : DEFAULT_OPTION); + // Fallback to path prefix matching for pages not in any sidebar (e.g. /engram/api/rest). + setSelectedOption(matchedOption + ? matchedOption[0] + : (findOptionByPathPrefix(currentPath)?.[0] || DEFAULT_OPTION)); setActiveLink(foundSidebar); }, [location.pathname]); diff --git a/src/theme/Tabs/index.js b/src/theme/Tabs/index.js index 2a9cd5688..5b4835a6a 100644 --- a/src/theme/Tabs/index.js +++ b/src/theme/Tabs/index.js @@ -33,6 +33,13 @@ const LANGUAGE_CONFIG = { shell: { label: "Shell", icon: null }, }; +// Predefined docs URL overrides by product name +const DOCS_URL_PRESETS = { + engram: { + py: "https://github.com/weaviate/engram-python-sdk", + }, +}; + // Context for sharing selected language across all code dropdowns const CodeLanguageContext = React.createContext(); @@ -117,6 +124,7 @@ const CodeDropdownTabs = ({ groupId, defaultValue, values, + docsUrl, ...props }) => { // Get tab values and labels from children @@ -244,6 +252,8 @@ const CodeDropdownTabs = ({ } const docSystem = DOC_SYSTEMS[selectedValue]; + const resolvedDocsUrl = typeof docsUrl === "string" ? DOCS_URL_PRESETS[docsUrl] : docsUrl; + const overrideDocsUrl = resolvedDocsUrl && resolvedDocsUrl[selectedValue]; const currentUrl = typeof window !== "undefined" ? window.location.href : ""; const params = new URLSearchParams({ template: "doc_feedback.yml", @@ -264,10 +274,10 @@ const CodeDropdownTabs = ({ /> - {docSystem?.baseUrl && ( + {(overrideDocsUrl || docSystem?.baseUrl) && (
= '3.12'", - "python_full_version == '3.11.*'", - "python_full_version < '3.11'", + "python_full_version < '3.12'", ] [[package]] @@ -23,7 +22,6 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, { name = "aiosignal" }, - { name = "async-timeout", marker = "python_full_version < '3.11'" }, { name = "attrs" }, { name = "frozenlist" }, { name = "multidict" }, @@ -32,23 +30,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, - { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, - { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, - { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, - { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, @@ -167,12 +148,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anthropic" +version = "0.84.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "docstring-parser" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/ea/0869d6df9ef83dcf393aeefc12dd81677d091c6ffc86f783e51cf44062f2/anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37", size = 539457, upload-time = "2026-02-25T05:22:38.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/ca/218fa25002a332c0aa149ba18ffc0543175998b1f65de63f6d106689a345/anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7", size = 455156, upload-time = "2026-02-25T05:22:40.468Z" }, +] + [[package]] name = "anyio" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "idna" }, { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, @@ -182,15 +181,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, ] -[[package]] -name = "async-timeout" -version = "5.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, -] - [[package]] name = "attrs" version = "25.4.0" @@ -230,18 +220,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, @@ -284,19 +262,6 @@ version = "3.4.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" }, - { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" }, - { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" }, - { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" }, - { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" }, - { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" }, - { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" }, - { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" }, - { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" }, - { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" }, { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, @@ -393,12 +358,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f2/2e/e2dbd629481b499b14516eed933f3276eb3239f7cee2dcfa4ee6b44d4711/cryptography-45.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a", size = 4554189, upload-time = "2025-07-02T13:05:46.045Z" }, { url = "https://files.pythonhosted.org/packages/f8/ea/a78a0c38f4c8736287b71c2ea3799d173d5ce778c7d6e3c163a95a05ad2a/cryptography-45.0.5-cp37-abi3-win32.whl", hash = "sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f", size = 2911769, upload-time = "2025-07-02T13:05:48.329Z" }, { url = "https://files.pythonhosted.org/packages/79/b3/28ac139109d9005ad3f6b6f8976ffede6706a6478e21c889ce36c840918e/cryptography-45.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97", size = 3390016, upload-time = "2025-07-02T13:05:50.811Z" }, - { url = "https://files.pythonhosted.org/packages/f8/8b/34394337abe4566848a2bd49b26bcd4b07fd466afd3e8cce4cb79a390869/cryptography-45.0.5-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd", size = 3575762, upload-time = "2025-07-02T13:05:53.166Z" }, - { url = "https://files.pythonhosted.org/packages/8b/5d/a19441c1e89afb0f173ac13178606ca6fab0d3bd3ebc29e9ed1318b507fc/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097", size = 4140906, upload-time = "2025-07-02T13:05:55.914Z" }, - { url = "https://files.pythonhosted.org/packages/4b/db/daceb259982a3c2da4e619f45b5bfdec0e922a23de213b2636e78ef0919b/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e", size = 4374411, upload-time = "2025-07-02T13:05:57.814Z" }, - { url = "https://files.pythonhosted.org/packages/6a/35/5d06ad06402fc522c8bf7eab73422d05e789b4e38fe3206a85e3d6966c11/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30", size = 4140942, upload-time = "2025-07-02T13:06:00.137Z" }, - { url = "https://files.pythonhosted.org/packages/65/79/020a5413347e44c382ef1f7f7e7a66817cd6273e3e6b5a72d18177b08b2f/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e", size = 4374079, upload-time = "2025-07-02T13:06:02.043Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c5/c0e07d84a9a2a8a0ed4f865e58f37c71af3eab7d5e094ff1b21f3f3af3bc/cryptography-45.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d", size = 3321362, upload-time = "2025-07-02T13:06:04.463Z" }, { url = "https://files.pythonhosted.org/packages/c0/71/9bdbcfd58d6ff5084687fe722c58ac718ebedbc98b9f8f93781354e6d286/cryptography-45.0.5-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e", size = 3587878, upload-time = "2025-07-02T13:06:06.339Z" }, { url = "https://files.pythonhosted.org/packages/f0/63/83516cfb87f4a8756eaa4203f93b283fda23d210fc14e1e594bd5f20edb6/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6", size = 4152447, upload-time = "2025-07-02T13:06:08.345Z" }, { url = "https://files.pythonhosted.org/packages/22/11/d2823d2a5a0bd5802b3565437add16f5c8ce1f0778bf3822f89ad2740a38/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18", size = 4386778, upload-time = "2025-07-02T13:06:10.263Z" }, @@ -418,8 +377,7 @@ dependencies = [ { name = "httpx" }, { name = "huggingface-hub" }, { name = "multiprocess" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, { name = "pyarrow" }, @@ -455,15 +413,21 @@ wheels = [ ] [[package]] -name = "exceptiongroup" -version = "1.3.0" +name = "distro" +version = "1.9.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } + +[[package]] +name = "docstring-parser" +version = "0.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, ] [[package]] @@ -481,22 +445,6 @@ version = "1.8.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, - { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, - { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, - { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, - { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, - { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, - { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, - { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, - { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, - { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, - { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, - { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, @@ -616,16 +564,6 @@ version = "1.74.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/38/b4/35feb8f7cab7239c5b94bd2db71abb3d6adb5f335ad8f131abb6060840b6/grpcio-1.74.0.tar.gz", hash = "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1", size = 12756048, upload-time = "2025-07-24T18:54:23.039Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/54/68e51a90797ad7afc5b0a7881426c337f6a9168ebab73c3210b76aa7c90d/grpcio-1.74.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907", size = 5481935, upload-time = "2025-07-24T18:52:43.756Z" }, - { url = "https://files.pythonhosted.org/packages/32/2a/af817c7e9843929e93e54d09c9aee2555c2e8d81b93102a9426b36e91833/grpcio-1.74.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb", size = 10986796, upload-time = "2025-07-24T18:52:47.219Z" }, - { url = "https://files.pythonhosted.org/packages/d5/94/d67756638d7bb07750b07d0826c68e414124574b53840ba1ff777abcd388/grpcio-1.74.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:e154d230dc1bbbd78ad2fdc3039fa50ad7ffcf438e4eb2fa30bce223a70c7486", size = 5983663, upload-time = "2025-07-24T18:52:49.463Z" }, - { url = "https://files.pythonhosted.org/packages/35/f5/c5e4853bf42148fea8532d49e919426585b73eafcf379a712934652a8de9/grpcio-1.74.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8978003816c7b9eabe217f88c78bc26adc8f9304bf6a594b02e5a49b2ef9c11", size = 6653765, upload-time = "2025-07-24T18:52:51.094Z" }, - { url = "https://files.pythonhosted.org/packages/fd/75/a1991dd64b331d199935e096cc9daa3415ee5ccbe9f909aa48eded7bba34/grpcio-1.74.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3d7bd6e3929fd2ea7fbc3f562e4987229ead70c9ae5f01501a46701e08f1ad9", size = 6215172, upload-time = "2025-07-24T18:52:53.282Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/7cef3dbb3b073d0ce34fd507efc44ac4c9442a0ef9fba4fb3f5c551efef5/grpcio-1.74.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:136b53c91ac1d02c8c24201bfdeb56f8b3ac3278668cbb8e0ba49c88069e1bdc", size = 6329142, upload-time = "2025-07-24T18:52:54.927Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d3/587920f882b46e835ad96014087054655312400e2f1f1446419e5179a383/grpcio-1.74.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fe0f540750a13fd8e5da4b3eaba91a785eea8dca5ccd2bc2ffe978caa403090e", size = 7018632, upload-time = "2025-07-24T18:52:56.523Z" }, - { url = "https://files.pythonhosted.org/packages/1f/95/c70a3b15a0bc83334b507e3d2ae20ee8fa38d419b8758a4d838f5c2a7d32/grpcio-1.74.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4e4181bfc24413d1e3a37a0b7889bea68d973d4b45dd2bc68bb766c140718f82", size = 6509641, upload-time = "2025-07-24T18:52:58.495Z" }, - { url = "https://files.pythonhosted.org/packages/4b/06/2e7042d06247d668ae69ea6998eca33f475fd4e2855f94dcb2aa5daef334/grpcio-1.74.0-cp310-cp310-win32.whl", hash = "sha256:1733969040989f7acc3d94c22f55b4a9501a30f6aaacdbccfaba0a3ffb255ab7", size = 3817478, upload-time = "2025-07-24T18:53:00.128Z" }, - { url = "https://files.pythonhosted.org/packages/93/20/e02b9dcca3ee91124060b65bbf5b8e1af80b3b76a30f694b44b964ab4d71/grpcio-1.74.0-cp310-cp310-win_amd64.whl", hash = "sha256:9e912d3c993a29df6c627459af58975b2e5c897d93287939b9d5065f000249b5", size = 4493971, upload-time = "2025-07-24T18:53:02.068Z" }, { url = "https://files.pythonhosted.org/packages/e7/77/b2f06db9f240a5abeddd23a0e49eae2b6ac54d85f0e5267784ce02269c3b/grpcio-1.74.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31", size = 5487368, upload-time = "2025-07-24T18:53:03.548Z" }, { url = "https://files.pythonhosted.org/packages/48/99/0ac8678a819c28d9a370a663007581744a9f2a844e32f0fa95e1ddda5b9e/grpcio-1.74.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4", size = 10999804, upload-time = "2025-07-24T18:53:05.095Z" }, { url = "https://files.pythonhosted.org/packages/45/c6/a2d586300d9e14ad72e8dc211c7aecb45fe9846a51e558c5bca0c9102c7f/grpcio-1.74.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce", size = 5987667, upload-time = "2025-07-24T18:53:07.157Z" }, @@ -769,17 +707,6 @@ version = "3.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a3/4f/1cfeada63f5fce87536651268ddf5cca79b8b4bbb457aee4e45777964a0a/ijson-3.4.0.tar.gz", hash = "sha256:5f74dcbad9d592c428d3ca3957f7115a42689ee7ee941458860900236ae9bb13", size = 65782, upload-time = "2025-05-08T02:37:20.135Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/6b/a247ba44004154aaa71f9e6bd9f05ba412f490cc4043618efb29314f035e/ijson-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e27e50f6dcdee648f704abc5d31b976cd2f90b4642ed447cf03296d138433d09", size = 87609, upload-time = "2025-05-08T02:35:20.535Z" }, - { url = "https://files.pythonhosted.org/packages/3c/1d/8d2009d74373b7dec2a49b1167e396debb896501396c70a674bb9ccc41ff/ijson-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2a753be681ac930740a4af9c93cfb4edc49a167faed48061ea650dc5b0f406f1", size = 59243, upload-time = "2025-05-08T02:35:21.958Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b2/a85a21ebaba81f64a326c303a94625fb94b84890c52d9efdd8acb38b6312/ijson-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a07c47aed534e0ec198e6a2d4360b259d32ac654af59c015afc517ad7973b7fb", size = 59309, upload-time = "2025-05-08T02:35:23.317Z" }, - { url = "https://files.pythonhosted.org/packages/b1/35/273dfa1f27c38eeaba105496ecb54532199f76c0120177b28315daf5aec3/ijson-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c55f48181e11c597cd7146fb31edc8058391201ead69f8f40d2ecbb0b3e4fc6", size = 131213, upload-time = "2025-05-08T02:35:24.735Z" }, - { url = "https://files.pythonhosted.org/packages/4d/37/9d3bb0e200a103ca9f8e9315c4d96ecaca43a3c1957c1ac069ea9dc9c6ba/ijson-3.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd5669f96f79d8a2dd5ae81cbd06770a4d42c435fd4a75c74ef28d9913b697d", size = 125456, upload-time = "2025-05-08T02:35:25.896Z" }, - { url = "https://files.pythonhosted.org/packages/00/54/8f015c4df30200fd14435dec9c67bf675dff0fee44a16c084a8ec0f82922/ijson-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e3ddd46d16b8542c63b1b8af7006c758d4e21cc1b86122c15f8530fae773461", size = 130192, upload-time = "2025-05-08T02:35:27.367Z" }, - { url = "https://files.pythonhosted.org/packages/88/01/46a0540ad3461332edcc689a8874fa13f0a4c00f60f02d155b70e36f5e0b/ijson-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1504cec7fe04be2bb0cc33b50c9dd3f83f98c0540ad4991d4017373b7853cfe6", size = 132217, upload-time = "2025-05-08T02:35:28.545Z" }, - { url = "https://files.pythonhosted.org/packages/d7/da/8f8df42f3fd7ef279e20eae294738eed62d41ed5b6a4baca5121abc7cf0f/ijson-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2f2ff456adeb216603e25d7915f10584c1b958b6eafa60038d76d08fc8a5fb06", size = 127118, upload-time = "2025-05-08T02:35:29.726Z" }, - { url = "https://files.pythonhosted.org/packages/82/0a/a410d9d3b082cc2ec9738d54935a589974cbe54c0f358e4d17465594d660/ijson-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0ab00d75d61613a125fbbb524551658b1ad6919a52271ca16563ca5bc2737bb1", size = 129808, upload-time = "2025-05-08T02:35:31.247Z" }, - { url = "https://files.pythonhosted.org/packages/2e/c6/a3e2a446b8bd2cf91cb4ca7439f128d2b379b5a79794d0ea25e379b0f4f3/ijson-3.4.0-cp310-cp310-win32.whl", hash = "sha256:ada421fd59fe2bfa4cfa64ba39aeba3f0753696cdcd4d50396a85f38b1d12b01", size = 51160, upload-time = "2025-05-08T02:35:32.964Z" }, - { url = "https://files.pythonhosted.org/packages/18/7c/e6620603df42d2ef8a92076eaa5cd2b905366e86e113adf49e7b79970bd3/ijson-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:8c75e82cec05d00ed3a4af5f4edf08f59d536ed1a86ac7e84044870872d82a33", size = 53710, upload-time = "2025-05-08T02:35:34.033Z" }, { url = "https://files.pythonhosted.org/packages/1a/0d/3e2998f4d7b7d2db2d511e4f0cf9127b6e2140c325c3cb77be46ae46ff1d/ijson-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e369bf5a173ca51846c243002ad8025d32032532523b06510881ecc8723ee54", size = 87643, upload-time = "2025-05-08T02:35:35.693Z" }, { url = "https://files.pythonhosted.org/packages/e9/7b/afef2b08af2fee5ead65fcd972fadc3e31f9ae2b517fe2c378d50a9bf79b/ijson-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26e7da0a3cd2a56a1fde1b34231867693f21c528b683856f6691e95f9f39caec", size = 59260, upload-time = "2025-05-08T02:35:37.166Z" }, { url = "https://files.pythonhosted.org/packages/da/4a/39f583a2a13096f5063028bb767622f09cafc9ec254c193deee6c80af59f/ijson-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1c28c7f604729be22aa453e604e9617b665fa0c24cd25f9f47a970e8130c571a", size = 59311, upload-time = "2025-05-08T02:35:38.538Z" }, @@ -824,12 +751,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c5/9c/e09c7b9ac720a703ab115b221b819f149ed54c974edfff623c1e925e57da/ijson-3.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:eda4cfb1d49c6073a901735aaa62e39cb7ab47f3ad7bb184862562f776f1fa8a", size = 203816, upload-time = "2025-05-08T02:36:35.348Z" }, { url = "https://files.pythonhosted.org/packages/7c/14/acd304f412e32d16a2c12182b9d78206bb0ae35354d35664f45db05c1b3b/ijson-3.4.0-cp313-cp313t-win32.whl", hash = "sha256:0772638efa1f3b72b51736833404f1cbd2f5beeb9c1a3d392e7d385b9160cba7", size = 53760, upload-time = "2025-05-08T02:36:36.608Z" }, { url = "https://files.pythonhosted.org/packages/2f/24/93dd0a467191590a5ed1fc2b35842bca9d09900d001e00b0b497c0208ef6/ijson-3.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3d8a0d67f36e4fb97c61a724456ef0791504b16ce6f74917a31c2e92309bbeb9", size = 56948, upload-time = "2025-05-08T02:36:37.849Z" }, - { url = "https://files.pythonhosted.org/packages/a7/22/da919f16ca9254f8a9ea0ba482d2c1d012ce6e4c712dcafd8adb16b16c63/ijson-3.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:54e989c35dba9cf163d532c14bcf0c260897d5f465643f0cd1fba9c908bed7ef", size = 56480, upload-time = "2025-05-08T02:36:54.942Z" }, - { url = "https://files.pythonhosted.org/packages/6d/54/c2afd289e034d11c4909f4ea90c9dae55053bed358064f310c3dd5033657/ijson-3.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:494eeb8e87afef22fbb969a4cb81ac2c535f30406f334fb6136e9117b0bb5380", size = 55956, upload-time = "2025-05-08T02:36:56.178Z" }, - { url = "https://files.pythonhosted.org/packages/43/d6/18799b0fca9ecb8a47e22527eedcea3267e95d4567b564ef21d0299e2d12/ijson-3.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81603de95de1688958af65cd2294881a4790edae7de540b70c65c8253c5dc44a", size = 69394, upload-time = "2025-05-08T02:36:57.699Z" }, - { url = "https://files.pythonhosted.org/packages/c2/d6/c58032c69e9e977bf6d954f22cad0cd52092db89c454ea98926744523665/ijson-3.4.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8524be12c1773e1be466034cc49c1ecbe3d5b47bb86217bd2a57f73f970a6c19", size = 70378, upload-time = "2025-05-08T02:36:58.98Z" }, - { url = "https://files.pythonhosted.org/packages/da/03/07c6840454d5d228bb5b4509c9a7ac5b9c0b8258e2b317a53f97372be1eb/ijson-3.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17994696ec895d05e0cfa21b11c68c920c82634b4a3d8b8a1455d6fe9fdee8f7", size = 67770, upload-time = "2025-05-08T02:37:00.162Z" }, - { url = "https://files.pythonhosted.org/packages/32/c7/da58a9840380308df574dfdb0276c9d802b12f6125f999e92bcef36db552/ijson-3.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0b67727aaee55d43b2e82b6a866c3cbcb2b66a5e9894212190cbd8773d0d9857", size = 53858, upload-time = "2025-05-08T02:37:01.691Z" }, { url = "https://files.pythonhosted.org/packages/a3/9b/0bc0594d357600c03c3b5a3a34043d764fc3ad3f0757d2f3aae5b28f6c1c/ijson-3.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cdc8c5ca0eec789ed99db29c68012dda05027af0860bb360afd28d825238d69d", size = 56483, upload-time = "2025-05-08T02:37:03.274Z" }, { url = "https://files.pythonhosted.org/packages/00/1f/506cf2574673da1adcc8a794ebb85bf857cabe6294523978637e646814de/ijson-3.4.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8e6b44b6ec45d5b1a0ee9d97e0e65ab7f62258727004cbbe202bf5f198bc21f7", size = 55957, upload-time = "2025-05-08T02:37:04.865Z" }, { url = "https://files.pythonhosted.org/packages/dc/3d/a7cd8d8a6de0f3084fe4d457a8f76176e11b013867d1cad16c67d25e8bec/ijson-3.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b51e239e4cb537929796e840d349fc731fdc0d58b1a0683ce5465ad725321e0f", size = 69394, upload-time = "2025-05-08T02:37:06.142Z" }, @@ -847,6 +768,91 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "jiter" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, + { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, + { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, + { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, + { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, + { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, + { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, + { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, + { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, + { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" }, + { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" }, + { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" }, + { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" }, + { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" }, + { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" }, + { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" }, + { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" }, + { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" }, + { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" }, + { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, + { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -872,29 +878,8 @@ wheels = [ name = "multidict" version = "6.7.1" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, - { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, - { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, - { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, - { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, - { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, - { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, - { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, - { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, - { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, - { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, - { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, - { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, - { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, - { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, @@ -1015,9 +1000,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/72/fd/2ae3826f5be24c6ed87266bc4e59c46ea5b059a103f3d7e7eb76a52aeecb/multiprocess-0.70.18.tar.gz", hash = "sha256:f9597128e6b3e67b23956da07cf3d2e5cba79e2f4e0fba8d7903636663ec6d0d", size = 1798503, upload-time = "2025-04-17T03:11:27.742Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/f8/7f9a8f08bf98cea1dfaa181e05cc8bbcb59cecf044b5a9ac3cce39f9c449/multiprocess-0.70.18-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25d4012dcaaf66b9e8e955f58482b42910c2ee526d532844d8bcf661bbc604df", size = 135083, upload-time = "2025-04-17T03:11:04.223Z" }, - { url = "https://files.pythonhosted.org/packages/e5/03/b7b10dbfc17b2b3ce07d4d30b3ba8367d0ed32d6d46cd166e298f161dd46/multiprocess-0.70.18-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:06b19433de0d02afe5869aec8931dd5c01d99074664f806c73896b0d9e527213", size = 135128, upload-time = "2025-04-17T03:11:06.045Z" }, - { url = "https://files.pythonhosted.org/packages/c1/a3/5f8d3b9690ea5580bee5868ab7d7e2cfca74b7e826b28192b40aa3881cdc/multiprocess-0.70.18-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6fa1366f994373aaf2d4738b0f56e707caeaa05486e97a7f71ee0853823180c2", size = 135132, upload-time = "2025-04-17T03:11:07.533Z" }, { url = "https://files.pythonhosted.org/packages/55/4d/9af0d1279c84618bcd35bf5fd7e371657358c7b0a523e54a9cffb87461f8/multiprocess-0.70.18-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b8940ae30139e04b076da6c5b83e9398585ebdf0f2ad3250673fef5b2ff06d6", size = 144695, upload-time = "2025-04-17T03:11:09.161Z" }, { url = "https://files.pythonhosted.org/packages/17/bf/87323e79dd0562474fad3373c21c66bc6c3c9963b68eb2a209deb4c8575e/multiprocess-0.70.18-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0929ba95831adb938edbd5fb801ac45e705ecad9d100b3e653946b7716cb6bd3", size = 144742, upload-time = "2025-04-17T03:11:10.072Z" }, { url = "https://files.pythonhosted.org/packages/dd/74/cb8c831e58dc6d5cf450b17c7db87f14294a1df52eb391da948b5e0a0b94/multiprocess-0.70.18-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4d77f8e4bfe6c6e2e661925bbf9aed4d5ade9a1c6502d5dfc10129b9d1141797", size = 144745, upload-time = "2025-04-17T03:11:11.453Z" }, @@ -1029,79 +1011,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6c/28/dd72947e59a6a8c856448a5e74da6201cb5502ddff644fbc790e4bd40b9a/multiprocess-0.70.18-py39-none-any.whl", hash = "sha256:e78ca805a72b1b810c690b6b4cc32579eba34f403094bbbae962b7b5bf9dfcb8", size = 133478, upload-time = "2025-04-17T03:11:26.253Z" }, ] -[[package]] -name = "numpy" -version = "2.2.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, - { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, - { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, - { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, - { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, - { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, - { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, - { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, - { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, - { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, - { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, - { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, - { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, - { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, - { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, - { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, - { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, - { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, - { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, - { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, - { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, - { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, - { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, - { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, - { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, - { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, - { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, - { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, - { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, - { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, - { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, - { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, - { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, - { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, - { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, - { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, - { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, - { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, - { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, - { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, - { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, - { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, - { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, - { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, - { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, - { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, - { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, - { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, - { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, -] - [[package]] name = "numpy" version = "2.3.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.12'", - "python_full_version == '3.11.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/96/26/1320083986108998bd487e2931eed2aeedf914b6e8905431487543ec911d/numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", size = 21259016, upload-time = "2025-07-24T20:24:35.214Z" }, @@ -1179,6 +1092,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/e3/6690b3f85a05506733c7e90b577e4762517404ea78bab2ca3a5cb1aeb78d/numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", size = 12977811, upload-time = "2025-07-24T21:29:18.234Z" }, ] +[[package]] +name = "openai" +version = "2.24.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/13/17e87641b89b74552ed408a92b231283786523edddc95f3545809fab673c/openai-2.24.0.tar.gz", hash = "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673", size = 658717, upload-time = "2026-02-24T20:02:07.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/30/844dc675ee6902579b8eef01ed23917cc9319a1c9c0c14ec6e39340c96d0/openai-2.24.0-py3-none-any.whl", hash = "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94", size = 1120122, upload-time = "2026-02-24T20:02:05.669Z" }, +] + [[package]] name = "packaging" version = "25.0" @@ -1193,21 +1125,13 @@ name = "pandas" version = "2.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d1/6f/75aa71f8a14267117adeeed5d21b204770189c0a0025acbdc03c337b28fc/pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", size = 4487493, upload-time = "2025-07-07T19:20:04.079Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/ca/aa97b47287221fa37a49634532e520300088e290b20d690b21ce3e448143/pandas-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9", size = 11542731, upload-time = "2025-07-07T19:18:12.619Z" }, - { url = "https://files.pythonhosted.org/packages/80/bf/7938dddc5f01e18e573dcfb0f1b8c9357d9b5fa6ffdee6e605b92efbdff2/pandas-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1", size = 10790031, upload-time = "2025-07-07T19:18:16.611Z" }, - { url = "https://files.pythonhosted.org/packages/ee/2f/9af748366763b2a494fed477f88051dbf06f56053d5c00eba652697e3f94/pandas-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0", size = 11724083, upload-time = "2025-07-07T19:18:20.512Z" }, - { url = "https://files.pythonhosted.org/packages/2c/95/79ab37aa4c25d1e7df953dde407bb9c3e4ae47d154bc0dd1692f3a6dcf8c/pandas-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191", size = 12342360, upload-time = "2025-07-07T19:18:23.194Z" }, - { url = "https://files.pythonhosted.org/packages/75/a7/d65e5d8665c12c3c6ff5edd9709d5836ec9b6f80071b7f4a718c6106e86e/pandas-2.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1", size = 13202098, upload-time = "2025-07-07T19:18:25.558Z" }, - { url = "https://files.pythonhosted.org/packages/65/f3/4c1dbd754dbaa79dbf8b537800cb2fa1a6e534764fef50ab1f7533226c5c/pandas-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97", size = 13837228, upload-time = "2025-07-07T19:18:28.344Z" }, - { url = "https://files.pythonhosted.org/packages/3f/d6/d7f5777162aa9b48ec3910bca5a58c9b5927cfd9cfde3aa64322f5ba4b9f/pandas-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83", size = 11336561, upload-time = "2025-07-07T19:18:31.211Z" }, { url = "https://files.pythonhosted.org/packages/76/1c/ccf70029e927e473a4476c00e0d5b32e623bff27f0402d0a92b7fc29bb9f/pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b", size = 11566608, upload-time = "2025-07-07T19:18:33.86Z" }, { url = "https://files.pythonhosted.org/packages/ec/d3/3c37cb724d76a841f14b8f5fe57e5e3645207cc67370e4f84717e8bb7657/pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f", size = 10823181, upload-time = "2025-07-07T19:18:36.151Z" }, { url = "https://files.pythonhosted.org/packages/8a/4c/367c98854a1251940edf54a4df0826dcacfb987f9068abf3e3064081a382/pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85", size = 11793570, upload-time = "2025-07-07T19:18:38.385Z" }, @@ -1252,21 +1176,6 @@ version = "0.4.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, - { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, - { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, - { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, - { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, - { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, - { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, - { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, - { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, @@ -1380,13 +1289,6 @@ version = "23.0.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56", size = 34307390, upload-time = "2026-02-16T10:08:08.654Z" }, - { url = "https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c", size = 35853761, upload-time = "2026-02-16T10:08:17.811Z" }, - { url = "https://files.pythonhosted.org/packages/2e/08/3e56a18819462210432ae37d10f5c8eed3828be1d6c751b6e6a2e93c286a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d0744403adabef53c985a7f8a082b502a368510c40d184df349a0a8754533258", size = 44493116, upload-time = "2026-02-16T10:08:25.792Z" }, - { url = "https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2", size = 47564532, upload-time = "2026-02-16T10:08:34.27Z" }, - { url = "https://files.pythonhosted.org/packages/20/bc/73f611989116b6f53347581b02177f9f620efdf3cd3f405d0e83cdf53a83/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ddf743e82f69dcd6dbbcb63628895d7161e04e56794ef80550ac6f3315eeb1d5", size = 48183685, upload-time = "2026-02-16T10:08:42.889Z" }, - { url = "https://files.pythonhosted.org/packages/b0/cc/6c6b3ecdae2a8c3aced99956187e8302fc954cc2cca2a37cf2111dad16ce/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e052a211c5ac9848ae15d5ec875ed0943c0221e2fcfe69eee80b604b4e703222", size = 50605582, upload-time = "2026-02-16T10:08:51.641Z" }, - { url = "https://files.pythonhosted.org/packages/8d/94/d359e708672878d7638a04a0448edf7c707f9e5606cee11e15aaa5c7535a/pyarrow-23.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5abde149bb3ce524782d838eb67ac095cd3fd6090eba051130589793f1a7f76d", size = 27521148, upload-time = "2026-02-16T10:08:58.077Z" }, { url = "https://files.pythonhosted.org/packages/b0/41/8e6b6ef7e225d4ceead8459427a52afdc23379768f54dd3566014d7618c1/pyarrow-23.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6f0147ee9e0386f519c952cc670eb4a8b05caa594eeffe01af0e25f699e4e9bb", size = 34302230, upload-time = "2026-02-16T10:09:03.859Z" }, { url = "https://files.pythonhosted.org/packages/bf/4a/1472c00392f521fea03ae93408bf445cc7bfa1ab81683faf9bc188e36629/pyarrow-23.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0ae6e17c828455b6265d590100c295193f93cc5675eb0af59e49dbd00d2de350", size = 35850050, upload-time = "2026-02-16T10:09:11.877Z" }, { url = "https://files.pythonhosted.org/packages/0c/b2/bd1f2f05ded56af7f54d702c8364c9c43cd6abb91b0e9933f3d77b4f4132/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:fed7020203e9ef273360b9e45be52a2a47d3103caf156a30ace5247ffb51bdbd", size = 44491918, upload-time = "2026-02-16T10:09:18.144Z" }, @@ -1464,19 +1366,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, - { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, - { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, - { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, - { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, - { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, @@ -1555,14 +1444,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, - { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, - { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, - { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, @@ -1588,12 +1469,10 @@ version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ @@ -1636,15 +1515,6 @@ version = "6.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, - { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, - { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, - { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, - { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, - { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, @@ -1749,45 +1619,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] -[[package]] -name = "tomli" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, -] - [[package]] name = "tqdm" version = "4.67.1" @@ -1912,8 +1743,7 @@ name = "weaviate-demo-datasets" version = "0.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "pandas" }, { name = "tqdm" }, ] @@ -1927,8 +1757,10 @@ name = "weaviate-docs" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "anthropic" }, { name = "datasets" }, { name = "ijson" }, + { name = "openai" }, { name = "pandas" }, { name = "pytest" }, { name = "python-dotenv" }, @@ -1937,12 +1769,15 @@ dependencies = [ { name = "weaviate-agents" }, { name = "weaviate-client" }, { name = "weaviate-demo-datasets" }, + { name = "weaviate-engram" }, ] [package.metadata] requires-dist = [ + { name = "anthropic", specifier = ">=0.40.0" }, { name = "datasets", specifier = ">=4.0.0" }, { name = "ijson", specifier = ">=3.3.0" }, + { name = "openai", specifier = ">=1.50.0" }, { name = "pandas", specifier = ">=2.2.3" }, { name = "pytest", specifier = ">=8.3.5" }, { name = "python-dotenv", specifier = ">=1.1.1" }, @@ -1951,6 +1786,19 @@ requires-dist = [ { name = "weaviate-agents", specifier = ">=1.1.0" }, { name = "weaviate-client", specifier = ">=4.19.0" }, { name = "weaviate-demo-datasets", specifier = ">=0.7.0" }, + { name = "weaviate-engram", specifier = ">=0.3.0" }, +] + +[[package]] +name = "weaviate-engram" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/b2/7929e35ac1322fb1709dc2df5fb9350eb6c942b2d68929d2749ee290642e/weaviate_engram-0.3.0.tar.gz", hash = "sha256:fbec6aa42652a821a148c68e28821ea0c01c28cdcb18b789ac6b969577c528a9", size = 7954, upload-time = "2026-03-05T11:20:42.329Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/80/41667ee6e1a6299d38a68e0e9a7eee4668baaab29427fd3f5f1557fc88dd/weaviate_engram-0.3.0-py3-none-any.whl", hash = "sha256:f73a31cf1effb6d73fbfcf2effa50063c18a469ddd26f7116f7357c9075ee46c", size = 13584, upload-time = "2026-03-05T11:20:43.259Z" }, ] [[package]] @@ -1959,21 +1807,6 @@ version = "3.6.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/ee/f9f1d656ad168681bb0f6b092372c1e533c4416b8069b1896a175c46e484/xxhash-3.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87ff03d7e35c61435976554477a7f4cd1704c3596a89a8300d5ce7fc83874a71", size = 32845, upload-time = "2025-10-02T14:33:51.573Z" }, - { url = "https://files.pythonhosted.org/packages/a3/b1/93508d9460b292c74a09b83d16750c52a0ead89c51eea9951cb97a60d959/xxhash-3.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f572dfd3d0e2eb1a57511831cf6341242f5a9f8298a45862d085f5b93394a27d", size = 30807, upload-time = "2025-10-02T14:33:52.964Z" }, - { url = "https://files.pythonhosted.org/packages/07/55/28c93a3662f2d200c70704efe74aab9640e824f8ce330d8d3943bf7c9b3c/xxhash-3.6.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:89952ea539566b9fed2bbd94e589672794b4286f342254fad28b149f9615fef8", size = 193786, upload-time = "2025-10-02T14:33:54.272Z" }, - { url = "https://files.pythonhosted.org/packages/c1/96/fec0be9bb4b8f5d9c57d76380a366f31a1781fb802f76fc7cda6c84893c7/xxhash-3.6.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e6f2ffb07a50b52465a1032c3cf1f4a5683f944acaca8a134a2f23674c2058", size = 212830, upload-time = "2025-10-02T14:33:55.706Z" }, - { url = "https://files.pythonhosted.org/packages/c4/a0/c706845ba77b9611f81fd2e93fad9859346b026e8445e76f8c6fd057cc6d/xxhash-3.6.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b5b848ad6c16d308c3ac7ad4ba6bede80ed5df2ba8ed382f8932df63158dd4b2", size = 211606, upload-time = "2025-10-02T14:33:57.133Z" }, - { url = "https://files.pythonhosted.org/packages/67/1e/164126a2999e5045f04a69257eea946c0dc3e86541b400d4385d646b53d7/xxhash-3.6.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a034590a727b44dd8ac5914236a7b8504144447a9682586c3327e935f33ec8cc", size = 444872, upload-time = "2025-10-02T14:33:58.446Z" }, - { url = "https://files.pythonhosted.org/packages/2d/4b/55ab404c56cd70a2cf5ecfe484838865d0fea5627365c6c8ca156bd09c8f/xxhash-3.6.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a8f1972e75ebdd161d7896743122834fe87378160c20e97f8b09166213bf8cc", size = 193217, upload-time = "2025-10-02T14:33:59.724Z" }, - { url = "https://files.pythonhosted.org/packages/45/e6/52abf06bac316db33aa269091ae7311bd53cfc6f4b120ae77bac1b348091/xxhash-3.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ee34327b187f002a596d7b167ebc59a1b729e963ce645964bbc050d2f1b73d07", size = 210139, upload-time = "2025-10-02T14:34:02.041Z" }, - { url = "https://files.pythonhosted.org/packages/34/37/db94d490b8691236d356bc249c08819cbcef9273a1a30acf1254ff9ce157/xxhash-3.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:339f518c3c7a850dd033ab416ea25a692759dc7478a71131fe8869010d2b75e4", size = 197669, upload-time = "2025-10-02T14:34:03.664Z" }, - { url = "https://files.pythonhosted.org/packages/b7/36/c4f219ef4a17a4f7a64ed3569bc2b5a9c8311abdb22249ac96093625b1a4/xxhash-3.6.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf48889c9630542d4709192578aebbd836177c9f7a4a2778a7d6340107c65f06", size = 210018, upload-time = "2025-10-02T14:34:05.325Z" }, - { url = "https://files.pythonhosted.org/packages/fd/06/bfac889a374fc2fc439a69223d1750eed2e18a7db8514737ab630534fa08/xxhash-3.6.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5576b002a56207f640636056b4160a378fe36a58db73ae5c27a7ec8db35f71d4", size = 413058, upload-time = "2025-10-02T14:34:06.925Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d1/555d8447e0dd32ad0930a249a522bb2e289f0d08b6b16204cfa42c1f5a0c/xxhash-3.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af1f3278bd02814d6dedc5dec397993b549d6f16c19379721e5a1d31e132c49b", size = 190628, upload-time = "2025-10-02T14:34:08.669Z" }, - { url = "https://files.pythonhosted.org/packages/d1/15/8751330b5186cedc4ed4b597989882ea05e0408b53fa47bcb46a6125bfc6/xxhash-3.6.0-cp310-cp310-win32.whl", hash = "sha256:aed058764db109dc9052720da65fafe84873b05eb8b07e5e653597951af57c3b", size = 30577, upload-time = "2025-10-02T14:34:10.234Z" }, - { url = "https://files.pythonhosted.org/packages/bb/cc/53f87e8b5871a6eb2ff7e89c48c66093bda2be52315a8161ddc54ea550c4/xxhash-3.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:e82da5670f2d0d98950317f82a0e4a0197150ff19a6df2ba40399c2a3b9ae5fb", size = 31487, upload-time = "2025-10-02T14:34:11.618Z" }, - { url = "https://files.pythonhosted.org/packages/9f/00/60f9ea3bb697667a14314d7269956f58bf56bb73864f8f8d52a3c2535e9a/xxhash-3.6.0-cp310-cp310-win_arm64.whl", hash = "sha256:4a082ffff8c6ac07707fb6b671caf7c6e020c75226c561830b73d862060f281d", size = 27863, upload-time = "2025-10-02T14:34:12.619Z" }, { url = "https://files.pythonhosted.org/packages/17/d4/cc2f0400e9154df4b9964249da78ebd72f318e35ccc425e9f403c392f22a/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a", size = 32844, upload-time = "2025-10-02T14:34:14.037Z" }, { url = "https://files.pythonhosted.org/packages/5e/ec/1cc11cd13e26ea8bc3cb4af4eaadd8d46d5014aebb67be3f71fb0b68802a/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa", size = 30809, upload-time = "2025-10-02T14:34:15.484Z" }, { url = "https://files.pythonhosted.org/packages/04/5f/19fe357ea348d98ca22f456f75a30ac0916b51c753e1f8b2e0e6fb884cce/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248", size = 194665, upload-time = "2025-10-02T14:34:16.541Z" }, @@ -2082,22 +1915,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, - { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, - { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, - { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, - { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, - { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, - { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, - { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, - { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, - { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, - { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, - { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, - { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, - { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" },