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.
- {vectara_agentic-0.2.5/vectara_agentic.egg-info → vectara_agentic-0.2.7}/PKG-INFO +10 -9
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/requirements.txt +7 -7
- vectara_agentic-0.2.7/tests/test_agent.py +162 -0
- vectara_agentic-0.2.7/tests/test_agent_planning.py +73 -0
- vectara_agentic-0.2.7/tests/test_agent_type.py +157 -0
- vectara_agentic-0.2.7/tests/test_fallback.py +83 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/test_private_llm.py +11 -10
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/test_tools.py +1 -1
- vectara_agentic-0.2.7/tests/test_workflow.py +67 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_observability.py +1 -1
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_prompts.py +5 -5
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_version.py +1 -1
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent.py +226 -111
- vectara_agentic-0.2.7/vectara_agentic/sub_query_workflow.py +304 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/tools.py +97 -74
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/types.py +6 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/utils.py +50 -11
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7/vectara_agentic.egg-info}/PKG-INFO +10 -9
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/SOURCES.txt +1 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/requires.txt +7 -7
- vectara_agentic-0.2.5/tests/test_agent.py +0 -140
- vectara_agentic-0.2.5/tests/test_agent_planning.py +0 -46
- vectara_agentic-0.2.5/tests/test_agent_type.py +0 -63
- vectara_agentic-0.2.5/tests/test_workflow.py +0 -42
- vectara_agentic-0.2.5/vectara_agentic/sub_query_workflow.py +0 -165
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/LICENSE +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/MANIFEST.in +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/README.md +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/setup.cfg +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/setup.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/__init__.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/tests/endpoint.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/__init__.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/_callback.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent_config.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/agent_endpoint.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/db_tools.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic/tools_catalog.py +0 -0
- {vectara_agentic-0.2.5 → vectara_agentic-0.2.7}/vectara_agentic.egg-info/dependency_links.txt +0 -0
- {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.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: vectara_agentic
|
|
3
|
-
Version: 0.2.
|
|
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.
|
|
45
|
-
Requires-Dist: opentelemetry-proto==1.
|
|
46
|
-
Requires-Dist: arize-phoenix==
|
|
47
|
-
Requires-Dist: arize-phoenix-otel==0.
|
|
48
|
-
Requires-Dist: protobuf==
|
|
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.
|
|
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.
|
|
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.
|
|
27
|
-
opentelemetry-proto==1.
|
|
28
|
-
arize-phoenix==
|
|
29
|
-
arize-phoenix-otel==0.
|
|
30
|
-
protobuf==
|
|
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.
|
|
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.
|
|
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=
|
|
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:
|
|
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:
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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__":
|
|
@@ -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()
|