vectara-agentic 0.2.5__tar.gz → 0.2.7__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 (40) hide show
  1. {vectara_agentic-0.2.5/vectara_agentic.egg-info → vectara_agentic-0.2.7}/PKG-INFO +10 -9
  2. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/requirements.txt +7 -7
  3. vectara_agentic-0.2.7/tests/test_agent.py +162 -0
  4. vectara_agentic-0.2.7/tests/test_agent_planning.py +73 -0
  5. vectara_agentic-0.2.7/tests/test_agent_type.py +157 -0
  6. vectara_agentic-0.2.7/tests/test_fallback.py +83 -0
  7. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/test_private_llm.py +11 -10
  8. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/test_tools.py +1 -1
  9. vectara_agentic-0.2.7/tests/test_workflow.py +67 -0
  10. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_observability.py +1 -1
  11. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_prompts.py +5 -5
  12. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_version.py +1 -1
  13. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent.py +226 -111
  14. vectara_agentic-0.2.7/vectara_agentic/sub_query_workflow.py +304 -0
  15. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/tools.py +97 -74
  16. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/types.py +6 -0
  17. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/utils.py +50 -11
  18. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7/vectara_agentic.egg-info}/PKG-INFO +10 -9
  19. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/SOURCES.txt +1 -0
  20. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/requires.txt +7 -7
  21. vectara_agentic-0.2.5/tests/test_agent.py +0 -140
  22. vectara_agentic-0.2.5/tests/test_agent_planning.py +0 -46
  23. vectara_agentic-0.2.5/tests/test_agent_type.py +0 -63
  24. vectara_agentic-0.2.5/tests/test_workflow.py +0 -42
  25. vectara_agentic-0.2.5/vectara_agentic/sub_query_workflow.py +0 -165
  26. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/LICENSE +0 -0
  27. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/MANIFEST.in +0 -0
  28. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/README.md +0 -0
  29. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/setup.cfg +0 -0
  30. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/setup.py +0 -0
  31. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/__init__.py +0 -0
  32. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/endpoint.py +0 -0
  33. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/__init__.py +0 -0
  34. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_callback.py +0 -0
  35. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent_config.py +0 -0
  36. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent_endpoint.py +0 -0
  37. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/db_tools.py +0 -0
  38. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/tools_catalog.py +0 -0
  39. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/dependency_links.txt +0 -0
  40. {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: vectara_agentic
3
- Version: 0.2.5
3
+ Version: 0.2.7
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
@@ -41,18 +41,18 @@ Requires-Dist: llama-index-tools-exa==0.3.0
41
41
  Requires-Dist: tavily-python==0.5.1
42
42
  Requires-Dist: exa-py==1.8.9
43
43
  Requires-Dist: yahoo-finance==1.4.0
44
- Requires-Dist: openinference-instrumentation-llama-index==3.1.4
45
- Requires-Dist: opentelemetry-proto==1.26.0
46
- Requires-Dist: arize-phoenix==7.11.0
47
- Requires-Dist: arize-phoenix-otel==0.6.1
48
- Requires-Dist: protobuf==4.25.5
44
+ Requires-Dist: openinference-instrumentation-llama-index==3.3.3
45
+ Requires-Dist: opentelemetry-proto==1.31.0
46
+ Requires-Dist: arize-phoenix==8.14.1
47
+ Requires-Dist: arize-phoenix-otel==0.8.0
48
+ Requires-Dist: protobuf==5.29.3
49
49
  Requires-Dist: tokenizers>=0.20
50
- Requires-Dist: pydantic==2.10.3
50
+ Requires-Dist: pydantic==2.10.6
51
51
  Requires-Dist: retrying==1.3.4
52
52
  Requires-Dist: python-dotenv==1.0.1
53
53
  Requires-Dist: tiktoken==0.9.0
54
54
  Requires-Dist: cloudpickle>=3.1.1
55
- Requires-Dist: httpx==0.27.2
55
+ Requires-Dist: httpx==0.28.1
56
56
  Dynamic: author
57
57
  Dynamic: author-email
58
58
  Dynamic: classifier
@@ -60,6 +60,7 @@ Dynamic: description
60
60
  Dynamic: description-content-type
61
61
  Dynamic: home-page
62
62
  Dynamic: keywords
63
+ Dynamic: license-file
63
64
  Dynamic: project-url
64
65
  Dynamic: requires-dist
65
66
  Dynamic: requires-python
@@ -23,15 +23,15 @@ llama-index-tools-exa==0.3.0
23
23
  tavily-python==0.5.1
24
24
  exa-py==1.8.9
25
25
  yahoo-finance==1.4.0
26
- openinference-instrumentation-llama-index==3.1.4
27
- opentelemetry-proto==1.26.0
28
- arize-phoenix==7.11.0
29
- arize-phoenix-otel==0.6.1
30
- protobuf==4.25.5
26
+ openinference-instrumentation-llama-index==3.3.3
27
+ opentelemetry-proto==1.31.0
28
+ arize-phoenix==8.14.1
29
+ arize-phoenix-otel==0.8.0
30
+ protobuf==5.29.3
31
31
  tokenizers>=0.20
32
- pydantic==2.10.3
32
+ pydantic==2.10.6
33
33
  retrying==1.3.4
34
34
  python-dotenv==1.0.1
35
35
  tiktoken==0.9.0
36
36
  cloudpickle>=3.1.1
37
- httpx==0.27.2
37
+ httpx==0.28.1
@@ -0,0 +1,162 @@
1
+ import unittest
2
+ import threading
3
+ from datetime import date
4
+
5
+ from vectara_agentic.agent import _get_prompt, Agent, AgentType
6
+ from vectara_agentic.agent_config import AgentConfig
7
+ from vectara_agentic.types import ModelProvider, ObserverType
8
+ from vectara_agentic.tools import ToolsFactory
9
+
10
+ def mult(x: float, y: float) -> float:
11
+ return x * y
12
+
13
+
14
+ ARIZE_LOCK = threading.Lock()
15
+
16
+ class TestAgentPackage(unittest.TestCase):
17
+ def test_get_prompt(self):
18
+ prompt_template = "{chat_topic} on {today} with {custom_instructions}"
19
+ topic = "Programming"
20
+ custom_instructions = "Always do as your mother tells you!"
21
+ expected_output = (
22
+ "Programming on "
23
+ + date.today().strftime("%A, %B %d, %Y")
24
+ + " with Always do as your mother tells you!"
25
+ )
26
+ self.assertEqual(
27
+ _get_prompt(prompt_template, topic, custom_instructions), expected_output
28
+ )
29
+
30
+ def test_agent_init(self):
31
+ tools = [ToolsFactory().create_tool(mult)]
32
+ topic = "AI"
33
+ custom_instructions = "Always do as your mother tells you!"
34
+ agent = Agent(tools, topic, custom_instructions)
35
+ self.assertEqual(agent.agent_type, AgentType.OPENAI)
36
+ self.assertEqual(agent._topic, topic)
37
+ self.assertEqual(agent._custom_instructions, custom_instructions)
38
+
39
+ # To run this test, you must have OPENAI_API_KEY in your environment
40
+ self.assertEqual(
41
+ agent.chat(
42
+ "What is 5 times 10. Only give the answer, nothing else"
43
+ ).response.replace("$", "\\$"),
44
+ "50",
45
+ )
46
+
47
+ def test_agent_config(self):
48
+ with ARIZE_LOCK:
49
+ tools = [ToolsFactory().create_tool(mult)]
50
+ topic = "AI topic"
51
+ instructions = "Always do as your father tells you, if your mother agrees!"
52
+ config = AgentConfig(
53
+ agent_type=AgentType.REACT,
54
+ main_llm_provider=ModelProvider.ANTHROPIC,
55
+ main_llm_model_name="claude-3-5-sonnet-20241022",
56
+ tool_llm_provider=ModelProvider.TOGETHER,
57
+ tool_llm_model_name="meta-llama/Llama-3.3-70B-Instruct-Turbo",
58
+ observer=ObserverType.ARIZE_PHOENIX
59
+ )
60
+
61
+ agent = Agent(
62
+ tools=tools,
63
+ topic=topic,
64
+ custom_instructions=instructions,
65
+ agent_config=config
66
+ )
67
+ self.assertEqual(agent._topic, topic)
68
+ self.assertEqual(agent._custom_instructions, instructions)
69
+ self.assertEqual(agent.agent_type, AgentType.REACT)
70
+ self.assertEqual(agent.agent_config.observer, ObserverType.ARIZE_PHOENIX)
71
+ self.assertEqual(agent.agent_config.main_llm_provider, ModelProvider.ANTHROPIC)
72
+ self.assertEqual(agent.agent_config.tool_llm_provider, ModelProvider.TOGETHER)
73
+
74
+ # To run this test, you must have ANTHROPIC_API_KEY and TOGETHER_API_KEY in your environment
75
+ self.assertEqual(
76
+ agent.chat(
77
+ "What is 5 times 10. Only give the answer, nothing else"
78
+ ).response.replace("$", "\\$"),
79
+ "50",
80
+ )
81
+
82
+ def test_multiturn(self):
83
+ tools = [ToolsFactory().create_tool(mult)]
84
+ topic = "AI topic"
85
+ instructions = "Always do as your father tells you, if your mother agrees!"
86
+ agent = Agent(
87
+ tools=tools,
88
+ topic=topic,
89
+ custom_instructions=instructions,
90
+ )
91
+
92
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
93
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
94
+ res = agent.chat("multiply the results of the last two questions. Output only the answer.")
95
+ self.assertEqual(res.response, "1050")
96
+
97
+ def test_from_corpus(self):
98
+ agent = Agent.from_corpus(
99
+ tool_name="RAG Tool",
100
+ vectara_corpus_key="corpus_key",
101
+ vectara_api_key="api_key",
102
+ data_description="information",
103
+ assistant_specialty="question answering",
104
+ )
105
+
106
+ self.assertIsInstance(agent, Agent)
107
+ self.assertEqual(agent._topic, "question answering")
108
+
109
+ def test_serialization(self):
110
+ with ARIZE_LOCK:
111
+ config = AgentConfig(
112
+ agent_type=AgentType.REACT,
113
+ main_llm_provider=ModelProvider.ANTHROPIC,
114
+ tool_llm_provider=ModelProvider.TOGETHER,
115
+ observer=ObserverType.ARIZE_PHOENIX
116
+ )
117
+
118
+ agent = Agent.from_corpus(
119
+ tool_name="RAG Tool",
120
+ agent_config=config,
121
+ vectara_corpus_key="corpus_key",
122
+ vectara_api_key="api_key",
123
+ data_description="information",
124
+ assistant_specialty="question answering",
125
+ )
126
+
127
+ agent_reloaded = agent.loads(agent.dumps())
128
+ agent_reloaded_again = agent_reloaded.loads(agent_reloaded.dumps())
129
+
130
+ self.assertIsInstance(agent_reloaded, Agent)
131
+ self.assertEqual(agent, agent_reloaded)
132
+ self.assertEqual(agent.agent_type, agent_reloaded.agent_type)
133
+
134
+ self.assertEqual(agent.agent_config.observer, agent_reloaded.agent_config.observer)
135
+ self.assertEqual(agent.agent_config.main_llm_provider, agent_reloaded.agent_config.main_llm_provider)
136
+ self.assertEqual(agent.agent_config.tool_llm_provider, agent_reloaded.agent_config.tool_llm_provider)
137
+
138
+ self.assertIsInstance(agent_reloaded, Agent)
139
+ self.assertEqual(agent, agent_reloaded_again)
140
+ self.assertEqual(agent.agent_type, agent_reloaded_again.agent_type)
141
+
142
+ self.assertEqual(agent.agent_config.observer, agent_reloaded_again.agent_config.observer)
143
+ self.assertEqual(agent.agent_config.main_llm_provider, agent_reloaded_again.agent_config.main_llm_provider)
144
+ self.assertEqual(agent.agent_config.tool_llm_provider, agent_reloaded_again.agent_config.tool_llm_provider)
145
+
146
+ def test_chat_history(self):
147
+ tools = [ToolsFactory().create_tool(mult)]
148
+ topic = "AI topic"
149
+ instructions = "Always do as your father tells you, if your mother agrees!"
150
+ agent = Agent(
151
+ tools=tools,
152
+ topic=topic,
153
+ custom_instructions=instructions,
154
+ chat_history=[("What is 5 times 10", "50"), ("What is 3 times 7", "21")]
155
+ )
156
+
157
+ res = agent.chat("multiply the results of the last two questions. Output only the answer.")
158
+ self.assertEqual(res.response, "1050")
159
+
160
+
161
+ if __name__ == "__main__":
162
+ unittest.main()
@@ -0,0 +1,73 @@
1
+ import unittest
2
+
3
+ from vectara_agentic.agent_config import AgentConfig
4
+ from vectara_agentic.agent import Agent
5
+ from vectara_agentic.tools import VectaraToolFactory
6
+
7
+ from pydantic import Field, BaseModel
8
+
9
+
10
+ # SETUP speical test account credentials for vectara
11
+ # It's okay to expose these credentials in the test code
12
+ vectara_corpus_key = "vectara-docs_1"
13
+ vectara_api_key = 'zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA'
14
+
15
+
16
+ class QueryArgs(BaseModel):
17
+ query: str = Field(..., description="The user query, always in the form of a question.")
18
+
19
+
20
+ vec_factory = VectaraToolFactory(vectara_api_key=vectara_api_key,
21
+ vectara_corpus_key=vectara_corpus_key)
22
+ summarizer = 'vectara-summary-table-md-query-ext-jan-2025-gpt-4o'
23
+ ask_vectara = vec_factory.create_rag_tool(
24
+ tool_name = "ask_vectara",
25
+ tool_description = "This tool can respond to questions about Vectara.",
26
+ tool_args_schema = QueryArgs,
27
+ reranker = "multilingual_reranker_v1", rerank_k = 100, rerank_cutoff = 0.1,
28
+ n_sentences_before = 2, n_sentences_after = 2, lambda_val = 0.005,
29
+ summary_num_results = 10,
30
+ vectara_summarizer = summarizer,
31
+ include_citations = True,
32
+ verbose=False,
33
+ )
34
+
35
+ class TestAgentPlanningPackage(unittest.TestCase):
36
+
37
+ def test_no_planning(self):
38
+ tools = [ask_vectara]
39
+ topic = "vectara"
40
+ instructions = "Answer user queries about Vectara."
41
+
42
+ query = "What is Vectara and what demos are available of the Vectara platform?"
43
+ agent = Agent(
44
+ tools=tools,
45
+ topic=topic,
46
+ custom_instructions=instructions,
47
+ agent_config=AgentConfig(),
48
+ )
49
+ res = agent.chat(query)
50
+ self.assertIn("demos", res.response)
51
+ self.assertIn("Vectara", res.response)
52
+
53
+ def test_structured_planning(self):
54
+ tools = [ask_vectara]
55
+ topic = "vectara"
56
+ instructions = "Answer user queries about Vectara."
57
+
58
+ query = "What is Vectara and what demos are available of the Vectara platform?"
59
+ agent = Agent(
60
+ tools=tools,
61
+ topic=topic,
62
+ custom_instructions=instructions,
63
+ agent_config=AgentConfig(),
64
+ use_structured_planning=True,
65
+ )
66
+
67
+ res = agent.chat(query)
68
+ self.assertIn("demos", res.response)
69
+ self.assertIn("Vectara", res.response)
70
+
71
+
72
+ if __name__ == "__main__":
73
+ unittest.main()
@@ -0,0 +1,157 @@
1
+ import unittest
2
+
3
+ from vectara_agentic.agent import Agent, AgentType
4
+ from vectara_agentic.agent_config import AgentConfig
5
+ from vectara_agentic.tools import ToolsFactory
6
+ from vectara_agentic.types import ModelProvider
7
+
8
+ import nest_asyncio
9
+ nest_asyncio.apply()
10
+
11
+ def mult(x: float, y: float) -> float:
12
+ return x * y
13
+
14
+
15
+ react_config_anthropic = AgentConfig(
16
+ agent_type=AgentType.REACT,
17
+ main_llm_provider=ModelProvider.ANTHROPIC,
18
+ tool_llm_provider=ModelProvider.ANTHROPIC,
19
+ )
20
+
21
+ react_config_gemini = AgentConfig(
22
+ agent_type=AgentType.REACT,
23
+ main_llm_provider=ModelProvider.GEMINI,
24
+ tool_llm_provider=ModelProvider.GEMINI,
25
+ )
26
+
27
+ react_config_together = AgentConfig(
28
+ agent_type=AgentType.REACT,
29
+ main_llm_provider=ModelProvider.TOGETHER,
30
+ tool_llm_provider=ModelProvider.TOGETHER,
31
+ )
32
+
33
+ fc_config_anthropic = AgentConfig(
34
+ agent_type=AgentType.FUNCTION_CALLING,
35
+ main_llm_provider=ModelProvider.ANTHROPIC,
36
+ tool_llm_provider=ModelProvider.ANTHROPIC,
37
+ )
38
+
39
+ fc_config_gemini = AgentConfig(
40
+ agent_type=AgentType.FUNCTION_CALLING,
41
+ main_llm_provider=ModelProvider.GEMINI,
42
+ tool_llm_provider=ModelProvider.GEMINI,
43
+ )
44
+
45
+ fc_config_together = AgentConfig(
46
+ agent_type=AgentType.FUNCTION_CALLING,
47
+ main_llm_provider=ModelProvider.TOGETHER,
48
+ tool_llm_provider=ModelProvider.TOGETHER,
49
+ )
50
+
51
+
52
+ openai_config = AgentConfig(
53
+ agent_type=AgentType.OPENAI,
54
+ )
55
+
56
+ class TestAgentType(unittest.TestCase):
57
+
58
+ def test_openai(self):
59
+ tools = [ToolsFactory().create_tool(mult)]
60
+ topic = "AI topic"
61
+ instructions = "Always do as your father tells you, if your mother agrees!"
62
+ agent = Agent(
63
+ agent_config=openai_config,
64
+ tools=tools,
65
+ topic=topic,
66
+ custom_instructions=instructions,
67
+ )
68
+
69
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
70
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
71
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
72
+ self.assertIn("1050", res.response)
73
+
74
+ def test_gemini(self):
75
+ tools = [ToolsFactory().create_tool(mult)]
76
+ topic = "AI topic"
77
+ instructions = "Always do as your father tells you, if your mother agrees!"
78
+
79
+ agent = Agent(
80
+ agent_config=react_config_gemini,
81
+ tools=tools,
82
+ topic=topic,
83
+ custom_instructions=instructions,
84
+ )
85
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
86
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
87
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
88
+ self.assertIn("1050", res.response)
89
+
90
+ agent = Agent(
91
+ agent_config=fc_config_gemini,
92
+ tools=tools,
93
+ topic=topic,
94
+ custom_instructions=instructions,
95
+ )
96
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
97
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
98
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
99
+ self.assertIn("1050", res.response)
100
+
101
+ def test_together(self):
102
+ tools = [ToolsFactory().create_tool(mult)]
103
+ topic = "AI topic"
104
+ instructions = "Always do as your father tells you, if your mother agrees!"
105
+
106
+ agent = Agent(
107
+ agent_config=react_config_together,
108
+ tools=tools,
109
+ topic=topic,
110
+ custom_instructions=instructions,
111
+ )
112
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
113
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
114
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
115
+ self.assertIn("1050", res.response)
116
+
117
+ agent = Agent(
118
+ agent_config=fc_config_together,
119
+ tools=tools,
120
+ topic=topic,
121
+ custom_instructions=instructions,
122
+ )
123
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
124
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
125
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
126
+ self.assertIn("1050", res.response)
127
+
128
+ def test_anthropic(self):
129
+ tools = [ToolsFactory().create_tool(mult)]
130
+ topic = "AI topic"
131
+ instructions = "Always do as your father tells you, if your mother agrees!"
132
+
133
+ agent = Agent(
134
+ agent_config=react_config_anthropic,
135
+ tools=tools,
136
+ topic=topic,
137
+ custom_instructions=instructions,
138
+ )
139
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
140
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
141
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
142
+ self.assertIn("1050", res.response)
143
+
144
+ agent = Agent(
145
+ agent_config=fc_config_anthropic,
146
+ tools=tools,
147
+ topic=topic,
148
+ custom_instructions=instructions,
149
+ )
150
+ agent.chat("What is 5 times 10. Only give the answer, nothing else")
151
+ agent.chat("what is 3 times 7. Only give the answer, nothing else")
152
+ res = agent.chat("multiply the results of the last two multiplications. Only give the answer, nothing else.")
153
+ self.assertIn("1050", res.response)
154
+
155
+
156
+ if __name__ == "__main__":
157
+ unittest.main()
@@ -0,0 +1,83 @@
1
+ import os
2
+ import unittest
3
+ import subprocess
4
+ import time
5
+ import requests
6
+ import signal
7
+
8
+ from vectara_agentic.agent import Agent, AgentType
9
+ from vectara_agentic.agent_config import AgentConfig
10
+ from vectara_agentic.types import ModelProvider, AgentConfigType
11
+ from vectara_agentic.tools import ToolsFactory
12
+
13
+ FLASK_PORT = 5002
14
+
15
+ class TestFallback(unittest.TestCase):
16
+
17
+ @classmethod
18
+ def setUp(cls):
19
+ # Start the Flask server as a subprocess
20
+ cls.flask_process = subprocess.Popen(
21
+ ['flask', 'run', f'--port={FLASK_PORT}'],
22
+ env={**os.environ, 'FLASK_APP': 'tests.endpoint:app', 'FLASK_ENV': 'development'},
23
+ stdout=None, stderr=None,
24
+ )
25
+ # Wait for the server to start
26
+ timeout = 10
27
+ url = f'http://127.0.0.1:{FLASK_PORT}/'
28
+ for _ in range(timeout):
29
+ try:
30
+ requests.get(url)
31
+ print("Flask server started for fallback unit test")
32
+ return
33
+ except requests.ConnectionError:
34
+ time.sleep(1)
35
+ raise RuntimeError(f"Failed to start Flask server at {url}")
36
+
37
+ @classmethod
38
+ def tearDown(cls):
39
+ # Terminate the Flask server
40
+ cls.flask_process.send_signal(signal.SIGINT)
41
+ cls.flask_process.wait()
42
+
43
+ def test_fallback_from_private(self):
44
+ def mult(x: float, y: float) -> float:
45
+ return x * y
46
+
47
+ tools = [ToolsFactory().create_tool(mult)]
48
+ topic = "calculator"
49
+ custom_instructions = "you are an agent specializing in math, assisting a user."
50
+ config = AgentConfig(
51
+ agent_type=AgentType.REACT,
52
+ main_llm_provider=ModelProvider.PRIVATE,
53
+ main_llm_model_name="gpt-4o",
54
+ private_llm_api_base=f"http://127.0.0.1:{FLASK_PORT}/v1",
55
+ private_llm_api_key="TEST_API_KEY",
56
+ )
57
+
58
+ # Set fallback agent config to OpenAI agent
59
+ fallback_config = AgentConfig()
60
+
61
+ agent = Agent(agent_config=config, tools=tools, topic=topic,
62
+ custom_instructions=custom_instructions,
63
+ fallback_agent_config=fallback_config)
64
+
65
+ # To run this test, you must have OPENAI_API_KEY in your environment
66
+ res = agent.chat(
67
+ "What is 5 times 10. Only give the answer, nothing else"
68
+ ).response
69
+ self.assertEqual(res, "50")
70
+
71
+ TestFallback.flask_process.send_signal(signal.SIGINT)
72
+ TestFallback.flask_process.wait()
73
+
74
+ res = agent.chat(
75
+ "What is 5 times 10. Only give the answer, nothing else"
76
+ ).response
77
+ self.assertEqual(res, "50")
78
+ self.assertEqual(agent.agent_config_type, AgentConfigType.FALLBACK)
79
+ self.assertEqual(agent.fallback_agent_config, fallback_config)
80
+
81
+
82
+ if __name__ == "__main__":
83
+ unittest.main()
@@ -10,22 +10,25 @@ from vectara_agentic.agent_config import AgentConfig
10
10
  from vectara_agentic.types import ModelProvider
11
11
  from vectara_agentic.tools import ToolsFactory
12
12
 
13
+
14
+ FLASK_PORT = 5001
13
15
  class TestPrivateLLM(unittest.TestCase):
14
16
 
15
17
  @classmethod
16
18
  def setUp(cls):
17
19
  # Start the Flask server as a subprocess
18
20
  cls.flask_process = subprocess.Popen(
19
- ['flask', 'run', '--port=5000'],
21
+ ['flask', 'run', f'--port={FLASK_PORT}'],
20
22
  env={**os.environ, 'FLASK_APP': 'tests.endpoint:app', 'FLASK_ENV': 'development'},
21
23
  stdout=None, stderr=None,
22
24
  )
23
25
  # Wait for the server to start
24
26
  timeout = 10
25
- url = 'http://127.0.0.1:5000/'
27
+ url = f'http://127.0.0.1:{FLASK_PORT}/'
26
28
  for _ in range(timeout):
27
29
  try:
28
30
  requests.get(url)
31
+ print("Flask server started for private LLM unit test")
29
32
  return
30
33
  except requests.ConnectionError:
31
34
  time.sleep(1)
@@ -38,7 +41,7 @@ class TestPrivateLLM(unittest.TestCase):
38
41
  cls.flask_process.wait()
39
42
 
40
43
  def test_endpoint(self):
41
- def mult(x, y):
44
+ def mult(x: float, y: float) -> float:
42
45
  return x * y
43
46
 
44
47
  tools = [ToolsFactory().create_tool(mult)]
@@ -48,19 +51,17 @@ class TestPrivateLLM(unittest.TestCase):
48
51
  agent_type=AgentType.REACT,
49
52
  main_llm_provider=ModelProvider.PRIVATE,
50
53
  main_llm_model_name="gpt-4o",
51
- private_llm_api_base="http://127.0.0.1:5000/v1",
54
+ private_llm_api_base=f"http://127.0.0.1:{FLASK_PORT}/v1",
52
55
  private_llm_api_key="TEST_API_KEY",
53
56
  )
54
57
  agent = Agent(agent_config=config, tools=tools, topic=topic,
55
58
  custom_instructions=custom_instructions)
56
59
 
57
60
  # To run this test, you must have OPENAI_API_KEY in your environment
58
- self.assertEqual(
59
- agent.chat(
60
- "What is 5 times 10. Only give the answer, nothing else"
61
- ).response.replace("$", "\\$"),
62
- "50",
63
- )
61
+ res = agent.chat(
62
+ "What is 5 times 10. Only give the answer, nothing else."
63
+ ).response
64
+ self.assertEqual(res, "50")
64
65
 
65
66
 
66
67
  if __name__ == "__main__":
@@ -47,7 +47,7 @@ class TestToolsPackage(unittest.TestCase):
47
47
  self.assertEqual(search_tool.metadata.tool_type, ToolType.QUERY)
48
48
 
49
49
  def test_tool_factory(self):
50
- def mult(x, y):
50
+ def mult(x: float, y: float) -> float:
51
51
  return x * y
52
52
 
53
53
  tools_factory = ToolsFactory()
@@ -0,0 +1,67 @@
1
+ import unittest
2
+
3
+ from vectara_agentic.agent import Agent
4
+ from vectara_agentic.agent_config import AgentConfig
5
+ from vectara_agentic.tools import ToolsFactory
6
+ from vectara_agentic.sub_query_workflow import SubQuestionQueryWorkflow, SequentialSubQuestionsWorkflow
7
+
8
+ def mult(x: float, y: float):
9
+ """
10
+ Multiply two numbers.
11
+ """
12
+ return x * y
13
+
14
+ def add(x: float, y: float):
15
+ """
16
+ Add two numbers.
17
+ """
18
+ return x + y
19
+
20
+ class TestWorkflowPackage(unittest.IsolatedAsyncioTestCase):
21
+
22
+ async def test_sub_query_workflow(self):
23
+ tools = [ToolsFactory().create_tool(mult)] + [ToolsFactory().create_tool(add)]
24
+ topic = "AI topic"
25
+ instructions = "You are a helpful AI assistant."
26
+ agent = Agent(
27
+ tools=tools,
28
+ topic=topic,
29
+ custom_instructions=instructions,
30
+ agent_config = AgentConfig(),
31
+ workflow_cls = SubQuestionQueryWorkflow,
32
+ )
33
+
34
+ inputs = SubQuestionQueryWorkflow.InputsModel(
35
+ query="Compute 5 times 3, then add 7 to the result."
36
+ )
37
+ res = await agent.run(inputs=inputs)
38
+ self.assertIn("22", res.response)
39
+
40
+ inputs = SubQuestionQueryWorkflow.InputsModel(
41
+ query="what is the sum of 10 with 21, and the multiplication of 3 and 6?"
42
+ )
43
+ res = await agent.run(inputs=inputs)
44
+ self.assertIn("31", res.response)
45
+ self.assertIn("18", res.response)
46
+
47
+ async def test_seq_sub_query_workflow(self):
48
+ tools = [ToolsFactory().create_tool(mult)] + [ToolsFactory().create_tool(add)]
49
+ topic = "AI topic"
50
+ instructions = "You are a helpful AI assistant."
51
+ agent = Agent(
52
+ tools=tools,
53
+ topic=topic,
54
+ custom_instructions=instructions,
55
+ agent_config = AgentConfig(),
56
+ workflow_cls = SequentialSubQuestionsWorkflow,
57
+ )
58
+
59
+ inputs = SequentialSubQuestionsWorkflow.InputsModel(
60
+ query="Compute 5 times 3, then add 7 to the result."
61
+ )
62
+ res = await agent.run(inputs=inputs, verbose=True)
63
+ self.assertIn("22", res.response)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ unittest.main()