vectorwave 0.1.8__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vectorwave-0.1.8/src/vectorwave.egg-info → vectorwave-0.2.0}/PKG-INFO +46 -52
- {vectorwave-0.1.8 → vectorwave-0.2.0}/Readme.md +44 -50
- {vectorwave-0.1.8 → vectorwave-0.2.0}/pyproject.toml +2 -2
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/test_semantic_caching.py +6 -3
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/search/test_execution_search.py +23 -3
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/test_replayer.py +45 -1
- vectorwave-0.2.0/src/tests/utils/test_return_caching.py +126 -0
- vectorwave-0.2.0/src/tests/utils/test_status.py +126 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/__init__.py +7 -1
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/db_search.py +107 -2
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/models/db_config.py +4 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/factory.py +4 -2
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/tracer.py +71 -7
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/execution_search.py +2 -8
- vectorwave-0.2.0/src/vectorwave/utils/healer.py +155 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/replayer.py +48 -12
- vectorwave-0.2.0/src/vectorwave/utils/replayer_semantic.py +232 -0
- vectorwave-0.2.0/src/vectorwave/utils/return_caching_utils.py +134 -0
- vectorwave-0.2.0/src/vectorwave/utils/status.py +55 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/factory.py +12 -10
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/huggingface_vectorizer.py +6 -5
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/openai_vectorizer.py +6 -5
- {vectorwave-0.1.8 → vectorwave-0.2.0/src/vectorwave.egg-info}/PKG-INFO +46 -52
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/SOURCES.txt +5 -0
- vectorwave-0.1.8/src/vectorwave/utils/return_caching_utils.py +0 -76
- {vectorwave-0.1.8 → vectorwave-0.2.0}/LICENSE +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/MANIFEST.in +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/NOTICE +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/setup.cfg +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/batch/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/batch/test_batch.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/conftest.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/core/test_decorator.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_archiver.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_db.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/database/test_db_search.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/exception/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/models/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/models/test_db_config.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/alert/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/alert/test_alerter.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/test_async_trace.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/monitoring/test_tracer.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/prediction/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/search/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/utils/test_function_cahe.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/tests/vectorizer/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/batch/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/batch/batch.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/core.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/decorator.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/core/generator.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/archiver.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/database/db.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/exception/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/exception/exceptions.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/models/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/base.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/null_alerter.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/alert/webhook_alerter.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/monitoring/monitoring.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/prediction/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/prediction/predictor.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/extended_search.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/search/rag_search.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/utils/function_cache.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/__init__.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave/vectorizer/base.py +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/dependency_links.txt +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/requires.txt +0 -0
- {vectorwave-0.1.8 → vectorwave-0.2.0}/src/vectorwave.egg-info/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vectorwave
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: VectorWave: Seamless Auto-Vectorization Framework
|
|
5
5
|
Author-email: junyeonggim <junyeonggim5@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
+
Project-URL: Repository, https://github.com/cozymori/vectorwave
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -130,62 +130,56 @@ process_payment("user_789", 5000)
|
|
|
130
130
|
|
|
131
131
|
To use the LLM feature, you must specify dependencies and environment variables.
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
> # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
|
|
148
|
-
> ```
|
|
133
|
+
#### Prerequisites for AI Auto-Documentation
|
|
134
|
+
|
|
135
|
+
To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
|
|
136
|
+
|
|
137
|
+
1. **Install Library:**
|
|
138
|
+
```bash
|
|
139
|
+
pip install openai
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
|
|
143
|
+
```ini
|
|
144
|
+
OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
|
|
145
|
+
# WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
|
|
146
|
+
```
|
|
149
147
|
|
|
150
148
|
### 2.2. 🚀 Usage: Auto-Generating Function Metadata (Auto=True)
|
|
151
149
|
|
|
152
150
|
Instead of manually defining `search_description` and `sequence_narrative`, you can use the `auto=True` flag.
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
> generate_and_register_metadata()
|
|
184
|
-
> ```
|
|
185
|
-
> ````
|
|
186
|
-
>
|
|
187
|
-
> *Note: Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.*
|
|
152
|
+
#### 3. Automatic Function Metadata Generation (Auto=True)
|
|
153
|
+
|
|
154
|
+
You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
|
|
155
|
+
|
|
156
|
+
1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
# Code from vectorwave/test_ex/example.py
|
|
160
|
+
@vectorize(auto=True, team="loyalty-program")
|
|
161
|
+
def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
|
|
162
|
+
"""
|
|
163
|
+
Function to calculate loyalty points based on purchase amount.
|
|
164
|
+
VIP customers earn double points.
|
|
165
|
+
"""
|
|
166
|
+
points = purchase_amount // 10
|
|
167
|
+
if is_vip:
|
|
168
|
+
points *= 2
|
|
169
|
+
return {"points": points, "tier": "VIP" if is_vip else "Regular"}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# ... (After defining the calculate_loyalty_points function above)
|
|
176
|
+
|
|
177
|
+
# [Mandatory] Must be called after all function definitions are complete.
|
|
178
|
+
print("🚀 Checking for functions needing auto-documentation...")
|
|
179
|
+
generate_and_register_metadata()
|
|
180
|
+
```
|
|
188
181
|
|
|
182
|
+
> **Note:** Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.
|
|
189
183
|
-----
|
|
190
184
|
|
|
191
185
|
#### Semantic Caching Example
|
|
@@ -104,62 +104,56 @@ process_payment("user_789", 5000)
|
|
|
104
104
|
|
|
105
105
|
To use the LLM feature, you must specify dependencies and environment variables.
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
> # WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
|
|
122
|
-
> ```
|
|
107
|
+
#### Prerequisites for AI Auto-Documentation
|
|
108
|
+
|
|
109
|
+
To use the AI-powered documentation feature, you must have the `openai` library installed and configure your API key.
|
|
110
|
+
|
|
111
|
+
1. **Install Library:**
|
|
112
|
+
```bash
|
|
113
|
+
pip install openai
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
2. **Set API Key:** Add your valid OpenAI API key to your `.env` file.
|
|
117
|
+
```ini
|
|
118
|
+
OPENAI_API_KEY="sk-proj-YOUR_API_KEY_HERE"
|
|
119
|
+
# WEAVIATE_GENERATIVE_MODULE="generative-openai" (Required to enable the Weaviate module when using OpenAI LLM)
|
|
120
|
+
```
|
|
123
121
|
|
|
124
122
|
### 2.2. 🚀 Usage: Auto-Generating Function Metadata (Auto=True)
|
|
125
123
|
|
|
126
124
|
Instead of manually defining `search_description` and `sequence_narrative`, you can use the `auto=True` flag.
|
|
127
125
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
> generate_and_register_metadata()
|
|
158
|
-
> ```
|
|
159
|
-
> ````
|
|
160
|
-
>
|
|
161
|
-
> *Note: Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.*
|
|
126
|
+
#### 3. Automatic Function Metadata Generation (Auto=True)
|
|
127
|
+
|
|
128
|
+
You can use the `auto=True` flag instead of manually defining `search_description` and `sequence_narrative`.
|
|
129
|
+
|
|
130
|
+
1. **Mark Function:** Set `auto=True`. It is **strongly recommended to include a detailed Docstring** to enhance the LLM's analysis quality.
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# Code from vectorwave/test_ex/example.py
|
|
134
|
+
@vectorize(auto=True, team="loyalty-program")
|
|
135
|
+
def calculate_loyalty_points(purchase_amount: int, is_vip: bool):
|
|
136
|
+
"""
|
|
137
|
+
Function to calculate loyalty points based on purchase amount.
|
|
138
|
+
VIP customers earn double points.
|
|
139
|
+
"""
|
|
140
|
+
points = purchase_amount // 10
|
|
141
|
+
if is_vip:
|
|
142
|
+
points *= 2
|
|
143
|
+
return {"points": points, "tier": "VIP" if is_vip else "Regular"}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
2. **Trigger Generation:** Call `generate_and_register_metadata()` **immediately after** all `@vectorize` function definitions are complete. This function calls the LLM, vectorizes the generated metadata, and registers it to the DB.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# ... (After defining the calculate_loyalty_points function above)
|
|
150
|
+
|
|
151
|
+
# [Mandatory] Must be called after all function definitions are complete.
|
|
152
|
+
print("🚀 Checking for functions needing auto-documentation...")
|
|
153
|
+
generate_and_register_metadata()
|
|
154
|
+
```
|
|
162
155
|
|
|
156
|
+
> **Note:** Since this process involves LLM API calls, it can cause **latency** if run during server startup. It is recommended to execute this via a separate management script or an admin API endpoint in a production environment.
|
|
163
157
|
-----
|
|
164
158
|
|
|
165
159
|
#### Semantic Caching Example
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vectorwave"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name = "junyeonggim", email = "junyeonggim5@gmail.com" },
|
|
10
10
|
]
|
|
@@ -32,7 +32,7 @@ dependencies = [
|
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
[project.urls]
|
|
35
|
-
Repository = "https://github.com/
|
|
35
|
+
Repository = "https://github.com/cozymori/vectorwave"
|
|
36
36
|
|
|
37
37
|
[tool.setuptools.packages.find]
|
|
38
38
|
where = ["src"]
|
|
@@ -14,6 +14,8 @@ from vectorwave.batch.batch import get_batch_manager as real_get_batch_manager
|
|
|
14
14
|
from vectorwave.database.db import get_cached_client as real_get_cached_client
|
|
15
15
|
from vectorwave.models.db_config import get_weaviate_settings as real_get_settings
|
|
16
16
|
from vectorwave.vectorizer.factory import get_vectorizer as real_get_vectorizer
|
|
17
|
+
from vectorwave.monitoring.tracer import _create_input_vector_data
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
# --- Fixture Setup ---
|
|
19
21
|
|
|
@@ -326,7 +328,6 @@ def test_tracer_input_vector_data_and_masking(mock_caching_deps):
|
|
|
326
328
|
"""
|
|
327
329
|
Tests that the _create_input_vector_data function masks sensitive keys.
|
|
328
330
|
"""
|
|
329
|
-
from vectorwave.monitoring.tracer import _create_input_vector_data
|
|
330
331
|
|
|
331
332
|
# Arrange: settings has sensitive_keys={"secret_key"}
|
|
332
333
|
settings = mock_caching_deps["settings"]
|
|
@@ -343,10 +344,12 @@ def test_tracer_input_vector_data_and_masking(mock_caching_deps):
|
|
|
343
344
|
text_content = input_data["text"]
|
|
344
345
|
assert "test_func" in text_content
|
|
345
346
|
assert "amount" in text_content
|
|
346
|
-
|
|
347
|
+
|
|
348
|
+
assert "[MASKED]" not in text_content
|
|
349
|
+
assert "secret_key" not in text_content
|
|
347
350
|
assert "my_top_secret" not in text_content
|
|
348
351
|
|
|
349
|
-
# 2. Verification: Check
|
|
352
|
+
# 2. Verification: Check stored properties
|
|
350
353
|
props = input_data["properties"]
|
|
351
354
|
assert props["function"] == "test_func"
|
|
352
355
|
assert props["kwargs"]["amount"] == 100
|
|
@@ -54,7 +54,6 @@ mock_db_errors = [
|
|
|
54
54
|
{"timestamp_utc": (mock_now - timedelta(minutes=15)).isoformat(), "error_code": "INVALID_INPUT"}, # Too old
|
|
55
55
|
]
|
|
56
56
|
|
|
57
|
-
|
|
58
57
|
# [Core Fix] Create mock datetime class
|
|
59
58
|
# Replaces the datetime.datetime class itself.
|
|
60
59
|
MockDateTime = MagicMock()
|
|
@@ -80,10 +79,31 @@ def test_find_recent_errors(mock_find_executions):
|
|
|
80
79
|
filters_arg = call_args.kwargs['filters']
|
|
81
80
|
|
|
82
81
|
assert filters_arg['status'] == 'ERROR'
|
|
83
|
-
assert filters_arg['error_code'] == 'INVALID_INPUT'
|
|
82
|
+
assert filters_arg['error_code'] == ['INVALID_INPUT']
|
|
84
83
|
assert filters_arg['timestamp_utc__gte'] == expected_time_limit_iso
|
|
85
84
|
|
|
86
85
|
|
|
86
|
+
@patch('vectorwave.search.execution_search.datetime', MockDateTime)
|
|
87
|
+
@patch('vectorwave.search.execution_search.find_executions')
|
|
88
|
+
def test_find_recent_errors_multi_code(mock_find_executions):
|
|
89
|
+
"""
|
|
90
|
+
Tests if find_recent_errors handles multiple error codes correctly by passing the list.
|
|
91
|
+
(Tests the newly implemented multi-code filtering path)
|
|
92
|
+
"""
|
|
93
|
+
error_list = ["INVALID_INPUT", "TIMEOUT_ERROR"]
|
|
94
|
+
find_recent_errors(minutes_ago=20, limit=5, error_codes=error_list)
|
|
95
|
+
|
|
96
|
+
call_args = mock_find_executions.call_args
|
|
97
|
+
filters_arg = call_args.kwargs['filters']
|
|
98
|
+
|
|
99
|
+
assert filters_arg['status'] == 'ERROR'
|
|
100
|
+
assert filters_arg['error_code'] == error_list
|
|
101
|
+
assert call_args.kwargs['limit'] == 5
|
|
102
|
+
|
|
103
|
+
expected_time_limit_iso_20 = (mock_now - timedelta(minutes=20)).isoformat()
|
|
104
|
+
assert filters_arg['timestamp_utc__gte'] == expected_time_limit_iso_20
|
|
105
|
+
|
|
106
|
+
|
|
87
107
|
@patch('vectorwave.search.execution_search.find_executions')
|
|
88
108
|
def test_find_slowest_executions(mock_find_executions):
|
|
89
109
|
"""
|
|
@@ -122,4 +142,4 @@ def test_find_by_trace_id(mock_find_executions):
|
|
|
122
142
|
# 2. Verify sort order (time ascending)
|
|
123
143
|
assert call_args.kwargs['sort_by'] == 'timestamp_utc'
|
|
124
144
|
assert call_args.kwargs['sort_ascending'] == True
|
|
125
|
-
assert call_args.kwargs['limit'] == 100
|
|
145
|
+
assert call_args.kwargs['limit'] == 100
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import json
|
|
3
|
+
import asyncio
|
|
4
|
+
import inspect
|
|
3
5
|
from unittest.mock import MagicMock, patch
|
|
4
6
|
from vectorwave.utils.replayer import VectorWaveReplayer
|
|
5
7
|
|
|
@@ -194,4 +196,46 @@ def test_replay_argument_filtering(mock_replayer_deps):
|
|
|
194
196
|
|
|
195
197
|
# Assert
|
|
196
198
|
# Should only be called with 'a=10', excluding 'team' and 'priority'
|
|
197
|
-
mock_func.assert_called_once_with(a=10)
|
|
199
|
+
mock_func.assert_called_once_with(a=10)
|
|
200
|
+
|
|
201
|
+
def test_replay_async_function_execution_fixed(mock_replayer_deps):
|
|
202
|
+
"""
|
|
203
|
+
[Case 5] Async Function Test (FIXED): Tests the async execution path using patching
|
|
204
|
+
of the import mechanism and executing the actual async function via asyncio.run.
|
|
205
|
+
"""
|
|
206
|
+
# Arrange
|
|
207
|
+
replayer = VectorWaveReplayer()
|
|
208
|
+
|
|
209
|
+
# 1. DB Mock Data
|
|
210
|
+
inputs = {"a": 1, "b": 2}
|
|
211
|
+
expected_result = 3
|
|
212
|
+
mock_logs = [create_mock_log("uuid-async-1", inputs, expected_result)]
|
|
213
|
+
mock_replayer_deps["query"].fetch_objects.return_value.objects = mock_logs
|
|
214
|
+
|
|
215
|
+
# 2. Define the actual ASYNC function for replayer to execute
|
|
216
|
+
async def real_async_add(a, b):
|
|
217
|
+
# This function will be called and executed by asyncio.run
|
|
218
|
+
await asyncio.sleep(0.001)
|
|
219
|
+
return a + b
|
|
220
|
+
|
|
221
|
+
# Manually attach the signature for the replayer's inspection check to pass
|
|
222
|
+
setattr(real_async_add, '__signature__', inspect.Signature([
|
|
223
|
+
inspect.Parameter('a', inspect.Parameter.POSITIONAL_OR_KEYWORD),
|
|
224
|
+
inspect.Parameter('b', inspect.Parameter.POSITIONAL_OR_KEYWORD)
|
|
225
|
+
]))
|
|
226
|
+
|
|
227
|
+
# 3. Patch importlib.import_module to return a mock module that contains the target function
|
|
228
|
+
mock_module = MagicMock()
|
|
229
|
+
mock_module.async_add = real_async_add # The mock module must have the function
|
|
230
|
+
|
|
231
|
+
with patch("vectorwave.utils.replayer.importlib.import_module", return_value=mock_module):
|
|
232
|
+
|
|
233
|
+
# Act
|
|
234
|
+
# replayer.replay (sync function) calls asyncio.run(real_async_add(**inputs)) internally.
|
|
235
|
+
result = replayer.replay("my_module.async_add", limit=1)
|
|
236
|
+
|
|
237
|
+
# Assert
|
|
238
|
+
# 1. The result should be successful and match the expected output
|
|
239
|
+
assert result["passed"] == 1
|
|
240
|
+
assert result["failed"] == 0
|
|
241
|
+
assert result["failures"] == []
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import MagicMock, patch
|
|
3
|
+
import json
|
|
4
|
+
from vectorwave.utils.return_caching_utils import _check_and_return_cached_result
|
|
5
|
+
from vectorwave.models.db_config import WeaviateSettings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# --- Mock Fixtures ---
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def mock_caching_utils_deps(monkeypatch):
|
|
12
|
+
"""
|
|
13
|
+
Mocks external dependencies of return_caching_utils.py (BatchManager, Tracer, DB search, etc.).
|
|
14
|
+
"""
|
|
15
|
+
# 1. Mock Settings
|
|
16
|
+
mock_settings = WeaviateSettings(
|
|
17
|
+
EXECUTION_COLLECTION_NAME="TestExecutions",
|
|
18
|
+
global_custom_values={"run_id": "test-run-123"}
|
|
19
|
+
)
|
|
20
|
+
mock_get_settings = MagicMock(return_value=mock_settings)
|
|
21
|
+
|
|
22
|
+
# 2. Mock Batch Manager (Key verification target)
|
|
23
|
+
mock_batch_manager = MagicMock()
|
|
24
|
+
mock_batch_manager.add_object = MagicMock()
|
|
25
|
+
mock_get_batch = MagicMock(return_value=mock_batch_manager)
|
|
26
|
+
|
|
27
|
+
# 3. Mock Vectorizer
|
|
28
|
+
mock_vectorizer = MagicMock()
|
|
29
|
+
mock_vectorizer.embed.return_value = [0.1, 0.2, 0.3] # Dummy Vector
|
|
30
|
+
mock_get_vectorizer = MagicMock(return_value=mock_vectorizer)
|
|
31
|
+
|
|
32
|
+
# 4. Mock Tracer Context (Provides current Trace ID)
|
|
33
|
+
mock_tracer = MagicMock()
|
|
34
|
+
mock_tracer.trace_id = "existing-trace-id-abc"
|
|
35
|
+
|
|
36
|
+
# 5. Apply Monkeypatches
|
|
37
|
+
TARGET_MODULE = "vectorwave.utils.return_caching_utils"
|
|
38
|
+
|
|
39
|
+
monkeypatch.setattr(f"{TARGET_MODULE}.get_weaviate_settings", mock_get_settings)
|
|
40
|
+
monkeypatch.setattr(f"{TARGET_MODULE}.get_batch_manager", mock_get_batch)
|
|
41
|
+
monkeypatch.setattr(f"{TARGET_MODULE}.get_vectorizer", mock_get_vectorizer)
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
"batch_manager": mock_batch_manager,
|
|
45
|
+
"vectorizer": mock_vectorizer,
|
|
46
|
+
"tracer_obj": mock_tracer
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_check_and_return_cached_result_cache_hit_logging(mock_caching_utils_deps):
|
|
51
|
+
"""
|
|
52
|
+
[Case 1] Verify that DB logging is correctly performed with 'CACHE_HIT' status upon a cache hit.
|
|
53
|
+
"""
|
|
54
|
+
# Arrange
|
|
55
|
+
# 1. Mock cache search result (Log found in DB)
|
|
56
|
+
mock_cached_log = {
|
|
57
|
+
"return_value": json.dumps({"result": "cached_data"}),
|
|
58
|
+
"metadata": {"distance": 0.1},
|
|
59
|
+
"uuid": "cached-log-uuid"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# 2. Mock search_similar_execution to return the above result (Simulate Cache Hit)
|
|
63
|
+
with patch("vectorwave.utils.return_caching_utils.search_similar_execution", return_value=mock_cached_log):
|
|
64
|
+
# [Fix] Instead of directly patching the .get method of the ContextVar object, replace the variable itself with a Mock object.
|
|
65
|
+
with patch("vectorwave.utils.return_caching_utils.current_tracer_var") as mock_tracer_var:
|
|
66
|
+
with patch("vectorwave.utils.return_caching_utils.current_span_id_var") as mock_span_var:
|
|
67
|
+
# Set return value for .get() call on the Mock object
|
|
68
|
+
mock_tracer_var.get.return_value = mock_caching_utils_deps["tracer_obj"]
|
|
69
|
+
mock_span_var.get.return_value = "parent-span-123"
|
|
70
|
+
|
|
71
|
+
# 4. Execute the target function
|
|
72
|
+
def dummy_func(a, b): pass # Target function
|
|
73
|
+
|
|
74
|
+
result = _check_and_return_cached_result(
|
|
75
|
+
func=dummy_func,
|
|
76
|
+
args=(10,),
|
|
77
|
+
kwargs={"b": 20},
|
|
78
|
+
function_name="dummy_func",
|
|
79
|
+
cache_threshold=0.9,
|
|
80
|
+
is_async=False
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Assert
|
|
84
|
+
# 1. Was the cached result returned correctly?
|
|
85
|
+
assert result == {"result": "cached_data"}
|
|
86
|
+
|
|
87
|
+
# 2. [Core] Was BatchManager.add_object called? (Check if logging occurred)
|
|
88
|
+
mock_batch = mock_caching_utils_deps["batch_manager"]
|
|
89
|
+
mock_batch.add_object.assert_called_once()
|
|
90
|
+
|
|
91
|
+
# 3. [Core] Verify properties of the saved log
|
|
92
|
+
call_kwargs = mock_batch.add_object.call_args.kwargs
|
|
93
|
+
props = call_kwargs["properties"]
|
|
94
|
+
|
|
95
|
+
assert props["status"] == "CACHE_HIT" # Check if status is CACHE_HIT
|
|
96
|
+
assert props["duration_ms"] == 0.0 # Check if duration is 0
|
|
97
|
+
assert props["trace_id"] == "existing-trace-id-abc" # Check if existing Trace ID is maintained
|
|
98
|
+
assert props["parent_span_id"] == "parent-span-123" # Check for parent Span ID maintenance
|
|
99
|
+
assert props["function_name"] == "dummy_func"
|
|
100
|
+
assert props["run_id"] == "test-run-123" # Check for inclusion of global tags
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_check_and_return_cached_result_cache_miss(mock_caching_utils_deps):
|
|
104
|
+
"""
|
|
105
|
+
[Case 2] Verify that None is returned without logging upon a cache miss.
|
|
106
|
+
"""
|
|
107
|
+
# Arrange
|
|
108
|
+
# Set search_similar_execution to return None (Cache Miss)
|
|
109
|
+
with patch("vectorwave.utils.return_caching_utils.search_similar_execution", return_value=None):
|
|
110
|
+
def dummy_func(): pass
|
|
111
|
+
|
|
112
|
+
result = _check_and_return_cached_result(
|
|
113
|
+
func=dummy_func,
|
|
114
|
+
args=(),
|
|
115
|
+
kwargs={},
|
|
116
|
+
function_name="dummy_func",
|
|
117
|
+
cache_threshold=0.9,
|
|
118
|
+
is_async=False
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Assert
|
|
122
|
+
# 1. Result should be None (To proceed to actual function execution)
|
|
123
|
+
assert result is None
|
|
124
|
+
|
|
125
|
+
# 2. BatchManager.add_object should not be called
|
|
126
|
+
mock_caching_utils_deps["batch_manager"].add_object.assert_not_called()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import MagicMock, patch
|
|
3
|
+
from vectorwave.utils.status import get_db_status, get_registered_functions
|
|
4
|
+
from vectorwave.models.db_config import WeaviateSettings
|
|
5
|
+
|
|
6
|
+
# --- Fixtures ---
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def mock_status_deps(monkeypatch):
|
|
10
|
+
"""
|
|
11
|
+
Mocks dependencies of status.py (get_cached_client, get_weaviate_settings).
|
|
12
|
+
"""
|
|
13
|
+
# 1. Mock Weaviate Client
|
|
14
|
+
mock_client = MagicMock()
|
|
15
|
+
mock_get_client = MagicMock(return_value=mock_client)
|
|
16
|
+
|
|
17
|
+
# 2. Mock Settings
|
|
18
|
+
mock_settings = WeaviateSettings(COLLECTION_NAME="TestFunctions")
|
|
19
|
+
mock_get_settings = MagicMock(return_value=mock_settings)
|
|
20
|
+
|
|
21
|
+
# 3. Apply Patches
|
|
22
|
+
monkeypatch.setattr("vectorwave.utils.status.get_cached_client", mock_get_client)
|
|
23
|
+
monkeypatch.setattr("vectorwave.utils.status.get_weaviate_settings", mock_get_settings)
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
"client": mock_client,
|
|
27
|
+
"settings": mock_settings,
|
|
28
|
+
"get_client": mock_get_client
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# --- Tests for get_db_status ---
|
|
32
|
+
|
|
33
|
+
def test_get_db_status_ready(mock_status_deps):
|
|
34
|
+
"""
|
|
35
|
+
Case 1: Test if True is returned when DB is connected and ready.
|
|
36
|
+
"""
|
|
37
|
+
mock_status_deps["client"].is_ready.return_value = True
|
|
38
|
+
|
|
39
|
+
assert get_db_status() is True
|
|
40
|
+
mock_status_deps["client"].is_ready.assert_called_once()
|
|
41
|
+
|
|
42
|
+
def test_get_db_status_not_ready(mock_status_deps):
|
|
43
|
+
"""
|
|
44
|
+
Case 2: Test if False is returned when DB is connected but not ready.
|
|
45
|
+
"""
|
|
46
|
+
mock_status_deps["client"].is_ready.return_value = False
|
|
47
|
+
|
|
48
|
+
assert get_db_status() is False
|
|
49
|
+
|
|
50
|
+
def test_get_db_status_exception(mock_status_deps):
|
|
51
|
+
"""
|
|
52
|
+
Case 3: Test if False is returned and error is logged when an exception occurs during DB connection.
|
|
53
|
+
"""
|
|
54
|
+
# Set exception to occur on client call
|
|
55
|
+
mock_status_deps["get_client"].side_effect = Exception("Connection Error")
|
|
56
|
+
|
|
57
|
+
assert get_db_status() is False
|
|
58
|
+
|
|
59
|
+
# --- Tests for get_registered_functions ---
|
|
60
|
+
|
|
61
|
+
@patch("vectorwave.utils.status.get_db_status")
|
|
62
|
+
def test_get_registered_functions_db_offline(mock_get_db_status, mock_status_deps):
|
|
63
|
+
"""
|
|
64
|
+
Case 4: Test if an empty list is returned when DB is offline (False).
|
|
65
|
+
"""
|
|
66
|
+
mock_get_db_status.return_value = False
|
|
67
|
+
|
|
68
|
+
result = get_registered_functions()
|
|
69
|
+
|
|
70
|
+
assert result == []
|
|
71
|
+
# Should not access client or collection if DB is offline
|
|
72
|
+
mock_status_deps["client"].collections.get.assert_not_called()
|
|
73
|
+
|
|
74
|
+
@patch("vectorwave.utils.status.get_db_status")
|
|
75
|
+
def test_get_registered_functions_success(mock_get_db_status, mock_status_deps):
|
|
76
|
+
"""
|
|
77
|
+
Case 5: Test if the list of registered functions is returned correctly.
|
|
78
|
+
"""
|
|
79
|
+
# 1. Arrange
|
|
80
|
+
mock_get_db_status.return_value = True
|
|
81
|
+
|
|
82
|
+
# Mock collection and query results
|
|
83
|
+
mock_collection = MagicMock()
|
|
84
|
+
mock_status_deps["client"].collections.get.return_value = mock_collection
|
|
85
|
+
|
|
86
|
+
# Create fake Weaviate objects
|
|
87
|
+
obj1 = MagicMock()
|
|
88
|
+
obj1.properties = {"function_name": "func_a", "module_name": "mod_a"}
|
|
89
|
+
obj2 = MagicMock()
|
|
90
|
+
obj2.properties = {"function_name": "func_b", "module_name": "mod_b"}
|
|
91
|
+
|
|
92
|
+
# Mock result of fetch_objects call
|
|
93
|
+
mock_collection.iterator.return_value = [obj1, obj2]
|
|
94
|
+
|
|
95
|
+
# 2. Act
|
|
96
|
+
result = get_registered_functions()
|
|
97
|
+
|
|
98
|
+
# 3. Assert
|
|
99
|
+
assert len(result) == 2
|
|
100
|
+
assert result[0]["function_name"] == "func_a"
|
|
101
|
+
assert result[1]["function_name"] == "func_b"
|
|
102
|
+
|
|
103
|
+
# Verify correct name usage when retrieving collection
|
|
104
|
+
mock_status_deps["client"].collections.get.assert_called_with("TestFunctions")
|
|
105
|
+
|
|
106
|
+
mock_collection.iterator.assert_called_once()
|
|
107
|
+
call_kwargs = mock_collection.iterator.call_args.kwargs
|
|
108
|
+
assert "return_properties" in call_kwargs
|
|
109
|
+
assert "function_name" in call_kwargs["return_properties"]
|
|
110
|
+
|
|
111
|
+
@patch("vectorwave.utils.status.get_db_status")
|
|
112
|
+
def test_get_registered_functions_exception(mock_get_db_status, mock_status_deps):
|
|
113
|
+
"""
|
|
114
|
+
Case 6: Test if an empty list is returned and error is handled when an exception occurs during retrieval.
|
|
115
|
+
"""
|
|
116
|
+
# 1. Arrange
|
|
117
|
+
mock_get_db_status.return_value = True
|
|
118
|
+
|
|
119
|
+
# Induce exception during collection retrieval
|
|
120
|
+
mock_status_deps["client"].collections.get.side_effect = Exception("Query Failed")
|
|
121
|
+
|
|
122
|
+
# 2. Act
|
|
123
|
+
result = get_registered_functions()
|
|
124
|
+
|
|
125
|
+
# 3. Assert
|
|
126
|
+
assert result == []
|
|
@@ -5,6 +5,9 @@ from .database.db_search import search_functions, search_executions, search_erro
|
|
|
5
5
|
from .monitoring.tracer import trace_span
|
|
6
6
|
from .search.rag_search import search_and_answer, analyze_trace_log
|
|
7
7
|
from .core.generator import generate_and_register_metadata
|
|
8
|
+
from .utils.healer import VectorWaveHealer
|
|
9
|
+
from .utils.replayer import VectorWaveReplayer
|
|
10
|
+
from .utils.replayer_semantic import SemanticReplayer
|
|
8
11
|
|
|
9
12
|
__all__ = [
|
|
10
13
|
'vectorize',
|
|
@@ -16,5 +19,8 @@ __all__ = [
|
|
|
16
19
|
'trace_span',
|
|
17
20
|
'search_and_answer',
|
|
18
21
|
'analyze_trace_log',
|
|
19
|
-
'generate_and_register_metadata'
|
|
22
|
+
'generate_and_register_metadata',
|
|
23
|
+
'VectorWaveHealer',
|
|
24
|
+
'VectorWaveReplayer',
|
|
25
|
+
'SemanticReplayer'
|
|
20
26
|
]
|