vectara-agentic 0.4.3__tar.gz → 0.4.5__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.

Potentially problematic release.


This version of vectara-agentic might be problematic. Click here for more details.

Files changed (67) hide show
  1. {vectara_agentic-0.4.3/vectara_agentic.egg-info → vectara_agentic-0.4.5}/PKG-INFO +9 -8
  2. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/README.md +1 -1
  3. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/requirements.txt +7 -6
  4. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_groq.py +34 -0
  5. vectara_agentic-0.4.5/tests/test_openai.py +160 -0
  6. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_streaming.py +0 -44
  7. vectara_agentic-0.4.5/tests/test_together.py +136 -0
  8. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/_version.py +1 -1
  9. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/llm_utils.py +65 -15
  10. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/tools.py +88 -31
  11. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5/vectara_agentic.egg-info}/PKG-INFO +9 -8
  12. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic.egg-info/SOURCES.txt +1 -0
  13. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic.egg-info/requires.txt +7 -6
  14. vectara_agentic-0.4.3/tests/test_together.py +0 -70
  15. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/LICENSE +0 -0
  16. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/MANIFEST.in +0 -0
  17. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/setup.cfg +0 -0
  18. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/setup.py +0 -0
  19. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/__init__.py +0 -0
  20. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/benchmark_models.py +0 -0
  21. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/conftest.py +0 -0
  22. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/endpoint.py +0 -0
  23. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/run_tests.py +0 -0
  24. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_agent.py +0 -0
  25. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_agent_fallback_memory.py +0 -0
  26. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_agent_memory_consistency.py +0 -0
  27. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_agent_type.py +0 -0
  28. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_api_endpoint.py +0 -0
  29. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_bedrock.py +0 -0
  30. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_fallback.py +0 -0
  31. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_gemini.py +0 -0
  32. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_private_llm.py +0 -0
  33. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_react_error_handling.py +0 -0
  34. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_react_memory.py +0 -0
  35. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_react_streaming.py +0 -0
  36. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_react_workflow_events.py +0 -0
  37. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_return_direct.py +0 -0
  38. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_serialization.py +0 -0
  39. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_session_memory.py +0 -0
  40. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_tools.py +0 -0
  41. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_vectara_llms.py +0 -0
  42. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_vhc.py +0 -0
  43. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/tests/test_workflow.py +0 -0
  44. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/__init__.py +0 -0
  45. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/_callback.py +0 -0
  46. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/_observability.py +0 -0
  47. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent.py +0 -0
  48. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_config.py +0 -0
  49. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/__init__.py +0 -0
  50. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/factory.py +0 -0
  51. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/prompts.py +0 -0
  52. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/serialization.py +0 -0
  53. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/streaming.py +0 -0
  54. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/utils/__init__.py +0 -0
  55. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/utils/hallucination.py +0 -0
  56. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/utils/logging.py +0 -0
  57. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/utils/schemas.py +0 -0
  58. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_core/utils/tools.py +0 -0
  59. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/agent_endpoint.py +0 -0
  60. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/db_tools.py +0 -0
  61. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/sub_query_workflow.py +0 -0
  62. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/tool_utils.py +0 -0
  63. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/tools_catalog.py +0 -0
  64. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/types.py +0 -0
  65. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic/utils.py +0 -0
  66. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic.egg-info/dependency_links.txt +0 -0
  67. {vectara_agentic-0.4.3 → vectara_agentic-0.4.5}/vectara_agentic.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectara_agentic
3
- Version: 0.4.3
3
+ Version: 0.4.5
4
4
  Summary: A Python package for creating AI Assistants and AI Agents with Vectara
5
5
  Home-page: https://github.com/vectara/py-vectara-agentic
6
6
  Author: Ofer Mendelevitch
@@ -16,19 +16,20 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: llama-index==0.13.2
20
- Requires-Dist: llama-index-core==0.13.2
19
+ Requires-Dist: llama-index==0.13.3
20
+ Requires-Dist: llama-index-core==0.13.3
21
21
  Requires-Dist: llama-index-workflows==1.3.0
22
22
  Requires-Dist: llama-index-cli==0.5.0
23
23
  Requires-Dist: llama-index-indices-managed-vectara==0.5.0
24
- Requires-Dist: llama-index-llms-openai==0.5.2
24
+ Requires-Dist: llama-index-llms-openai==0.5.4
25
25
  Requires-Dist: llama-index-llms-openai-like==0.5.0
26
- Requires-Dist: llama-index-llms-anthropic==0.8.2
26
+ Requires-Dist: llama-index-llms-anthropic==0.8.5
27
27
  Requires-Dist: llama-index-llms-together==0.4.0
28
28
  Requires-Dist: llama-index-llms-groq==0.4.0
29
29
  Requires-Dist: llama-index-llms-cohere==0.6.0
30
30
  Requires-Dist: llama-index-llms-google-genai==0.3.0
31
- Requires-Dist: llama-index-llms-bedrock-converse==0.8.0
31
+ Requires-Dist: google_genai>=1.31.0
32
+ Requires-Dist: llama-index-llms-bedrock-converse==0.8.2
32
33
  Requires-Dist: llama-index-tools-yahoo-finance==0.4.0
33
34
  Requires-Dist: llama-index-tools-arxiv==0.4.0
34
35
  Requires-Dist: llama-index-tools-database==0.4.0
@@ -54,7 +55,7 @@ Requires-Dist: protobuf==5.29.5
54
55
  Requires-Dist: tokenizers>=0.20
55
56
  Requires-Dist: pydantic>=2.11.5
56
57
  Requires-Dist: pandas==2.2.3
57
- Requires-Dist: retrying==1.3.4
58
+ Requires-Dist: retrying==1.4.2
58
59
  Requires-Dist: python-dotenv==1.0.1
59
60
  Requires-Dist: cloudpickle>=3.1.1
60
61
  Requires-Dist: httpx==0.28.1
@@ -869,7 +870,7 @@ agent_config = AgentConfig(
869
870
  main_llm_provider = ModelProvider.ANTHROPIC,
870
871
  main_llm_model_name = 'claude-3-5-sonnet-20241022',
871
872
  tool_llm_provider = ModelProvider.TOGETHER,
872
- tool_llm_model_name = 'meta-llama/Llama-3.3-70B-Instruct-Turbo'
873
+ tool_llm_model_name = 'deepseek-ai/DeepSeek-V3'
873
874
  )
874
875
 
875
876
  agent = Agent(
@@ -795,7 +795,7 @@ agent_config = AgentConfig(
795
795
  main_llm_provider = ModelProvider.ANTHROPIC,
796
796
  main_llm_model_name = 'claude-3-5-sonnet-20241022',
797
797
  tool_llm_provider = ModelProvider.TOGETHER,
798
- tool_llm_model_name = 'meta-llama/Llama-3.3-70B-Instruct-Turbo'
798
+ tool_llm_model_name = 'deepseek-ai/DeepSeek-V3'
799
799
  )
800
800
 
801
801
  agent = Agent(
@@ -1,16 +1,17 @@
1
- llama-index==0.13.2
2
- llama-index-core==0.13.2
1
+ llama-index==0.13.3
2
+ llama-index-core==0.13.3
3
3
  llama-index-workflows==1.3.0
4
4
  llama-index-cli==0.5.0
5
5
  llama-index-indices-managed-vectara==0.5.0
6
- llama-index-llms-openai==0.5.2
6
+ llama-index-llms-openai==0.5.4
7
7
  llama-index-llms-openai-like==0.5.0
8
- llama-index-llms-anthropic==0.8.2
8
+ llama-index-llms-anthropic==0.8.5
9
9
  llama-index-llms-together==0.4.0
10
10
  llama-index-llms-groq==0.4.0
11
11
  llama-index-llms-cohere==0.6.0
12
12
  llama-index-llms-google-genai==0.3.0
13
- llama-index-llms-bedrock-converse==0.8.0
13
+ google_genai>=1.31.0
14
+ llama-index-llms-bedrock-converse==0.8.2
14
15
  llama-index-tools-yahoo-finance==0.4.0
15
16
  llama-index-tools-arxiv==0.4.0
16
17
  llama-index-tools-database==0.4.0
@@ -36,7 +37,7 @@ protobuf==5.29.5
36
37
  tokenizers>=0.20
37
38
  pydantic>=2.11.5
38
39
  pandas==2.2.3
39
- retrying==1.3.4
40
+ retrying==1.4.2
40
41
  python-dotenv==1.0.1
41
42
  cloudpickle>=3.1.1
42
43
  httpx==0.28.1
@@ -8,6 +8,8 @@ import threading
8
8
 
9
9
  from vectara_agentic.agent import Agent
10
10
  from vectara_agentic.tools import ToolsFactory
11
+ from vectara_agentic.agent_config import AgentConfig
12
+ from vectara_agentic.types import AgentType, ModelProvider
11
13
 
12
14
  import nest_asyncio
13
15
 
@@ -64,6 +66,38 @@ class TestGROQ(unittest.IsolatedAsyncioTestCase):
64
66
 
65
67
  self.assertEqual(response3.response, "1050")
66
68
 
69
+ async def test_gpt_oss_120b(self):
70
+ """Test GPT-OSS-120B model with GROQ provider."""
71
+ with ARIZE_LOCK:
72
+ # Create config specifically for GPT-OSS-120B via GROQ
73
+ gpt_oss_config = AgentConfig(
74
+ agent_type=AgentType.FUNCTION_CALLING,
75
+ main_llm_provider=ModelProvider.GROQ,
76
+ main_llm_model_name="openai/gpt-oss-120b",
77
+ tool_llm_provider=ModelProvider.GROQ,
78
+ tool_llm_model_name="openai/gpt-oss-120b",
79
+ )
80
+
81
+ tools = [ToolsFactory().create_tool(mult)]
82
+ agent = Agent(
83
+ agent_config=gpt_oss_config,
84
+ tools=tools,
85
+ topic=STANDARD_TEST_TOPIC,
86
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
87
+ )
88
+
89
+ # Test simple multiplication: 8 * 6 = 48
90
+ stream = await agent.astream_chat(
91
+ "What is 8 times 6? Only give the answer, nothing else"
92
+ )
93
+ # Consume the stream
94
+ async for chunk in stream.async_response_gen():
95
+ pass
96
+ response = await stream.aget_response()
97
+
98
+ # Verify the response contains the correct answer
99
+ self.assertIn("48", response.response)
100
+
67
101
 
68
102
  if __name__ == "__main__":
69
103
  unittest.main()
@@ -0,0 +1,160 @@
1
+ # Suppress external dependency warnings before any other imports
2
+ import warnings
3
+
4
+ warnings.simplefilter("ignore", DeprecationWarning)
5
+
6
+ import unittest
7
+ import threading
8
+
9
+ from vectara_agentic.agent import Agent
10
+ from vectara_agentic.tools import ToolsFactory
11
+ from vectara_agentic.agent_config import AgentConfig
12
+ from vectara_agentic.types import AgentType, ModelProvider
13
+
14
+ import nest_asyncio
15
+
16
+ nest_asyncio.apply()
17
+
18
+ from conftest import (
19
+ fc_config_openai,
20
+ mult,
21
+ STANDARD_TEST_TOPIC,
22
+ STANDARD_TEST_INSTRUCTIONS,
23
+ )
24
+
25
+
26
+ ARIZE_LOCK = threading.Lock()
27
+
28
+
29
+ class TestOpenAI(unittest.IsolatedAsyncioTestCase):
30
+
31
+ async def test_multiturn(self):
32
+ """Test multi-turn conversation with default OpenAI model."""
33
+ with ARIZE_LOCK:
34
+ tools = [ToolsFactory().create_tool(mult)]
35
+ agent = Agent(
36
+ agent_config=fc_config_openai,
37
+ tools=tools,
38
+ topic=STANDARD_TEST_TOPIC,
39
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
40
+ )
41
+
42
+ # First calculation: 5 * 10 = 50
43
+ stream1 = await agent.astream_chat(
44
+ "What is 5 times 10. Only give the answer, nothing else"
45
+ )
46
+ # Consume the stream
47
+ async for chunk in stream1.async_response_gen():
48
+ pass
49
+ _ = await stream1.aget_response()
50
+
51
+ # Second calculation: 3 * 7 = 21
52
+ stream2 = await agent.astream_chat(
53
+ "what is 3 times 7. Only give the answer, nothing else"
54
+ )
55
+ # Consume the stream
56
+ async for chunk in stream2.async_response_gen():
57
+ pass
58
+ _ = await stream2.aget_response()
59
+
60
+ # Final calculation: 50 * 21 = 1050
61
+ stream3 = await agent.astream_chat(
62
+ "multiply the results of the last two questions. Output only the answer."
63
+ )
64
+ # Consume the stream
65
+ async for chunk in stream3.async_response_gen():
66
+ pass
67
+ response3 = await stream3.aget_response()
68
+
69
+ self.assertEqual(response3.response, "1050")
70
+
71
+ async def test_gpt_4o(self):
72
+ """Test GPT-4o model with OpenAI provider."""
73
+ with ARIZE_LOCK:
74
+ config = AgentConfig(
75
+ agent_type=AgentType.FUNCTION_CALLING,
76
+ main_llm_provider=ModelProvider.OPENAI,
77
+ main_llm_model_name="gpt-4o",
78
+ tool_llm_provider=ModelProvider.OPENAI,
79
+ tool_llm_model_name="gpt-4o",
80
+ )
81
+
82
+ tools = [ToolsFactory().create_tool(mult)]
83
+ agent = Agent(
84
+ agent_config=config,
85
+ tools=tools,
86
+ topic=STANDARD_TEST_TOPIC,
87
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
88
+ )
89
+
90
+ # Test simple multiplication: 4 * 3 = 12
91
+ stream = await agent.astream_chat(
92
+ "What is 4 times 3? Only give the answer, nothing else"
93
+ )
94
+ async for chunk in stream.async_response_gen():
95
+ pass
96
+ response = await stream.aget_response()
97
+
98
+ self.assertIn("12", response.response)
99
+
100
+ async def test_gpt_4_1(self):
101
+ """Test GPT-4.1 model with OpenAI provider."""
102
+ with ARIZE_LOCK:
103
+ config = AgentConfig(
104
+ agent_type=AgentType.FUNCTION_CALLING,
105
+ main_llm_provider=ModelProvider.OPENAI,
106
+ main_llm_model_name="gpt-4.1",
107
+ tool_llm_provider=ModelProvider.OPENAI,
108
+ tool_llm_model_name="gpt-4.1",
109
+ )
110
+
111
+ tools = [ToolsFactory().create_tool(mult)]
112
+ agent = Agent(
113
+ agent_config=config,
114
+ tools=tools,
115
+ topic=STANDARD_TEST_TOPIC,
116
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
117
+ )
118
+
119
+ # Test simple multiplication: 6 * 2 = 12
120
+ stream = await agent.astream_chat(
121
+ "What is 6 times 2? Only give the answer, nothing else"
122
+ )
123
+ async for chunk in stream.async_response_gen():
124
+ pass
125
+ response = await stream.aget_response()
126
+
127
+ self.assertIn("12", response.response)
128
+
129
+ async def test_gpt_5_minimal_reasoning(self):
130
+ """Test GPT-5 model with minimal reasoning effort."""
131
+ with ARIZE_LOCK:
132
+ config = AgentConfig(
133
+ agent_type=AgentType.FUNCTION_CALLING,
134
+ main_llm_provider=ModelProvider.OPENAI,
135
+ main_llm_model_name="gpt-5",
136
+ tool_llm_provider=ModelProvider.OPENAI,
137
+ tool_llm_model_name="gpt-5",
138
+ )
139
+
140
+ tools = [ToolsFactory().create_tool(mult)]
141
+ agent = Agent(
142
+ agent_config=config,
143
+ tools=tools,
144
+ topic=STANDARD_TEST_TOPIC,
145
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
146
+ )
147
+
148
+ # Test simple multiplication: 5 * 5 = 25
149
+ stream = await agent.astream_chat(
150
+ "What is 5 times 5? Only give the answer, nothing else"
151
+ )
152
+ async for chunk in stream.async_response_gen():
153
+ pass
154
+ response = await stream.aget_response()
155
+
156
+ self.assertIn("25", response.response)
157
+
158
+
159
+ if __name__ == "__main__":
160
+ unittest.main()
@@ -4,7 +4,6 @@ import warnings
4
4
  warnings.simplefilter("ignore", DeprecationWarning)
5
5
 
6
6
  import unittest
7
- import asyncio
8
7
 
9
8
  from vectara_agentic.agent import Agent
10
9
  from vectara_agentic.tools import ToolsFactory
@@ -14,7 +13,6 @@ import nest_asyncio
14
13
  nest_asyncio.apply()
15
14
 
16
15
  from conftest import (
17
- fc_config_openai,
18
16
  fc_config_anthropic,
19
17
  mult,
20
18
  STANDARD_TEST_TOPIC,
@@ -62,48 +60,6 @@ class TestAgentStreaming(unittest.IsolatedAsyncioTestCase):
62
60
 
63
61
  self.assertIn("1050", response3.response)
64
62
 
65
- async def test_openai(self):
66
- tools = [ToolsFactory().create_tool(mult)]
67
- agent = Agent(
68
- agent_config=fc_config_openai,
69
- tools=tools,
70
- topic=STANDARD_TEST_TOPIC,
71
- custom_instructions=STANDARD_TEST_INSTRUCTIONS,
72
- )
73
-
74
- # First calculation: 5 * 10 = 50
75
- stream1 = await agent.astream_chat(
76
- "What is 5 times 10. Only give the answer, nothing else"
77
- )
78
- # Consume the stream
79
- async for chunk in stream1.async_response_gen():
80
- pass
81
- _ = await stream1.aget_response()
82
-
83
- # Second calculation: 3 * 7 = 21
84
- stream2 = await agent.astream_chat(
85
- "what is 3 times 7. Only give the answer, nothing else"
86
- )
87
- # Consume the stream
88
- async for chunk in stream2.async_response_gen():
89
- pass
90
- _ = await stream2.aget_response()
91
-
92
- # Final calculation: 50 * 21 = 1050
93
- stream3 = await agent.astream_chat(
94
- "multiply the results of the last two multiplications. Only give the answer, nothing else."
95
- )
96
- # Consume the stream
97
- async for chunk in stream3.async_response_gen():
98
- pass
99
- response3 = await stream3.aget_response()
100
-
101
- self.assertIn("1050", response3.response)
102
-
103
- def test_openai_sync(self):
104
- """Synchronous wrapper for the async test"""
105
- asyncio.run(self.test_openai())
106
-
107
63
 
108
64
  if __name__ == "__main__":
109
65
  unittest.main()
@@ -0,0 +1,136 @@
1
+ # Suppress external dependency warnings before any other imports
2
+ import warnings
3
+
4
+ warnings.simplefilter("ignore", DeprecationWarning)
5
+
6
+ import unittest
7
+ import threading
8
+
9
+ from vectara_agentic.agent import Agent
10
+ from vectara_agentic.tools import ToolsFactory
11
+
12
+ import nest_asyncio
13
+
14
+ nest_asyncio.apply()
15
+
16
+ from conftest import (
17
+ fc_config_together,
18
+ mult,
19
+ STANDARD_TEST_TOPIC,
20
+ STANDARD_TEST_INSTRUCTIONS,
21
+ )
22
+ from vectara_agentic.agent_config import AgentConfig
23
+ from vectara_agentic.types import AgentType, ModelProvider
24
+
25
+
26
+ ARIZE_LOCK = threading.Lock()
27
+
28
+
29
+ class TestTogether(unittest.IsolatedAsyncioTestCase):
30
+
31
+ async def test_multiturn(self):
32
+ with ARIZE_LOCK:
33
+ tools = [ToolsFactory().create_tool(mult)]
34
+ agent = Agent(
35
+ agent_config=fc_config_together,
36
+ tools=tools,
37
+ topic=STANDARD_TEST_TOPIC,
38
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
39
+ )
40
+
41
+ # First calculation: 5 * 10 = 50
42
+ stream1 = await agent.astream_chat(
43
+ "What is 5 times 10. Only give the answer, nothing else"
44
+ )
45
+ # Consume the stream
46
+ async for chunk in stream1.async_response_gen():
47
+ pass
48
+ _ = await stream1.aget_response()
49
+
50
+ # Second calculation: 3 * 7 = 21
51
+ stream2 = await agent.astream_chat(
52
+ "what is 3 times 7. Only give the answer, nothing else"
53
+ )
54
+ # Consume the stream
55
+ async for chunk in stream2.async_response_gen():
56
+ pass
57
+ _ = await stream2.aget_response()
58
+
59
+ # Final calculation: 50 * 21 = 1050
60
+ stream3 = await agent.astream_chat(
61
+ "multiply the results of the last two questions. Output only the answer."
62
+ )
63
+ # Consume the stream
64
+ async for chunk in stream3.async_response_gen():
65
+ pass
66
+ response3 = await stream3.aget_response()
67
+
68
+ self.assertEqual(response3.response, "1050")
69
+
70
+ async def test_qwen3_coder(self):
71
+ """Test Qwen3-Coder-480B-A35B-Instruct-FP8 model with Together AI provider."""
72
+ with ARIZE_LOCK:
73
+ # Create config specifically for Qwen3-Coder
74
+ qwen_config = AgentConfig(
75
+ agent_type=AgentType.FUNCTION_CALLING,
76
+ main_llm_provider=ModelProvider.TOGETHER,
77
+ main_llm_model_name="Qwen/Qwen3-235B-A22B-fp8-tput",
78
+ tool_llm_provider=ModelProvider.TOGETHER,
79
+ tool_llm_model_name="Qwen/Qwen3-235B-A22B-fp8-tput",
80
+ )
81
+
82
+ tools = [ToolsFactory().create_tool(mult)]
83
+ agent = Agent(
84
+ agent_config=qwen_config,
85
+ tools=tools,
86
+ topic=STANDARD_TEST_TOPIC,
87
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
88
+ )
89
+
90
+ # Test simple multiplication: 7 * 9 = 63
91
+ stream = await agent.astream_chat(
92
+ "What is 7 times 9? Only give the answer, nothing else"
93
+ )
94
+ # Consume the stream
95
+ async for chunk in stream.async_response_gen():
96
+ pass
97
+ response = await stream.aget_response()
98
+
99
+ # Verify the response contains the correct answer
100
+ self.assertIn("63", response.response)
101
+
102
+ async def test_llama4_scout(self):
103
+ """Test Llama-4-Scout-17B-16E-Instruct model with Together AI provider."""
104
+ with ARIZE_LOCK:
105
+ # Create config specifically for Llama 4 Scout
106
+ llama4_config = AgentConfig(
107
+ agent_type=AgentType.FUNCTION_CALLING,
108
+ main_llm_provider=ModelProvider.TOGETHER,
109
+ main_llm_model_name="meta-llama/Llama-4-Scout-17B-16E-Instruct",
110
+ tool_llm_provider=ModelProvider.TOGETHER,
111
+ tool_llm_model_name="meta-llama/Llama-4-Scout-17B-16E-Instruct",
112
+ )
113
+
114
+ tools = [ToolsFactory().create_tool(mult)]
115
+ agent = Agent(
116
+ agent_config=llama4_config,
117
+ tools=tools,
118
+ topic=STANDARD_TEST_TOPIC,
119
+ custom_instructions=STANDARD_TEST_INSTRUCTIONS,
120
+ )
121
+
122
+ # Test simple multiplication: 8 * 6 = 48
123
+ stream = await agent.astream_chat(
124
+ "What is 8 times 6? Only give the answer, nothing else"
125
+ )
126
+ # Consume the stream
127
+ async for chunk in stream.async_response_gen():
128
+ pass
129
+ response = await stream.aget_response()
130
+
131
+ # Verify the response contains the correct answer
132
+ self.assertIn("48", response.response)
133
+
134
+
135
+ if __name__ == "__main__":
136
+ unittest.main()
@@ -1,4 +1,4 @@
1
1
  """
2
2
  Define the version of the package.
3
3
  """
4
- __version__ = "0.4.3"
4
+ __version__ = "0.4.5"
@@ -18,14 +18,51 @@ from .agent_config import AgentConfig
18
18
 
19
19
  provider_to_default_model_name = {
20
20
  ModelProvider.OPENAI: "gpt-4.1-mini",
21
- ModelProvider.ANTHROPIC: "claude-sonnet-4-20250514",
21
+ ModelProvider.ANTHROPIC: "claude-sonnet-4-0",
22
22
  ModelProvider.TOGETHER: "deepseek-ai/DeepSeek-V3",
23
23
  ModelProvider.GROQ: "openai/gpt-oss-20b",
24
24
  ModelProvider.BEDROCK: "us.anthropic.claude-sonnet-4-20250514-v1:0",
25
25
  ModelProvider.COHERE: "command-a-03-2025",
26
- ModelProvider.GEMINI: "models/gemini-2.5-flash-lite",
26
+ ModelProvider.GEMINI: "models/gemini-2.5-flash",
27
27
  }
28
28
 
29
+ models_to_max_tokens = {
30
+ "gpt-5": 128000,
31
+ "gpt-5-mini": 128000,
32
+ "gpt-4.1": 32768,
33
+ "gpt-4o": 16384,
34
+ "gpt-4.1-mini": 32768,
35
+ "claude-sonnet-4-20250514": 64000,
36
+ "claude-sonnet-4-0": 64000,
37
+ "deepseek-ai/deepseek-v3": 8192,
38
+ "models/gemini-2.5-flash": 65536,
39
+ "models/gemini-2.5-flash-lite": 65536,
40
+ "models/gemini-2.5-pro": 65536,
41
+ "openai/gpt-oss-20b": 65536,
42
+ "openai/gpt-oss-120b": 65536,
43
+ "us.anthropic.claude-sonnet-4-20250514-v1:0": 64000,
44
+ "command-a-03-2025": 8192,
45
+ }
46
+
47
+
48
+ def get_max_tokens(model_name: str, model_provider: str) -> int:
49
+ """Get the maximum token limit for a given model name and provider."""
50
+ if model_provider in [
51
+ ModelProvider.GEMINI,
52
+ ModelProvider.TOGETHER,
53
+ ModelProvider.OPENAI,
54
+ ModelProvider.ANTHROPIC,
55
+ ModelProvider.GROQ,
56
+ ModelProvider.BEDROCK,
57
+ ModelProvider.COHERE,
58
+ ]:
59
+ # Try exact match first (case-insensitive)
60
+ max_tokens = models_to_max_tokens.get(model_name.lower(), 16384)
61
+ else:
62
+ max_tokens = 8192
63
+ return max_tokens
64
+
65
+
29
66
  DEFAULT_MODEL_PROVIDER = ModelProvider.OPENAI
30
67
 
31
68
  # Manual cache for LLM instances to handle mutable AgentConfig objects
@@ -94,19 +131,11 @@ def get_llm(role: LLMRole, config: Optional[AgentConfig] = None) -> LLM:
94
131
  if cache_key in _llm_cache:
95
132
  return _llm_cache[cache_key]
96
133
  model_provider, model_name = _get_llm_params_for_role(role, config)
97
- max_tokens = (
98
- 16384
99
- if model_provider
100
- in [
101
- ModelProvider.GEMINI,
102
- ModelProvider.TOGETHER,
103
- ModelProvider.OPENAI,
104
- ModelProvider.ANTHROPIC,
105
- ]
106
- else 8192
107
- )
134
+ max_tokens = get_max_tokens(model_name, model_provider)
108
135
  if model_provider == ModelProvider.OPENAI:
109
- additional_kwargs = {"reasoning_effort": "minimal"} if model_name.startswith("gpt-5") else {}
136
+ additional_kwargs = (
137
+ {"reasoning_effort": "minimal"} if model_name.startswith("gpt-5") else {}
138
+ )
110
139
  llm = OpenAI(
111
140
  model=model_name,
112
141
  temperature=0,
@@ -129,11 +158,20 @@ def get_llm(role: LLMRole, config: Optional[AgentConfig] = None) -> LLM:
129
158
  raise ImportError(
130
159
  "google_genai not available. Install with: pip install llama-index-llms-google-genai"
131
160
  ) from e
161
+ import google.genai.types as google_types
162
+ generation_config = google_types.GenerateContentConfig(
163
+ temperature=0.0,
164
+ seed=123,
165
+ max_output_tokens=max_tokens,
166
+ thinking_config=google_types.ThinkingConfig(thinking_budget=0, include_thoughts=False),
167
+ )
132
168
  llm = GoogleGenAI(
133
169
  model=model_name,
134
170
  temperature=0,
135
171
  is_function_calling_model=True,
136
172
  max_tokens=max_tokens,
173
+ generation_config=generation_config,
174
+ context_window=1_000_000,
137
175
  )
138
176
  elif model_provider == ModelProvider.TOGETHER:
139
177
  try:
@@ -142,11 +180,19 @@ def get_llm(role: LLMRole, config: Optional[AgentConfig] = None) -> LLM:
142
180
  raise ImportError(
143
181
  "together not available. Install with: pip install llama-index-llms-together"
144
182
  ) from e
183
+ additional_kwargs = {"seed": 42}
184
+ if model_name in [
185
+ "deepseek-ai/DeepSeek-V3.1", "openai/gpt-oss-120b",
186
+ "deepseek-ai/DeepSeek-R1", "Qwen/Qwen3-235B-A22B-Thinking-2507"
187
+ "openai/gpt-oss-120b", "openai/gpt-oss-20b",
188
+ ]:
189
+ additional_kwargs['reasoning_effort'] = "low"
145
190
  llm = TogetherLLM(
146
191
  model=model_name,
147
192
  temperature=0,
148
193
  is_function_calling_model=True,
149
194
  max_tokens=max_tokens,
195
+ additional_kwargs=additional_kwargs,
150
196
  )
151
197
  elif model_provider == ModelProvider.GROQ:
152
198
  try:
@@ -193,7 +239,11 @@ def get_llm(role: LLMRole, config: Optional[AgentConfig] = None) -> LLM:
193
239
  raise ImportError(
194
240
  "openai_like not available. Install with: pip install llama-index-llms-openai-like"
195
241
  ) from e
196
- if not config or not config.private_llm_api_base or not config.private_llm_api_key:
242
+ if (
243
+ not config
244
+ or not config.private_llm_api_base
245
+ or not config.private_llm_api_key
246
+ ):
197
247
  raise ValueError(
198
248
  "Private LLM requires both private_llm_api_base and private_llm_api_key to be set in AgentConfig."
199
249
  )
@@ -3,12 +3,12 @@ This module contains the ToolsFactory class for creating agent tools.
3
3
  """
4
4
 
5
5
  import inspect
6
- import re
7
6
  import importlib
8
7
  import os
9
8
  import asyncio
10
-
11
9
  from typing import Callable, List, Dict, Any, Optional, Union
10
+
11
+ from retrying import retry
12
12
  from pydantic import BaseModel, Field
13
13
 
14
14
  from llama_index.core.tools import FunctionTool
@@ -65,6 +65,18 @@ LI_packages = {
65
65
  }
66
66
 
67
67
 
68
+ @retry(stop_max_attempt_number=3, wait_exponential_multiplier=1000, wait_exponential_max=10000)
69
+ def _query_with_retry(vectara_query_engine, query):
70
+ """Execute Vectara query with automatic retry on timeout/failure."""
71
+ return vectara_query_engine.query(query)
72
+
73
+
74
+ @retry(stop_max_attempt_number=3, wait_exponential_multiplier=1000, wait_exponential_max=10000)
75
+ def _retrieve_with_retry(vectara_retriever, query):
76
+ """Execute Vectara retrieve with automatic retry on timeout/failure."""
77
+ return vectara_retriever.retrieve(query)
78
+
79
+
68
80
  class VectaraToolFactory:
69
81
  """
70
82
  A factory class for creating Vectara RAG tools.
@@ -165,6 +177,7 @@ class VectaraToolFactory:
165
177
  vectara_base_url=vectara_base_url,
166
178
  vectara_verify_ssl=vectara_verify_ssl,
167
179
  )
180
+ vectara.vectara_api_timeout = 10
168
181
 
169
182
  # Dynamically generate the search function
170
183
  def search_function(*args: Any, **kwargs: Any) -> list[dict]:
@@ -220,7 +233,7 @@ class VectaraToolFactory:
220
233
  x_source_str="vectara-agentic",
221
234
  verbose=verbose,
222
235
  )
223
- response = vectara_retriever.retrieve(query)
236
+ response = _retrieve_with_retry(vectara_retriever, query)
224
237
 
225
238
  if len(response) == 0:
226
239
  msg = "Vectara Tool failed to retrieve any results for the query."
@@ -370,6 +383,7 @@ class VectaraToolFactory:
370
383
  save_history: bool = False,
371
384
  fcs_threshold: float = 0.0,
372
385
  return_direct: bool = False,
386
+ return_human_readable_output: bool = False,
373
387
  verbose: bool = False,
374
388
  vectara_base_url: str = "https://api.vectara.io",
375
389
  vectara_verify_ssl: bool = True,
@@ -432,6 +446,7 @@ class VectaraToolFactory:
432
446
  fcs_threshold (float, optional): A threshold for factual consistency.
433
447
  If set above 0, the tool notifies the calling agent that it "cannot respond" if FCS is too low.
434
448
  return_direct (bool, optional): Whether the agent should return the tool's response directly.
449
+ return_human_readable_output (bool, optional): Whether to return the output in a human-readable format.
435
450
  verbose (bool, optional): Whether to print verbose output.
436
451
  vectara_base_url (str, optional): The base URL for the Vectara API.
437
452
  vectara_verify_ssl (bool, optional): Whether to verify SSL certificates for the Vectara API.
@@ -447,6 +462,7 @@ class VectaraToolFactory:
447
462
  vectara_base_url=vectara_base_url,
448
463
  vectara_verify_ssl=vectara_verify_ssl,
449
464
  )
465
+ vectara.vectara_api_timeout = 60
450
466
  keys_to_ignore = ["lang", "offset", "len"]
451
467
 
452
468
  # Dynamically generate the RAG function
@@ -473,7 +489,7 @@ class VectaraToolFactory:
473
489
  )
474
490
  return {"text": msg, "metadata": {"args": args, "kwargs": kwargs}}
475
491
 
476
- citations_url_pattern = (
492
+ computed_citations_url_pattern = (
477
493
  (
478
494
  citation_url_pattern
479
495
  if citation_url_pattern is not None
@@ -482,6 +498,8 @@ class VectaraToolFactory:
482
498
  if include_citations
483
499
  else None
484
500
  )
501
+ computed_citations_text_pattern = citation_text_pattern if include_citations else None
502
+
485
503
  vectara_query_engine = vectara.as_query_engine(
486
504
  summary_enabled=True,
487
505
  similarity_top_k=summary_num_results,
@@ -514,15 +532,13 @@ class VectaraToolFactory:
514
532
  frequency_penalty=frequency_penalty,
515
533
  presence_penalty=presence_penalty,
516
534
  citations_style="markdown" if include_citations else None,
517
- citations_url_pattern=citations_url_pattern,
518
- citations_text_pattern=(
519
- citation_text_pattern if include_citations else None
520
- ),
535
+ citations_url_pattern=computed_citations_url_pattern,
536
+ citations_text_pattern=computed_citations_text_pattern,
521
537
  save_history=save_history,
522
538
  x_source_str="vectara-agentic",
523
539
  verbose=verbose,
524
540
  )
525
- response = vectara_query_engine.query(query)
541
+ response = _query_with_retry(vectara_query_engine, query)
526
542
 
527
543
  if len(response.source_nodes) == 0:
528
544
  msg = (
@@ -536,20 +552,6 @@ class VectaraToolFactory:
536
552
  kwargs["query"] = query
537
553
  return {"text": msg, "metadata": {"args": args, "kwargs": kwargs}}
538
554
 
539
- # Extract citation metadata
540
- pattern = r"\[(\d+)\]"
541
- matches = re.findall(pattern, response.response)
542
- citation_numbers = sorted(set(int(match) for match in matches))
543
- citation_metadata = {}
544
- for citation_number in citation_numbers:
545
- metadata = {
546
- k: v
547
- for k, v in response.source_nodes[
548
- citation_number - 1
549
- ].metadata.items()
550
- if k not in keys_to_ignore
551
- }
552
- citation_metadata[str(citation_number)] = metadata
553
555
  fcs = 0.0
554
556
  fcs_str = response.metadata["fcs"] if "fcs" in response.metadata else "0.0"
555
557
  if fcs_str and is_float(fcs_str):
@@ -560,16 +562,71 @@ class VectaraToolFactory:
560
562
  "text": msg,
561
563
  "metadata": {"args": args, "kwargs": kwargs, "fcs": fcs},
562
564
  }
563
- if fcs:
564
- citation_metadata["fcs"] = fcs
565
- res = {"text": response.response, "metadata": citation_metadata}
566
565
 
567
- # Create human-readable output with citation formatting
568
- def format_rag_response(result):
569
- text = result["text"]
570
- return text
566
+ # Add source nodes to tool output
567
+ if ((not return_human_readable_output) and
568
+ (computed_citations_url_pattern is not None) and
569
+ (computed_citations_text_pattern is not None)):
570
+ response_text = str(response.response)
571
+ citation_metadata = []
572
+
573
+ # Converts a dictionary to an object with .<field> access
574
+ def to_obj(data):
575
+ return type('obj', (object,), data)()
576
+
577
+ for source_node in response.source_nodes:
578
+ node = source_node.node
579
+ node_id = node.id_
580
+ node_text = (
581
+ node.text_resource.text if hasattr(node, 'text_resource')
582
+ else getattr(node, 'text', '')
583
+ )
584
+ node_metadata = getattr(node, 'metadata', {})
585
+ for key in keys_to_ignore:
586
+ if key in node_metadata:
587
+ del node_metadata[key]
588
+
589
+ try:
590
+ template_data = {}
591
+
592
+ doc_data = node_metadata.get('document', {})
593
+ template_data['doc'] = to_obj(doc_data)
594
+
595
+ part_data = {k: v for k, v in node_metadata.items() if k != 'document'}
596
+ template_data['part'] = to_obj(part_data)
597
+
598
+ formatted_citation_text = computed_citations_text_pattern.format(**template_data)
599
+ formatted_citation_url = computed_citations_url_pattern.format(**template_data)
600
+ expected_citation = f"[{formatted_citation_text}]({formatted_citation_url})"
601
+
602
+ if expected_citation in response_text:
603
+ citation_metadata.append({
604
+ 'doc_id': node_id,
605
+ 'text': node_text,
606
+ 'metadata': node_metadata,
607
+ 'score': getattr(node, 'score', None)
608
+ })
609
+
610
+ except Exception as e:
611
+ if verbose:
612
+ print(f"Could not format citation for search result {node_id}: {e}")
613
+ continue
614
+
615
+ res = {"text": response.response, "citations": citation_metadata}
616
+ if fcs:
617
+ res["fcs"] = fcs
618
+ else:
619
+ res = {"text": response.response}
620
+
621
+ # Create human-readable output
622
+ if return_human_readable_output:
623
+ def format_rag_response(result):
624
+ text = result["text"]
625
+ return text
626
+
627
+ return create_human_readable_output(res, format_rag_response)
571
628
 
572
- return create_human_readable_output(res, format_rag_response)
629
+ return res
573
630
 
574
631
  class RagToolBaseParams(BaseModel):
575
632
  """Model for the base parameters of the RAG tool."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectara_agentic
3
- Version: 0.4.3
3
+ Version: 0.4.5
4
4
  Summary: A Python package for creating AI Assistants and AI Agents with Vectara
5
5
  Home-page: https://github.com/vectara/py-vectara-agentic
6
6
  Author: Ofer Mendelevitch
@@ -16,19 +16,20 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: llama-index==0.13.2
20
- Requires-Dist: llama-index-core==0.13.2
19
+ Requires-Dist: llama-index==0.13.3
20
+ Requires-Dist: llama-index-core==0.13.3
21
21
  Requires-Dist: llama-index-workflows==1.3.0
22
22
  Requires-Dist: llama-index-cli==0.5.0
23
23
  Requires-Dist: llama-index-indices-managed-vectara==0.5.0
24
- Requires-Dist: llama-index-llms-openai==0.5.2
24
+ Requires-Dist: llama-index-llms-openai==0.5.4
25
25
  Requires-Dist: llama-index-llms-openai-like==0.5.0
26
- Requires-Dist: llama-index-llms-anthropic==0.8.2
26
+ Requires-Dist: llama-index-llms-anthropic==0.8.5
27
27
  Requires-Dist: llama-index-llms-together==0.4.0
28
28
  Requires-Dist: llama-index-llms-groq==0.4.0
29
29
  Requires-Dist: llama-index-llms-cohere==0.6.0
30
30
  Requires-Dist: llama-index-llms-google-genai==0.3.0
31
- Requires-Dist: llama-index-llms-bedrock-converse==0.8.0
31
+ Requires-Dist: google_genai>=1.31.0
32
+ Requires-Dist: llama-index-llms-bedrock-converse==0.8.2
32
33
  Requires-Dist: llama-index-tools-yahoo-finance==0.4.0
33
34
  Requires-Dist: llama-index-tools-arxiv==0.4.0
34
35
  Requires-Dist: llama-index-tools-database==0.4.0
@@ -54,7 +55,7 @@ Requires-Dist: protobuf==5.29.5
54
55
  Requires-Dist: tokenizers>=0.20
55
56
  Requires-Dist: pydantic>=2.11.5
56
57
  Requires-Dist: pandas==2.2.3
57
- Requires-Dist: retrying==1.3.4
58
+ Requires-Dist: retrying==1.4.2
58
59
  Requires-Dist: python-dotenv==1.0.1
59
60
  Requires-Dist: cloudpickle>=3.1.1
60
61
  Requires-Dist: httpx==0.28.1
@@ -869,7 +870,7 @@ agent_config = AgentConfig(
869
870
  main_llm_provider = ModelProvider.ANTHROPIC,
870
871
  main_llm_model_name = 'claude-3-5-sonnet-20241022',
871
872
  tool_llm_provider = ModelProvider.TOGETHER,
872
- tool_llm_model_name = 'meta-llama/Llama-3.3-70B-Instruct-Turbo'
873
+ tool_llm_model_name = 'deepseek-ai/DeepSeek-V3'
873
874
  )
874
875
 
875
876
  agent = Agent(
@@ -17,6 +17,7 @@ tests/test_bedrock.py
17
17
  tests/test_fallback.py
18
18
  tests/test_gemini.py
19
19
  tests/test_groq.py
20
+ tests/test_openai.py
20
21
  tests/test_private_llm.py
21
22
  tests/test_react_error_handling.py
22
23
  tests/test_react_memory.py
@@ -1,16 +1,17 @@
1
- llama-index==0.13.2
2
- llama-index-core==0.13.2
1
+ llama-index==0.13.3
2
+ llama-index-core==0.13.3
3
3
  llama-index-workflows==1.3.0
4
4
  llama-index-cli==0.5.0
5
5
  llama-index-indices-managed-vectara==0.5.0
6
- llama-index-llms-openai==0.5.2
6
+ llama-index-llms-openai==0.5.4
7
7
  llama-index-llms-openai-like==0.5.0
8
- llama-index-llms-anthropic==0.8.2
8
+ llama-index-llms-anthropic==0.8.5
9
9
  llama-index-llms-together==0.4.0
10
10
  llama-index-llms-groq==0.4.0
11
11
  llama-index-llms-cohere==0.6.0
12
12
  llama-index-llms-google-genai==0.3.0
13
- llama-index-llms-bedrock-converse==0.8.0
13
+ google_genai>=1.31.0
14
+ llama-index-llms-bedrock-converse==0.8.2
14
15
  llama-index-tools-yahoo-finance==0.4.0
15
16
  llama-index-tools-arxiv==0.4.0
16
17
  llama-index-tools-database==0.4.0
@@ -36,7 +37,7 @@ protobuf==5.29.5
36
37
  tokenizers>=0.20
37
38
  pydantic>=2.11.5
38
39
  pandas==2.2.3
39
- retrying==1.3.4
40
+ retrying==1.4.2
40
41
  python-dotenv==1.0.1
41
42
  cloudpickle>=3.1.1
42
43
  httpx==0.28.1
@@ -1,70 +0,0 @@
1
- # Suppress external dependency warnings before any other imports
2
- import warnings
3
-
4
- warnings.simplefilter("ignore", DeprecationWarning)
5
-
6
- import unittest
7
- import threading
8
-
9
- from vectara_agentic.agent import Agent
10
- from vectara_agentic.tools import ToolsFactory
11
-
12
- import nest_asyncio
13
-
14
- nest_asyncio.apply()
15
-
16
- from conftest import (
17
- fc_config_together,
18
- mult,
19
- STANDARD_TEST_TOPIC,
20
- STANDARD_TEST_INSTRUCTIONS,
21
- )
22
-
23
-
24
- ARIZE_LOCK = threading.Lock()
25
-
26
-
27
- class TestTogether(unittest.IsolatedAsyncioTestCase):
28
-
29
- async def test_multiturn(self):
30
- with ARIZE_LOCK:
31
- tools = [ToolsFactory().create_tool(mult)]
32
- agent = Agent(
33
- agent_config=fc_config_together,
34
- tools=tools,
35
- topic=STANDARD_TEST_TOPIC,
36
- custom_instructions=STANDARD_TEST_INSTRUCTIONS,
37
- )
38
-
39
- # First calculation: 5 * 10 = 50
40
- stream1 = await agent.astream_chat(
41
- "What is 5 times 10. Only give the answer, nothing else"
42
- )
43
- # Consume the stream
44
- async for chunk in stream1.async_response_gen():
45
- pass
46
- _ = await stream1.aget_response()
47
-
48
- # Second calculation: 3 * 7 = 21
49
- stream2 = await agent.astream_chat(
50
- "what is 3 times 7. Only give the answer, nothing else"
51
- )
52
- # Consume the stream
53
- async for chunk in stream2.async_response_gen():
54
- pass
55
- _ = await stream2.aget_response()
56
-
57
- # Final calculation: 50 * 21 = 1050
58
- stream3 = await agent.astream_chat(
59
- "multiply the results of the last two questions. Output only the answer."
60
- )
61
- # Consume the stream
62
- async for chunk in stream3.async_response_gen():
63
- pass
64
- response3 = await stream3.aget_response()
65
-
66
- self.assertEqual(response3.response, "1050")
67
-
68
-
69
- if __name__ == "__main__":
70
- unittest.main()
File without changes