vectara-agentic 0.4.1__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/__init__.py +1 -0
- tests/benchmark_models.py +1120 -0
- tests/conftest.py +18 -16
- tests/endpoint.py +9 -5
- tests/run_tests.py +3 -0
- tests/test_agent.py +52 -8
- tests/test_agent_type.py +2 -0
- tests/test_api_endpoint.py +13 -13
- tests/test_bedrock.py +9 -1
- tests/test_fallback.py +19 -8
- tests/test_gemini.py +14 -40
- tests/test_groq.py +9 -1
- tests/test_private_llm.py +20 -7
- tests/test_react_error_handling.py +293 -0
- tests/test_react_memory.py +257 -0
- tests/test_react_streaming.py +135 -0
- tests/test_react_workflow_events.py +395 -0
- tests/test_return_direct.py +1 -0
- tests/test_serialization.py +58 -20
- tests/test_together.py +9 -1
- tests/test_tools.py +3 -1
- tests/test_vectara_llms.py +2 -2
- tests/test_vhc.py +7 -2
- tests/test_workflow.py +17 -11
- vectara_agentic/_callback.py +79 -21
- vectara_agentic/_observability.py +19 -0
- vectara_agentic/_version.py +1 -1
- vectara_agentic/agent.py +89 -21
- vectara_agentic/agent_core/factory.py +5 -6
- vectara_agentic/agent_core/prompts.py +3 -4
- vectara_agentic/agent_core/serialization.py +12 -10
- vectara_agentic/agent_core/streaming.py +245 -68
- vectara_agentic/agent_core/utils/schemas.py +2 -2
- vectara_agentic/llm_utils.py +6 -2
- vectara_agentic/sub_query_workflow.py +3 -2
- vectara_agentic/tools.py +0 -19
- {vectara_agentic-0.4.1.dist-info → vectara_agentic-0.4.3.dist-info}/METADATA +156 -61
- vectara_agentic-0.4.3.dist-info/RECORD +58 -0
- vectara_agentic-0.4.1.dist-info/RECORD +0 -53
- {vectara_agentic-0.4.1.dist-info → vectara_agentic-0.4.3.dist-info}/WHEEL +0 -0
- {vectara_agentic-0.4.1.dist-info → vectara_agentic-0.4.3.dist-info}/licenses/LICENSE +0 -0
- {vectara_agentic-0.4.1.dist-info → vectara_agentic-0.4.3.dist-info}/top_level.txt +0 -0
tests/conftest.py
CHANGED
|
@@ -101,9 +101,9 @@ react_config_anthropic = AgentConfig(
|
|
|
101
101
|
react_config_gemini = AgentConfig(
|
|
102
102
|
agent_type=AgentType.REACT,
|
|
103
103
|
main_llm_provider=ModelProvider.GEMINI,
|
|
104
|
-
main_llm_model_name="models/gemini-2.5-flash",
|
|
104
|
+
main_llm_model_name="models/gemini-2.5-flash-lite",
|
|
105
105
|
tool_llm_provider=ModelProvider.GEMINI,
|
|
106
|
-
tool_llm_model_name="models/gemini-2.5-flash",
|
|
106
|
+
tool_llm_model_name="models/gemini-2.5-flash-lite",
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
react_config_together = AgentConfig(
|
|
@@ -112,29 +112,36 @@ react_config_together = AgentConfig(
|
|
|
112
112
|
tool_llm_provider=ModelProvider.TOGETHER,
|
|
113
113
|
)
|
|
114
114
|
|
|
115
|
+
react_config_openai = AgentConfig(
|
|
116
|
+
agent_type=AgentType.REACT,
|
|
117
|
+
main_llm_provider=ModelProvider.OPENAI,
|
|
118
|
+
tool_llm_provider=ModelProvider.OPENAI,
|
|
119
|
+
)
|
|
120
|
+
|
|
115
121
|
react_config_groq = AgentConfig(
|
|
116
122
|
agent_type=AgentType.REACT,
|
|
117
123
|
main_llm_provider=ModelProvider.GROQ,
|
|
118
124
|
tool_llm_provider=ModelProvider.GROQ,
|
|
119
125
|
)
|
|
120
126
|
|
|
127
|
+
|
|
121
128
|
# Private LLM configurations
|
|
122
129
|
private_llm_react_config = AgentConfig(
|
|
123
130
|
agent_type=AgentType.REACT,
|
|
124
131
|
main_llm_provider=ModelProvider.PRIVATE,
|
|
125
|
-
main_llm_model_name="gpt-
|
|
132
|
+
main_llm_model_name="gpt-4.1-mini",
|
|
126
133
|
private_llm_api_base="http://localhost:8000/v1",
|
|
127
134
|
tool_llm_provider=ModelProvider.PRIVATE,
|
|
128
|
-
tool_llm_model_name="gpt-
|
|
135
|
+
tool_llm_model_name="gpt-4.1-mini",
|
|
129
136
|
)
|
|
130
137
|
|
|
131
138
|
private_llm_fc_config = AgentConfig(
|
|
132
139
|
agent_type=AgentType.FUNCTION_CALLING,
|
|
133
140
|
main_llm_provider=ModelProvider.PRIVATE,
|
|
134
|
-
main_llm_model_name="gpt-4.1",
|
|
141
|
+
main_llm_model_name="gpt-4.1-mini",
|
|
135
142
|
private_llm_api_base="http://localhost:8000/v1",
|
|
136
143
|
tool_llm_provider=ModelProvider.PRIVATE,
|
|
137
|
-
tool_llm_model_name="gpt-4.1",
|
|
144
|
+
tool_llm_model_name="gpt-4.1-mini",
|
|
138
145
|
)
|
|
139
146
|
|
|
140
147
|
|
|
@@ -161,14 +168,6 @@ def is_rate_limited(response_text: str) -> bool:
|
|
|
161
168
|
"rate limit",
|
|
162
169
|
"quota exceeded",
|
|
163
170
|
"usage limit",
|
|
164
|
-
# GROQ-specific
|
|
165
|
-
"tokens per day",
|
|
166
|
-
"TPD",
|
|
167
|
-
"service tier",
|
|
168
|
-
"on_demand",
|
|
169
|
-
"deepseek-r1-distill-llama-70b",
|
|
170
|
-
"Upgrade to Dev Tier",
|
|
171
|
-
"console.groq.com/settings/billing",
|
|
172
171
|
# OpenAI-specific
|
|
173
172
|
"requests per minute",
|
|
174
173
|
"RPM",
|
|
@@ -188,6 +187,9 @@ def is_rate_limited(response_text: str) -> bool:
|
|
|
188
187
|
# Additional rate limit patterns
|
|
189
188
|
"Limit.*Used.*Requested",
|
|
190
189
|
"Need more tokens",
|
|
190
|
+
# Provider failure patterns
|
|
191
|
+
"failure can't be resolved after",
|
|
192
|
+
"Got empty message",
|
|
191
193
|
]
|
|
192
194
|
|
|
193
195
|
response_lower = response_text.lower()
|
|
@@ -279,10 +281,10 @@ class AgentTestMixin:
|
|
|
279
281
|
provider: Provider name for error messages
|
|
280
282
|
|
|
281
283
|
Usage:
|
|
282
|
-
with self.with_provider_fallback("
|
|
284
|
+
with self.with_provider_fallback("OpenAI"):
|
|
283
285
|
response = agent.chat("test")
|
|
284
286
|
|
|
285
|
-
with self.with_provider_fallback("
|
|
287
|
+
with self.with_provider_fallback("OpenAI"):
|
|
286
288
|
async for chunk in agent.astream_chat("test"):
|
|
287
289
|
pass
|
|
288
290
|
|
tests/endpoint.py
CHANGED
|
@@ -10,12 +10,13 @@ app = Flask(__name__)
|
|
|
10
10
|
# Configure logging
|
|
11
11
|
logging.basicConfig(level=logging.INFO)
|
|
12
12
|
app.logger.setLevel(logging.INFO)
|
|
13
|
-
werkzeug_log = logging.getLogger(
|
|
13
|
+
werkzeug_log = logging.getLogger("werkzeug")
|
|
14
14
|
werkzeug_log.setLevel(logging.ERROR)
|
|
15
15
|
|
|
16
16
|
# Load expected API key from environment (fallback for testing)
|
|
17
17
|
EXPECTED_API_KEY = "TEST_API_KEY"
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
# Authentication decorator
|
|
20
21
|
def require_api_key(f):
|
|
21
22
|
@wraps(f)
|
|
@@ -27,12 +28,15 @@ def require_api_key(f):
|
|
|
27
28
|
if api_key != EXPECTED_API_KEY:
|
|
28
29
|
return jsonify({"error": "Unauthorized"}), 401
|
|
29
30
|
return f(*args, **kwargs)
|
|
31
|
+
|
|
30
32
|
return decorated_function
|
|
31
33
|
|
|
34
|
+
|
|
32
35
|
@app.before_request
|
|
33
36
|
def log_request_info():
|
|
34
37
|
app.logger.info("%s %s", request.method, request.path)
|
|
35
38
|
|
|
39
|
+
|
|
36
40
|
@app.route("/v1/chat/completions", methods=["POST"])
|
|
37
41
|
@require_api_key
|
|
38
42
|
def chat_completions():
|
|
@@ -46,7 +50,7 @@ def chat_completions():
|
|
|
46
50
|
return jsonify({"error": "Invalid JSON payload"}), 400
|
|
47
51
|
|
|
48
52
|
client = OpenAI()
|
|
49
|
-
is_stream = data.get(
|
|
53
|
+
is_stream = data.get("stream", False)
|
|
50
54
|
|
|
51
55
|
if is_stream:
|
|
52
56
|
# Stream each chunk to the client as Server-Sent Events
|
|
@@ -62,9 +66,9 @@ def chat_completions():
|
|
|
62
66
|
yield f"data: {error_msg}\n\n"
|
|
63
67
|
|
|
64
68
|
headers = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
"Content-Type": "text/event-stream",
|
|
70
|
+
"Cache-Control": "no-cache",
|
|
71
|
+
"Connection": "keep-alive",
|
|
68
72
|
}
|
|
69
73
|
return Response(generate(), headers=headers)
|
|
70
74
|
|
tests/run_tests.py
CHANGED
|
@@ -35,6 +35,8 @@ def suppress_pydantic_warnings():
|
|
|
35
35
|
".*unclosed transport.*",
|
|
36
36
|
".*unclosed <socket\\.socket.*",
|
|
37
37
|
".*unclosed event loop.*",
|
|
38
|
+
".*unclosed resource <TCPTransport.*",
|
|
39
|
+
".*Implicitly cleaning up <TemporaryDirectory.*",
|
|
38
40
|
]
|
|
39
41
|
|
|
40
42
|
for pattern in pydantic_patterns:
|
|
@@ -64,6 +66,7 @@ def main():
|
|
|
64
66
|
|
|
65
67
|
# Add tests directory to Python path for relative imports
|
|
66
68
|
import os
|
|
69
|
+
|
|
67
70
|
sys.path.insert(0, os.path.abspath("tests"))
|
|
68
71
|
|
|
69
72
|
# Discover and run tests
|
tests/test_agent.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import unittest
|
|
@@ -18,7 +19,32 @@ from conftest import mult, STANDARD_TEST_TOPIC, STANDARD_TEST_INSTRUCTIONS
|
|
|
18
19
|
|
|
19
20
|
ARIZE_LOCK = threading.Lock()
|
|
20
21
|
|
|
22
|
+
|
|
21
23
|
class TestAgentPackage(unittest.TestCase):
|
|
24
|
+
def setUp(self):
|
|
25
|
+
self.agents_to_cleanup = []
|
|
26
|
+
|
|
27
|
+
def tearDown(self):
|
|
28
|
+
import gc
|
|
29
|
+
import asyncio
|
|
30
|
+
|
|
31
|
+
for agent in self.agents_to_cleanup:
|
|
32
|
+
if hasattr(agent, "cleanup"):
|
|
33
|
+
agent.cleanup()
|
|
34
|
+
|
|
35
|
+
# Force garbage collection to clean up any remaining references
|
|
36
|
+
gc.collect()
|
|
37
|
+
|
|
38
|
+
# Cancel any remaining asyncio tasks without closing the event loop
|
|
39
|
+
try:
|
|
40
|
+
loop = asyncio.get_event_loop()
|
|
41
|
+
if not loop.is_closed():
|
|
42
|
+
pending = asyncio.all_tasks(loop)
|
|
43
|
+
for task in pending:
|
|
44
|
+
task.cancel()
|
|
45
|
+
except RuntimeError:
|
|
46
|
+
pass
|
|
47
|
+
|
|
22
48
|
def test_get_prompt(self):
|
|
23
49
|
prompt_template = "{chat_topic} on {today} with {custom_instructions}"
|
|
24
50
|
topic = "Programming"
|
|
@@ -29,12 +55,16 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
29
55
|
+ " with Always do as your mother tells you!"
|
|
30
56
|
)
|
|
31
57
|
self.assertEqual(
|
|
32
|
-
format_prompt(
|
|
58
|
+
format_prompt(
|
|
59
|
+
prompt_template, GENERAL_INSTRUCTIONS, topic, custom_instructions
|
|
60
|
+
),
|
|
61
|
+
expected_output,
|
|
33
62
|
)
|
|
34
63
|
|
|
35
64
|
def test_agent_init(self):
|
|
36
65
|
tools = [ToolsFactory().create_tool(mult)]
|
|
37
66
|
agent = Agent(tools, STANDARD_TEST_TOPIC, STANDARD_TEST_INSTRUCTIONS)
|
|
67
|
+
self.agents_to_cleanup.append(agent)
|
|
38
68
|
self.assertEqual(agent.agent_type, AgentType.FUNCTION_CALLING)
|
|
39
69
|
self.assertEqual(agent._topic, STANDARD_TEST_TOPIC)
|
|
40
70
|
self.assertEqual(agent._custom_instructions, STANDARD_TEST_INSTRUCTIONS)
|
|
@@ -56,21 +86,26 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
56
86
|
main_llm_model_name="claude-sonnet-4-20250514",
|
|
57
87
|
tool_llm_provider=ModelProvider.TOGETHER,
|
|
58
88
|
tool_llm_model_name="moonshotai/Kimi-K2-Instruct",
|
|
59
|
-
observer=ObserverType.ARIZE_PHOENIX
|
|
89
|
+
observer=ObserverType.ARIZE_PHOENIX,
|
|
60
90
|
)
|
|
61
91
|
|
|
62
92
|
agent = Agent(
|
|
63
93
|
tools=tools,
|
|
64
94
|
topic=STANDARD_TEST_TOPIC,
|
|
65
95
|
custom_instructions=STANDARD_TEST_INSTRUCTIONS,
|
|
66
|
-
agent_config=config
|
|
96
|
+
agent_config=config,
|
|
67
97
|
)
|
|
98
|
+
self.agents_to_cleanup.append(agent)
|
|
68
99
|
self.assertEqual(agent._topic, STANDARD_TEST_TOPIC)
|
|
69
100
|
self.assertEqual(agent._custom_instructions, STANDARD_TEST_INSTRUCTIONS)
|
|
70
101
|
self.assertEqual(agent.agent_type, AgentType.REACT)
|
|
71
102
|
self.assertEqual(agent.agent_config.observer, ObserverType.ARIZE_PHOENIX)
|
|
72
|
-
self.assertEqual(
|
|
73
|
-
|
|
103
|
+
self.assertEqual(
|
|
104
|
+
agent.agent_config.main_llm_provider, ModelProvider.ANTHROPIC
|
|
105
|
+
)
|
|
106
|
+
self.assertEqual(
|
|
107
|
+
agent.agent_config.tool_llm_provider, ModelProvider.TOGETHER
|
|
108
|
+
)
|
|
74
109
|
|
|
75
110
|
# To run this test, you must have ANTHROPIC_API_KEY and TOGETHER_API_KEY in your environment
|
|
76
111
|
self.assertEqual(
|
|
@@ -90,10 +125,13 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
90
125
|
topic=topic,
|
|
91
126
|
custom_instructions=instructions,
|
|
92
127
|
)
|
|
128
|
+
self.agents_to_cleanup.append(agent)
|
|
93
129
|
|
|
94
130
|
agent.chat("What is 5 times 10. Only give the answer, nothing else")
|
|
95
131
|
agent.chat("what is 3 times 7. Only give the answer, nothing else")
|
|
96
|
-
res = agent.chat(
|
|
132
|
+
res = agent.chat(
|
|
133
|
+
"multiply the results of the last two questions. Output only the answer."
|
|
134
|
+
)
|
|
97
135
|
self.assertEqual(res.response, "1050")
|
|
98
136
|
|
|
99
137
|
def test_from_corpus(self):
|
|
@@ -104,6 +142,7 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
104
142
|
data_description="information",
|
|
105
143
|
assistant_specialty="question answering",
|
|
106
144
|
)
|
|
145
|
+
self.agents_to_cleanup.append(agent)
|
|
107
146
|
|
|
108
147
|
self.assertIsInstance(agent, Agent)
|
|
109
148
|
self.assertEqual(agent._topic, "question answering")
|
|
@@ -116,14 +155,17 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
116
155
|
tools=tools,
|
|
117
156
|
topic=topic,
|
|
118
157
|
custom_instructions=instructions,
|
|
119
|
-
chat_history=[("What is 5 times 10", "50"), ("What is 3 times 7", "21")]
|
|
158
|
+
chat_history=[("What is 5 times 10", "50"), ("What is 3 times 7", "21")],
|
|
120
159
|
)
|
|
160
|
+
self.agents_to_cleanup.append(agent)
|
|
121
161
|
|
|
122
162
|
data = agent.dumps()
|
|
123
163
|
clone = Agent.loads(data)
|
|
124
164
|
assert clone.memory.get() == agent.memory.get()
|
|
125
165
|
|
|
126
|
-
res = agent.chat(
|
|
166
|
+
res = agent.chat(
|
|
167
|
+
"multiply the results of the last two questions. Output only the answer."
|
|
168
|
+
)
|
|
127
169
|
self.assertEqual(res.response, "1050")
|
|
128
170
|
|
|
129
171
|
def test_custom_general_instruction(self):
|
|
@@ -136,8 +178,10 @@ class TestAgentPackage(unittest.TestCase):
|
|
|
136
178
|
assistant_specialty="question answering",
|
|
137
179
|
general_instructions=general_instructions,
|
|
138
180
|
)
|
|
181
|
+
self.agents_to_cleanup.append(agent)
|
|
139
182
|
|
|
140
183
|
res = agent.chat("What is the meaning of the universe?")
|
|
184
|
+
print(f"Response: {res.response}")
|
|
141
185
|
self.assertEqual(res.response, "I DIDN'T DO IT")
|
|
142
186
|
|
|
143
187
|
|
tests/test_agent_type.py
CHANGED
|
@@ -7,6 +7,7 @@ import unittest
|
|
|
7
7
|
|
|
8
8
|
import sys
|
|
9
9
|
import os
|
|
10
|
+
|
|
10
11
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
11
12
|
|
|
12
13
|
from conftest import (
|
|
@@ -25,6 +26,7 @@ from conftest import (
|
|
|
25
26
|
from vectara_agentic.agent import Agent
|
|
26
27
|
from vectara_agentic.tools import ToolsFactory
|
|
27
28
|
|
|
29
|
+
|
|
28
30
|
class TestAgentType(unittest.TestCase, AgentTestMixin):
|
|
29
31
|
|
|
30
32
|
def setUp(self):
|
tests/test_api_endpoint.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import unittest
|
|
@@ -21,6 +22,7 @@ class DummyAgent(Agent):
|
|
|
21
22
|
def chat(self, message: str) -> str:
|
|
22
23
|
return f"Echo: {message}"
|
|
23
24
|
|
|
25
|
+
|
|
24
26
|
class APITestCase(unittest.TestCase):
|
|
25
27
|
@classmethod
|
|
26
28
|
def setUpClass(cls):
|
|
@@ -42,7 +44,9 @@ class APITestCase(unittest.TestCase):
|
|
|
42
44
|
self.assertIn("No message provided", r.json()["detail"])
|
|
43
45
|
|
|
44
46
|
def test_chat_unauthorized(self):
|
|
45
|
-
r = self.client.get(
|
|
47
|
+
r = self.client.get(
|
|
48
|
+
"/chat", params={"message": "hello"}, headers={"X-API-Key": "bad"}
|
|
49
|
+
)
|
|
46
50
|
self.assertEqual(r.status_code, 403)
|
|
47
51
|
|
|
48
52
|
def test_completions_success(self):
|
|
@@ -69,14 +73,13 @@ class APITestCase(unittest.TestCase):
|
|
|
69
73
|
|
|
70
74
|
def test_completions_unauthorized(self):
|
|
71
75
|
payload = {"model": "m1", "prompt": "hi"}
|
|
72
|
-
r = self.client.post(
|
|
76
|
+
r = self.client.post(
|
|
77
|
+
"/v1/completions", json=payload, headers={"X-API-Key": "bad"}
|
|
78
|
+
)
|
|
73
79
|
self.assertEqual(r.status_code, 403)
|
|
74
80
|
|
|
75
81
|
def test_chat_completion_success(self):
|
|
76
|
-
payload = {
|
|
77
|
-
"model": "m1",
|
|
78
|
-
"messages": [{"role": "user", "content": "hello"}]
|
|
79
|
-
}
|
|
82
|
+
payload = {"model": "m1", "messages": [{"role": "user", "content": "hello"}]}
|
|
80
83
|
r = self.client.post("/v1/chat", json=payload, headers=self.headers)
|
|
81
84
|
self.assertEqual(r.status_code, 200)
|
|
82
85
|
data = r.json()
|
|
@@ -99,8 +102,8 @@ class APITestCase(unittest.TestCase):
|
|
|
99
102
|
{"role": "system", "content": "ignore me"},
|
|
100
103
|
{"role": "user", "content": "foo"},
|
|
101
104
|
{"role": "assistant", "content": "pong"},
|
|
102
|
-
{"role": "user", "content": "bar"}
|
|
103
|
-
]
|
|
105
|
+
{"role": "user", "content": "bar"},
|
|
106
|
+
],
|
|
104
107
|
}
|
|
105
108
|
r = self.client.post("/v1/chat", json=payload, headers=self.headers)
|
|
106
109
|
self.assertEqual(r.status_code, 200)
|
|
@@ -108,7 +111,7 @@ class APITestCase(unittest.TestCase):
|
|
|
108
111
|
|
|
109
112
|
# Should concatenate only user messages: "foo bar"
|
|
110
113
|
self.assertEqual(data["choices"][0]["message"]["content"], "Echo: foo bar")
|
|
111
|
-
self.assertEqual(data["usage"]["prompt_tokens"], 2)
|
|
114
|
+
self.assertEqual(data["usage"]["prompt_tokens"], 2) # "foo","bar"
|
|
112
115
|
self.assertEqual(data["usage"]["completion_tokens"], 3) # "Echo:","foo","bar"
|
|
113
116
|
|
|
114
117
|
def test_chat_completion_no_messages(self):
|
|
@@ -118,10 +121,7 @@ class APITestCase(unittest.TestCase):
|
|
|
118
121
|
self.assertIn("`messages` is required", r.json()["detail"])
|
|
119
122
|
|
|
120
123
|
def test_chat_completion_unauthorized(self):
|
|
121
|
-
payload = {
|
|
122
|
-
"model": "m1",
|
|
123
|
-
"messages": [{"role": "user", "content": "oops"}]
|
|
124
|
-
}
|
|
124
|
+
payload = {"model": "m1", "messages": [{"role": "user", "content": "oops"}]}
|
|
125
125
|
r = self.client.post("/v1/chat", json=payload, headers={"X-API-Key": "bad"})
|
|
126
126
|
self.assertEqual(r.status_code, 403)
|
|
127
127
|
|
tests/test_bedrock.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import unittest
|
|
@@ -9,12 +10,19 @@ from vectara_agentic.agent import Agent
|
|
|
9
10
|
from vectara_agentic.tools import ToolsFactory
|
|
10
11
|
|
|
11
12
|
import nest_asyncio
|
|
13
|
+
|
|
12
14
|
nest_asyncio.apply()
|
|
13
15
|
|
|
14
|
-
from conftest import
|
|
16
|
+
from conftest import (
|
|
17
|
+
mult,
|
|
18
|
+
fc_config_bedrock,
|
|
19
|
+
STANDARD_TEST_TOPIC,
|
|
20
|
+
STANDARD_TEST_INSTRUCTIONS,
|
|
21
|
+
)
|
|
15
22
|
|
|
16
23
|
ARIZE_LOCK = threading.Lock()
|
|
17
24
|
|
|
25
|
+
|
|
18
26
|
class TestBedrock(unittest.IsolatedAsyncioTestCase):
|
|
19
27
|
|
|
20
28
|
async def test_multiturn(self):
|
tests/test_fallback.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import os
|
|
@@ -16,19 +17,25 @@ from vectara_agentic.tools import ToolsFactory
|
|
|
16
17
|
|
|
17
18
|
FLASK_PORT = 5002
|
|
18
19
|
|
|
20
|
+
|
|
19
21
|
class TestFallback(unittest.TestCase):
|
|
20
22
|
|
|
21
23
|
@classmethod
|
|
22
24
|
def setUp(cls):
|
|
23
25
|
# Start the Flask server as a subprocess
|
|
24
26
|
cls.flask_process = subprocess.Popen(
|
|
25
|
-
[
|
|
26
|
-
env={
|
|
27
|
-
|
|
27
|
+
["flask", "run", f"--port={FLASK_PORT}"],
|
|
28
|
+
env={
|
|
29
|
+
**os.environ,
|
|
30
|
+
"FLASK_APP": "tests.endpoint:app",
|
|
31
|
+
"FLASK_ENV": "development",
|
|
32
|
+
},
|
|
33
|
+
stdout=None,
|
|
34
|
+
stderr=None,
|
|
28
35
|
)
|
|
29
36
|
# Wait for the server to start
|
|
30
37
|
timeout = 10
|
|
31
|
-
url = f
|
|
38
|
+
url = f"http://127.0.0.1:{FLASK_PORT}/"
|
|
32
39
|
for _ in range(timeout):
|
|
33
40
|
try:
|
|
34
41
|
requests.get(url)
|
|
@@ -54,7 +61,7 @@ class TestFallback(unittest.TestCase):
|
|
|
54
61
|
config = AgentConfig(
|
|
55
62
|
agent_type=AgentType.REACT,
|
|
56
63
|
main_llm_provider=ModelProvider.PRIVATE,
|
|
57
|
-
main_llm_model_name="gpt-
|
|
64
|
+
main_llm_model_name="gpt-4.1-mini",
|
|
58
65
|
private_llm_api_base=f"http://127.0.0.1:{FLASK_PORT}/v1",
|
|
59
66
|
private_llm_api_key="TEST_API_KEY",
|
|
60
67
|
)
|
|
@@ -62,9 +69,13 @@ class TestFallback(unittest.TestCase):
|
|
|
62
69
|
# Set fallback agent config to OpenAI agent
|
|
63
70
|
fallback_config = AgentConfig()
|
|
64
71
|
|
|
65
|
-
agent = Agent(
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
agent = Agent(
|
|
73
|
+
agent_config=config,
|
|
74
|
+
tools=tools,
|
|
75
|
+
topic=topic,
|
|
76
|
+
custom_instructions=custom_instructions,
|
|
77
|
+
fallback_agent_config=fallback_config,
|
|
78
|
+
)
|
|
68
79
|
|
|
69
80
|
# To run this test, you must have OPENAI_API_KEY in your environment
|
|
70
81
|
res = agent.chat(
|
tests/test_gemini.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import unittest
|
|
@@ -9,46 +10,15 @@ from vectara_agentic.tools import ToolsFactory
|
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
import nest_asyncio
|
|
12
|
-
nest_asyncio.apply()
|
|
13
|
-
|
|
14
|
-
from conftest import mult, fc_config_gemini, STANDARD_TEST_TOPIC, STANDARD_TEST_INSTRUCTIONS
|
|
15
|
-
|
|
16
|
-
tickers = {
|
|
17
|
-
"C": "Citigroup",
|
|
18
|
-
"COF": "Capital One",
|
|
19
|
-
"JPM": "JPMorgan Chase",
|
|
20
|
-
"AAPL": "Apple Computer",
|
|
21
|
-
"GOOG": "Google",
|
|
22
|
-
"AMZN": "Amazon",
|
|
23
|
-
"SNOW": "Snowflake",
|
|
24
|
-
"TEAM": "Atlassian",
|
|
25
|
-
"TSLA": "Tesla",
|
|
26
|
-
"NVDA": "Nvidia",
|
|
27
|
-
"MSFT": "Microsoft",
|
|
28
|
-
"AMD": "Advanced Micro Devices",
|
|
29
|
-
"INTC": "Intel",
|
|
30
|
-
"NFLX": "Netflix",
|
|
31
|
-
"STT": "State Street",
|
|
32
|
-
"BK": "Bank of New York Mellon",
|
|
33
|
-
}
|
|
34
|
-
years = list(range(2015, 2025))
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def get_company_info() -> list[str]:
|
|
38
|
-
"""
|
|
39
|
-
Returns a dictionary of companies you can query about. Always check this before using any other tool.
|
|
40
|
-
The output is a dictionary of valid ticker symbols mapped to company names.
|
|
41
|
-
You can use this to identify the companies you can query about, and their ticker information.
|
|
42
|
-
"""
|
|
43
|
-
return tickers
|
|
44
13
|
|
|
14
|
+
nest_asyncio.apply()
|
|
45
15
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
16
|
+
from conftest import (
|
|
17
|
+
mult,
|
|
18
|
+
fc_config_gemini,
|
|
19
|
+
STANDARD_TEST_TOPIC,
|
|
20
|
+
STANDARD_TEST_INSTRUCTIONS,
|
|
21
|
+
)
|
|
52
22
|
|
|
53
23
|
|
|
54
24
|
class TestGEMINI(unittest.TestCase):
|
|
@@ -63,7 +33,9 @@ class TestGEMINI(unittest.TestCase):
|
|
|
63
33
|
)
|
|
64
34
|
_ = agent.chat("What is 5 times 10. Only give the answer, nothing else")
|
|
65
35
|
_ = agent.chat("what is 3 times 7. Only give the answer, nothing else")
|
|
66
|
-
res = agent.chat(
|
|
36
|
+
res = agent.chat(
|
|
37
|
+
"what is the result of multiplying the results of the last two multiplications. Only give the answer, nothing else."
|
|
38
|
+
)
|
|
67
39
|
self.assertIn("1050", res.response)
|
|
68
40
|
|
|
69
41
|
def test_gemini_single_prompt(self):
|
|
@@ -75,7 +47,9 @@ class TestGEMINI(unittest.TestCase):
|
|
|
75
47
|
topic=STANDARD_TEST_TOPIC,
|
|
76
48
|
custom_instructions=STANDARD_TEST_INSTRUCTIONS,
|
|
77
49
|
)
|
|
78
|
-
res = agent.chat(
|
|
50
|
+
res = agent.chat(
|
|
51
|
+
"First, multiply 5 by 10. Then, multiply 3 by 7. Finally, multiply the results of the first two calculations."
|
|
52
|
+
)
|
|
79
53
|
self.assertIn("1050", res.response)
|
|
80
54
|
|
|
81
55
|
|
tests/test_groq.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import unittest
|
|
@@ -9,12 +10,19 @@ from vectara_agentic.agent import Agent
|
|
|
9
10
|
from vectara_agentic.tools import ToolsFactory
|
|
10
11
|
|
|
11
12
|
import nest_asyncio
|
|
13
|
+
|
|
12
14
|
nest_asyncio.apply()
|
|
13
15
|
|
|
14
|
-
from conftest import
|
|
16
|
+
from conftest import (
|
|
17
|
+
mult,
|
|
18
|
+
fc_config_groq,
|
|
19
|
+
STANDARD_TEST_TOPIC,
|
|
20
|
+
STANDARD_TEST_INSTRUCTIONS,
|
|
21
|
+
)
|
|
15
22
|
|
|
16
23
|
ARIZE_LOCK = threading.Lock()
|
|
17
24
|
|
|
25
|
+
|
|
18
26
|
class TestGROQ(unittest.IsolatedAsyncioTestCase):
|
|
19
27
|
|
|
20
28
|
async def test_multiturn(self):
|
tests/test_private_llm.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Suppress external dependency warnings before any other imports
|
|
2
2
|
import warnings
|
|
3
|
+
|
|
3
4
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
4
5
|
|
|
5
6
|
import os
|
|
@@ -16,19 +17,26 @@ from vectara_agentic.tools import ToolsFactory
|
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
FLASK_PORT = 5001
|
|
20
|
+
|
|
21
|
+
|
|
19
22
|
class TestPrivateLLM(unittest.TestCase):
|
|
20
23
|
|
|
21
24
|
@classmethod
|
|
22
25
|
def setUp(cls):
|
|
23
26
|
# Start the Flask server as a subprocess
|
|
24
27
|
cls.flask_process = subprocess.Popen(
|
|
25
|
-
[
|
|
26
|
-
env={
|
|
27
|
-
|
|
28
|
+
["flask", "run", f"--port={FLASK_PORT}"],
|
|
29
|
+
env={
|
|
30
|
+
**os.environ,
|
|
31
|
+
"FLASK_APP": "tests.endpoint:app",
|
|
32
|
+
"FLASK_ENV": "development",
|
|
33
|
+
},
|
|
34
|
+
stdout=None,
|
|
35
|
+
stderr=None,
|
|
28
36
|
)
|
|
29
37
|
# Wait for the server to start
|
|
30
38
|
timeout = 10
|
|
31
|
-
url = f
|
|
39
|
+
url = f"http://127.0.0.1:{FLASK_PORT}/"
|
|
32
40
|
for _ in range(timeout):
|
|
33
41
|
try:
|
|
34
42
|
requests.get(url)
|
|
@@ -54,12 +62,17 @@ class TestPrivateLLM(unittest.TestCase):
|
|
|
54
62
|
config = AgentConfig(
|
|
55
63
|
agent_type=AgentType.FUNCTION_CALLING,
|
|
56
64
|
main_llm_provider=ModelProvider.PRIVATE,
|
|
57
|
-
main_llm_model_name="gpt-4.1",
|
|
65
|
+
main_llm_model_name="gpt-4.1-mini",
|
|
58
66
|
private_llm_api_base=f"http://127.0.0.1:{FLASK_PORT}/v1",
|
|
59
67
|
private_llm_api_key="TEST_API_KEY",
|
|
60
68
|
)
|
|
61
|
-
agent = Agent(
|
|
62
|
-
|
|
69
|
+
agent = Agent(
|
|
70
|
+
agent_config=config,
|
|
71
|
+
tools=tools,
|
|
72
|
+
topic=topic,
|
|
73
|
+
custom_instructions=custom_instructions,
|
|
74
|
+
verbose=False,
|
|
75
|
+
)
|
|
63
76
|
|
|
64
77
|
# To run this test, you must have OPENAI_API_KEY in your environment
|
|
65
78
|
res = agent.chat(
|