vectara-agentic 0.2.16__tar.gz → 0.2.18__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.16/vectara_agentic.egg-info → vectara_agentic-0.2.18}/PKG-INFO +62 -18
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/README.md +52 -11
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/requirements.txt +9 -6
- vectara_agentic-0.2.18/tests/test_api_endpoint.py +126 -0
- vectara_agentic-0.2.18/tests/test_gemini.py +115 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_groq.py +0 -7
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_tools.py +9 -33
- vectara_agentic-0.2.18/tests/test_workflow.py +134 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/_version.py +1 -1
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/agent.py +50 -28
- vectara_agentic-0.2.18/vectara_agentic/agent_endpoint.py +252 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/llm_utils.py +0 -17
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/sub_query_workflow.py +5 -2
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/tool_utils.py +3 -43
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/tools.py +2 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/utils.py +1 -1
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18/vectara_agentic.egg-info}/PKG-INFO +62 -18
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic.egg-info/SOURCES.txt +2 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic.egg-info/requires.txt +9 -6
- vectara_agentic-0.2.16/tests/test_workflow.py +0 -67
- vectara_agentic-0.2.16/vectara_agentic/agent_endpoint.py +0 -62
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/LICENSE +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/MANIFEST.in +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/setup.cfg +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/setup.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/__init__.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/endpoint.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_agent.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_agent_planning.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_agent_type.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_fallback.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_private_llm.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_return_direct.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_serialization.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/tests/test_vectara_llms.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/__init__.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/_callback.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/_observability.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/_prompts.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/agent_config.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/db_tools.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/tools_catalog.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic/types.py +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/vectara_agentic.egg-info/dependency_links.txt +0 -0
- {vectara_agentic-0.2.16 → vectara_agentic-0.2.18}/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.2.
|
|
3
|
+
Version: 0.2.18
|
|
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,12 +16,13 @@ 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.12.
|
|
19
|
+
Requires-Dist: llama-index==0.12.35
|
|
20
20
|
Requires-Dist: llama-index-indices-managed-vectara==0.4.5
|
|
21
21
|
Requires-Dist: llama-index-agent-llm-compiler==0.3.0
|
|
22
22
|
Requires-Dist: llama-index-agent-lats==0.3.0
|
|
23
|
-
Requires-Dist: llama-index-agent-openai==0.4.
|
|
24
|
-
Requires-Dist: llama-index-llms-openai==0.3.
|
|
23
|
+
Requires-Dist: llama-index-agent-openai==0.4.8
|
|
24
|
+
Requires-Dist: llama-index-llms-openai==0.3.42
|
|
25
|
+
Requires-Dist: llama-index-llms-openai-like>=0.3.5
|
|
25
26
|
Requires-Dist: llama-index-llms-anthropic==0.6.10
|
|
26
27
|
Requires-Dist: llama-index-llms-together==0.3.1
|
|
27
28
|
Requires-Dist: llama-index-llms-groq==0.3.1
|
|
@@ -36,15 +37,17 @@ Requires-Dist: llama-index-tools-google==0.3.0
|
|
|
36
37
|
Requires-Dist: llama-index-tools-tavily_research==0.3.0
|
|
37
38
|
Requires-Dist: llama_index.tools.brave_search==0.3.0
|
|
38
39
|
Requires-Dist: llama-index-tools-neo4j==0.3.0
|
|
40
|
+
Requires-Dist: llama-index-tools-waii==0.3.0
|
|
39
41
|
Requires-Dist: llama-index-graph-stores-kuzu==0.7.0
|
|
42
|
+
Requires-Dist: llama-index-tools-salesforce==0.3.0
|
|
40
43
|
Requires-Dist: llama-index-tools-slack==0.3.0
|
|
41
44
|
Requires-Dist: llama-index-tools-exa==0.3.0
|
|
42
45
|
Requires-Dist: llama-index-tools-wikipedia==0.3.0
|
|
43
46
|
Requires-Dist: llama-index-tools-bing-search==0.3.0
|
|
44
|
-
Requires-Dist: tavily-python==0.
|
|
45
|
-
Requires-Dist: exa-py==1.12.
|
|
47
|
+
Requires-Dist: tavily-python==0.7.2
|
|
48
|
+
Requires-Dist: exa-py==1.12.1
|
|
46
49
|
Requires-Dist: openinference-instrumentation-llama-index==4.2.1
|
|
47
|
-
Requires-Dist: opentelemetry-proto
|
|
50
|
+
Requires-Dist: opentelemetry-proto>=1.31.0
|
|
48
51
|
Requires-Dist: arize-phoenix==8.26.1
|
|
49
52
|
Requires-Dist: arize-phoenix-otel==0.9.2
|
|
50
53
|
Requires-Dist: protobuf==5.29.3
|
|
@@ -365,51 +368,92 @@ vectara-agentic includes various other tools from LlamaIndex ToolSpecs:
|
|
|
365
368
|
* Tavily Search: Real-time web search using [Tavily API](https://tavily.com/)
|
|
366
369
|
```python
|
|
367
370
|
from vectara_agentic.tools_catalog import ToolsCatalog
|
|
368
|
-
|
|
371
|
+
tools_factory = ToolsFactory()
|
|
372
|
+
tavily_tools = tools_factory.get_llama_index_tools(
|
|
373
|
+
tool_package_name="tavily_research",
|
|
374
|
+
tool_spec_name="TavilyToolSpec",
|
|
375
|
+
api_key=str(os.environ["TAVILY_API_KEY"]),
|
|
376
|
+
)
|
|
369
377
|
```
|
|
370
378
|
* EXA.AI: Advanced web search and data extraction
|
|
371
379
|
```python
|
|
372
|
-
|
|
380
|
+
exa_tools = tools_factory.get_llama_index_tools(
|
|
381
|
+
tool_package_name="exa.ai",
|
|
382
|
+
tool_spec_name="ExaToolSpec",
|
|
383
|
+
api_key=str(os.environ["EXA_API_KEY"]),
|
|
384
|
+
)
|
|
373
385
|
```
|
|
374
386
|
* Brave Search: Web search using Brave's search engine
|
|
375
387
|
```python
|
|
376
|
-
|
|
388
|
+
brave_tools = tools_factory.get_llama_index_tools(
|
|
389
|
+
tool_package_name="brave_search",
|
|
390
|
+
tool_spec_name="BraveSearchToolSpec",
|
|
391
|
+
api_key=str(os.environ["BRAVE_API_KEY"]),
|
|
392
|
+
)
|
|
377
393
|
```
|
|
378
394
|
|
|
379
395
|
* **Academic Tools**
|
|
380
396
|
* arXiv: Search and retrieve academic papers
|
|
381
397
|
```python
|
|
382
|
-
|
|
398
|
+
arxiv_tools = tools_factory.get_llama_index_tools(
|
|
399
|
+
tool_package_name="arxiv",
|
|
400
|
+
tool_spec_name="ArxivToolSpec",
|
|
401
|
+
)
|
|
383
402
|
```
|
|
384
403
|
|
|
385
|
-
* **
|
|
404
|
+
* **Database Tools**
|
|
386
405
|
* Neo4j: Graph database integration
|
|
387
406
|
```python
|
|
388
|
-
|
|
407
|
+
neo4j_tools = tools_factory.get_llama_index_tools(
|
|
408
|
+
tool_package_name="neo4j",
|
|
409
|
+
tool_spec_name="Neo4jQueryToolSpec",
|
|
410
|
+
)
|
|
389
411
|
```
|
|
390
412
|
* Kuzu: Lightweight graph database
|
|
391
413
|
```python
|
|
392
|
-
|
|
414
|
+
kuzu_tools = tools_factory.get_llama_index_tools(
|
|
415
|
+
tool_package_name="kuzu",
|
|
416
|
+
tool_spec_name="KuzuGraphStore",
|
|
417
|
+
)
|
|
418
|
+
```
|
|
419
|
+
* Waii: tools for natural langauge query of a relational database
|
|
420
|
+
```python
|
|
421
|
+
waii_tools = tools_factory.get_llama_index_tools(
|
|
422
|
+
tool_package_name="waii",
|
|
423
|
+
tool_spec_name="WaiiToolSpec",
|
|
424
|
+
)
|
|
393
425
|
```
|
|
394
426
|
|
|
395
427
|
* **Google Tools**
|
|
396
428
|
* Gmail: Read and send emails
|
|
397
429
|
```python
|
|
398
|
-
|
|
430
|
+
gmail_tools = tools_factory.get_llama_index_tools(
|
|
431
|
+
tool_package_name="google",
|
|
432
|
+
tool_spec_name="GmailToolSpec",
|
|
433
|
+
)
|
|
399
434
|
```
|
|
400
435
|
* Calendar: Manage calendar events
|
|
401
436
|
```python
|
|
402
|
-
|
|
437
|
+
calendar_tools = tools_factory.get_llama_index_tools(
|
|
438
|
+
tool_package_name="google",
|
|
439
|
+
tool_spec_name="GoogleCalendarToolSpec",
|
|
440
|
+
)
|
|
403
441
|
```
|
|
404
442
|
* Search: Google search integration
|
|
405
443
|
```python
|
|
406
|
-
|
|
444
|
+
search_tools = tools_factory.get_llama_index_tools(
|
|
445
|
+
tool_package_name="google",
|
|
446
|
+
tool_spec_name="GoogleSearchToolSpec",
|
|
447
|
+
)
|
|
407
448
|
```
|
|
408
449
|
|
|
409
450
|
* **Communication Tools**
|
|
410
451
|
* Slack: Send messages and interact with Slack
|
|
411
452
|
```python
|
|
412
|
-
|
|
453
|
+
slack_tools = tools_factory.get_llama_index_tools(
|
|
454
|
+
tool_package_name="slack",
|
|
455
|
+
tool_spec_name="SlackToolSpec",
|
|
456
|
+
)
|
|
413
457
|
```
|
|
414
458
|
|
|
415
459
|
For detailed setup instructions and API key requirements, please refer the instructions on [LlamaIndex hub](https://llamahub.ai/?tab=tools) for the specific tool.
|
|
@@ -295,51 +295,92 @@ vectara-agentic includes various other tools from LlamaIndex ToolSpecs:
|
|
|
295
295
|
* Tavily Search: Real-time web search using [Tavily API](https://tavily.com/)
|
|
296
296
|
```python
|
|
297
297
|
from vectara_agentic.tools_catalog import ToolsCatalog
|
|
298
|
-
|
|
298
|
+
tools_factory = ToolsFactory()
|
|
299
|
+
tavily_tools = tools_factory.get_llama_index_tools(
|
|
300
|
+
tool_package_name="tavily_research",
|
|
301
|
+
tool_spec_name="TavilyToolSpec",
|
|
302
|
+
api_key=str(os.environ["TAVILY_API_KEY"]),
|
|
303
|
+
)
|
|
299
304
|
```
|
|
300
305
|
* EXA.AI: Advanced web search and data extraction
|
|
301
306
|
```python
|
|
302
|
-
|
|
307
|
+
exa_tools = tools_factory.get_llama_index_tools(
|
|
308
|
+
tool_package_name="exa.ai",
|
|
309
|
+
tool_spec_name="ExaToolSpec",
|
|
310
|
+
api_key=str(os.environ["EXA_API_KEY"]),
|
|
311
|
+
)
|
|
303
312
|
```
|
|
304
313
|
* Brave Search: Web search using Brave's search engine
|
|
305
314
|
```python
|
|
306
|
-
|
|
315
|
+
brave_tools = tools_factory.get_llama_index_tools(
|
|
316
|
+
tool_package_name="brave_search",
|
|
317
|
+
tool_spec_name="BraveSearchToolSpec",
|
|
318
|
+
api_key=str(os.environ["BRAVE_API_KEY"]),
|
|
319
|
+
)
|
|
307
320
|
```
|
|
308
321
|
|
|
309
322
|
* **Academic Tools**
|
|
310
323
|
* arXiv: Search and retrieve academic papers
|
|
311
324
|
```python
|
|
312
|
-
|
|
325
|
+
arxiv_tools = tools_factory.get_llama_index_tools(
|
|
326
|
+
tool_package_name="arxiv",
|
|
327
|
+
tool_spec_name="ArxivToolSpec",
|
|
328
|
+
)
|
|
313
329
|
```
|
|
314
330
|
|
|
315
|
-
* **
|
|
331
|
+
* **Database Tools**
|
|
316
332
|
* Neo4j: Graph database integration
|
|
317
333
|
```python
|
|
318
|
-
|
|
334
|
+
neo4j_tools = tools_factory.get_llama_index_tools(
|
|
335
|
+
tool_package_name="neo4j",
|
|
336
|
+
tool_spec_name="Neo4jQueryToolSpec",
|
|
337
|
+
)
|
|
319
338
|
```
|
|
320
339
|
* Kuzu: Lightweight graph database
|
|
321
340
|
```python
|
|
322
|
-
|
|
341
|
+
kuzu_tools = tools_factory.get_llama_index_tools(
|
|
342
|
+
tool_package_name="kuzu",
|
|
343
|
+
tool_spec_name="KuzuGraphStore",
|
|
344
|
+
)
|
|
345
|
+
```
|
|
346
|
+
* Waii: tools for natural langauge query of a relational database
|
|
347
|
+
```python
|
|
348
|
+
waii_tools = tools_factory.get_llama_index_tools(
|
|
349
|
+
tool_package_name="waii",
|
|
350
|
+
tool_spec_name="WaiiToolSpec",
|
|
351
|
+
)
|
|
323
352
|
```
|
|
324
353
|
|
|
325
354
|
* **Google Tools**
|
|
326
355
|
* Gmail: Read and send emails
|
|
327
356
|
```python
|
|
328
|
-
|
|
357
|
+
gmail_tools = tools_factory.get_llama_index_tools(
|
|
358
|
+
tool_package_name="google",
|
|
359
|
+
tool_spec_name="GmailToolSpec",
|
|
360
|
+
)
|
|
329
361
|
```
|
|
330
362
|
* Calendar: Manage calendar events
|
|
331
363
|
```python
|
|
332
|
-
|
|
364
|
+
calendar_tools = tools_factory.get_llama_index_tools(
|
|
365
|
+
tool_package_name="google",
|
|
366
|
+
tool_spec_name="GoogleCalendarToolSpec",
|
|
367
|
+
)
|
|
333
368
|
```
|
|
334
369
|
* Search: Google search integration
|
|
335
370
|
```python
|
|
336
|
-
|
|
371
|
+
search_tools = tools_factory.get_llama_index_tools(
|
|
372
|
+
tool_package_name="google",
|
|
373
|
+
tool_spec_name="GoogleSearchToolSpec",
|
|
374
|
+
)
|
|
337
375
|
```
|
|
338
376
|
|
|
339
377
|
* **Communication Tools**
|
|
340
378
|
* Slack: Send messages and interact with Slack
|
|
341
379
|
```python
|
|
342
|
-
|
|
380
|
+
slack_tools = tools_factory.get_llama_index_tools(
|
|
381
|
+
tool_package_name="slack",
|
|
382
|
+
tool_spec_name="SlackToolSpec",
|
|
383
|
+
)
|
|
343
384
|
```
|
|
344
385
|
|
|
345
386
|
For detailed setup instructions and API key requirements, please refer the instructions on [LlamaIndex hub](https://llamahub.ai/?tab=tools) for the specific tool.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
llama-index==0.12.
|
|
1
|
+
llama-index==0.12.35
|
|
2
2
|
llama-index-indices-managed-vectara==0.4.5
|
|
3
3
|
llama-index-agent-llm-compiler==0.3.0
|
|
4
4
|
llama-index-agent-lats==0.3.0
|
|
5
|
-
llama-index-agent-openai==0.4.
|
|
6
|
-
llama-index-llms-openai==0.3.
|
|
5
|
+
llama-index-agent-openai==0.4.8
|
|
6
|
+
llama-index-llms-openai==0.3.42
|
|
7
|
+
llama-index-llms-openai-like>=0.3.5
|
|
7
8
|
llama-index-llms-anthropic==0.6.10
|
|
8
9
|
llama-index-llms-together==0.3.1
|
|
9
10
|
llama-index-llms-groq==0.3.1
|
|
@@ -18,15 +19,17 @@ llama-index-tools-google==0.3.0
|
|
|
18
19
|
llama-index-tools-tavily_research==0.3.0
|
|
19
20
|
llama_index.tools.brave_search==0.3.0
|
|
20
21
|
llama-index-tools-neo4j==0.3.0
|
|
22
|
+
llama-index-tools-waii==0.3.0
|
|
21
23
|
llama-index-graph-stores-kuzu==0.7.0
|
|
24
|
+
llama-index-tools-salesforce==0.3.0
|
|
22
25
|
llama-index-tools-slack==0.3.0
|
|
23
26
|
llama-index-tools-exa==0.3.0
|
|
24
27
|
llama-index-tools-wikipedia==0.3.0
|
|
25
28
|
llama-index-tools-bing-search==0.3.0
|
|
26
|
-
tavily-python==0.
|
|
27
|
-
exa-py==1.12.
|
|
29
|
+
tavily-python==0.7.2
|
|
30
|
+
exa-py==1.12.1
|
|
28
31
|
openinference-instrumentation-llama-index==4.2.1
|
|
29
|
-
opentelemetry-proto
|
|
32
|
+
opentelemetry-proto>=1.31.0
|
|
30
33
|
arize-phoenix==8.26.1
|
|
31
34
|
arize-phoenix-otel==0.9.2
|
|
32
35
|
protobuf==5.29.3
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
from fastapi.testclient import TestClient
|
|
5
|
+
|
|
6
|
+
# Adjust this import to point at the file where you put create_app
|
|
7
|
+
from vectara_agentic.agent_endpoint import create_app
|
|
8
|
+
from vectara_agentic.agent import Agent
|
|
9
|
+
from vectara_agentic.agent_config import AgentConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DummyAgent(Agent):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
# satisfy Agent.__init__(tools: ...)
|
|
15
|
+
super().__init__(tools=[])
|
|
16
|
+
|
|
17
|
+
def chat(self, message: str) -> str:
|
|
18
|
+
return f"Echo: {message}"
|
|
19
|
+
|
|
20
|
+
class APITestCase(unittest.TestCase):
|
|
21
|
+
@classmethod
|
|
22
|
+
def setUpClass(cls):
|
|
23
|
+
cls.agent = DummyAgent()
|
|
24
|
+
# Override only the endpoint_api_key, leave everything else as default
|
|
25
|
+
cls.config = AgentConfig(endpoint_api_key="testkey")
|
|
26
|
+
app = create_app(cls.agent, cls.config)
|
|
27
|
+
cls.client = TestClient(app)
|
|
28
|
+
cls.headers = {"X-API-Key": cls.config.endpoint_api_key}
|
|
29
|
+
|
|
30
|
+
def test_chat_success(self):
|
|
31
|
+
r = self.client.get("/chat", params={"message": "hello"}, headers=self.headers)
|
|
32
|
+
self.assertEqual(r.status_code, 200)
|
|
33
|
+
self.assertEqual(r.json(), {"response": "Echo: hello"})
|
|
34
|
+
|
|
35
|
+
def test_chat_empty_message(self):
|
|
36
|
+
r = self.client.get("/chat", params={"message": ""}, headers=self.headers)
|
|
37
|
+
self.assertEqual(r.status_code, 400)
|
|
38
|
+
self.assertIn("No message provided", r.json()["detail"])
|
|
39
|
+
|
|
40
|
+
def test_chat_unauthorized(self):
|
|
41
|
+
r = self.client.get("/chat", params={"message": "hello"}, headers={"X-API-Key": "bad"})
|
|
42
|
+
self.assertEqual(r.status_code, 403)
|
|
43
|
+
|
|
44
|
+
def test_completions_success(self):
|
|
45
|
+
payload = {"model": "m1", "prompt": "test"}
|
|
46
|
+
r = self.client.post("/v1/completions", json=payload, headers=self.headers)
|
|
47
|
+
self.assertEqual(r.status_code, 200)
|
|
48
|
+
data = r.json()
|
|
49
|
+
|
|
50
|
+
# ID prefix + valid UUID check
|
|
51
|
+
self.assertTrue(data["id"].startswith("cmpl-"))
|
|
52
|
+
UUID(data["id"].split("-", 1)[1])
|
|
53
|
+
|
|
54
|
+
self.assertEqual(data["model"], "m1")
|
|
55
|
+
self.assertEqual(data["choices"][0]["text"], "Echo: test")
|
|
56
|
+
# prompt_tokens=1, completion_tokens=2 ("Echo:", "test")
|
|
57
|
+
self.assertEqual(data["usage"]["prompt_tokens"], 1)
|
|
58
|
+
self.assertEqual(data["usage"]["completion_tokens"], 2)
|
|
59
|
+
|
|
60
|
+
def test_completions_no_prompt(self):
|
|
61
|
+
payload = {"model": "m1"} # missing prompt
|
|
62
|
+
r = self.client.post("/v1/completions", json=payload, headers=self.headers)
|
|
63
|
+
self.assertEqual(r.status_code, 400)
|
|
64
|
+
self.assertIn("`prompt` is required", r.json()["detail"])
|
|
65
|
+
|
|
66
|
+
def test_completions_unauthorized(self):
|
|
67
|
+
payload = {"model": "m1", "prompt": "hi"}
|
|
68
|
+
r = self.client.post("/v1/completions", json=payload, headers={"X-API-Key": "bad"})
|
|
69
|
+
self.assertEqual(r.status_code, 403)
|
|
70
|
+
|
|
71
|
+
def test_chat_completion_success(self):
|
|
72
|
+
payload = {
|
|
73
|
+
"model": "m1",
|
|
74
|
+
"messages": [{"role": "user", "content": "hello"}]
|
|
75
|
+
}
|
|
76
|
+
r = self.client.post("/v1/chat", json=payload, headers=self.headers)
|
|
77
|
+
self.assertEqual(r.status_code, 200)
|
|
78
|
+
data = r.json()
|
|
79
|
+
|
|
80
|
+
# ID prefix + valid UUID check
|
|
81
|
+
self.assertTrue(data["id"].startswith("chatcmpl-"))
|
|
82
|
+
UUID(data["id"].split("-", 1)[1])
|
|
83
|
+
|
|
84
|
+
self.assertEqual(data["model"], "m1")
|
|
85
|
+
self.assertEqual(data["choices"][0]["message"]["content"], "Echo: hello")
|
|
86
|
+
|
|
87
|
+
# prompt_tokens=1, completion_tokens=2 ("Echo:", "hello")
|
|
88
|
+
self.assertEqual(data["usage"]["prompt_tokens"], 1)
|
|
89
|
+
self.assertEqual(data["usage"]["completion_tokens"], 2)
|
|
90
|
+
|
|
91
|
+
def test_chat_completion_multiple_user_messages(self):
|
|
92
|
+
payload = {
|
|
93
|
+
"model": "m1",
|
|
94
|
+
"messages": [
|
|
95
|
+
{"role": "system", "content": "ignore me"},
|
|
96
|
+
{"role": "user", "content": "foo"},
|
|
97
|
+
{"role": "assistant", "content": "pong"},
|
|
98
|
+
{"role": "user", "content": "bar"}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
r = self.client.post("/v1/chat", json=payload, headers=self.headers)
|
|
102
|
+
self.assertEqual(r.status_code, 200)
|
|
103
|
+
data = r.json()
|
|
104
|
+
|
|
105
|
+
# Should concatenate only user messages: "foo bar"
|
|
106
|
+
self.assertEqual(data["choices"][0]["message"]["content"], "Echo: foo bar")
|
|
107
|
+
self.assertEqual(data["usage"]["prompt_tokens"], 2) # "foo","bar"
|
|
108
|
+
self.assertEqual(data["usage"]["completion_tokens"], 3) # "Echo:","foo","bar"
|
|
109
|
+
|
|
110
|
+
def test_chat_completion_no_messages(self):
|
|
111
|
+
payload = {"model": "m1", "messages": []}
|
|
112
|
+
r = self.client.post("/v1/chat", json=payload, headers=self.headers)
|
|
113
|
+
self.assertEqual(r.status_code, 400)
|
|
114
|
+
self.assertIn("`messages` is required", r.json()["detail"])
|
|
115
|
+
|
|
116
|
+
def test_chat_completion_unauthorized(self):
|
|
117
|
+
payload = {
|
|
118
|
+
"model": "m1",
|
|
119
|
+
"messages": [{"role": "user", "content": "oops"}]
|
|
120
|
+
}
|
|
121
|
+
r = self.client.post("/v1/chat", json=payload, headers={"X-API-Key": "bad"})
|
|
122
|
+
self.assertEqual(r.status_code, 403)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
unittest.main()
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, BaseModel
|
|
4
|
+
|
|
5
|
+
from vectara_agentic.agent import Agent, AgentType
|
|
6
|
+
from vectara_agentic.agent_config import AgentConfig
|
|
7
|
+
from vectara_agentic.tools import VectaraToolFactory
|
|
8
|
+
from vectara_agentic.types import ModelProvider
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import nest_asyncio
|
|
12
|
+
nest_asyncio.apply()
|
|
13
|
+
|
|
14
|
+
tickers = {
|
|
15
|
+
"C": "Citigroup",
|
|
16
|
+
"COF": "Capital One",
|
|
17
|
+
"JPM": "JPMorgan Chase",
|
|
18
|
+
"AAPL": "Apple Computer",
|
|
19
|
+
"GOOG": "Google",
|
|
20
|
+
"AMZN": "Amazon",
|
|
21
|
+
"SNOW": "Snowflake",
|
|
22
|
+
"TEAM": "Atlassian",
|
|
23
|
+
"TSLA": "Tesla",
|
|
24
|
+
"NVDA": "Nvidia",
|
|
25
|
+
"MSFT": "Microsoft",
|
|
26
|
+
"AMD": "Advanced Micro Devices",
|
|
27
|
+
"INTC": "Intel",
|
|
28
|
+
"NFLX": "Netflix",
|
|
29
|
+
"STT": "State Street",
|
|
30
|
+
"BK": "Bank of New York Mellon",
|
|
31
|
+
}
|
|
32
|
+
years = list(range(2015, 2025))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def mult(x: float, y: float) -> float:
|
|
36
|
+
"Multiply two numbers"
|
|
37
|
+
return x * y
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_company_info() -> list[str]:
|
|
41
|
+
"""
|
|
42
|
+
Returns a dictionary of companies you can query about. Always check this before using any other tool.
|
|
43
|
+
The output is a dictionary of valid ticker symbols mapped to company names.
|
|
44
|
+
You can use this to identify the companies you can query about, and their ticker information.
|
|
45
|
+
"""
|
|
46
|
+
return tickers
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_valid_years() -> list[str]:
|
|
50
|
+
"""
|
|
51
|
+
Returns a list of the years for which financial reports are available.
|
|
52
|
+
Always check this before using any other tool.
|
|
53
|
+
"""
|
|
54
|
+
return years
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
fc_config_gemini = AgentConfig(
|
|
58
|
+
agent_type=AgentType.FUNCTION_CALLING,
|
|
59
|
+
main_llm_provider=ModelProvider.GEMINI,
|
|
60
|
+
tool_llm_provider=ModelProvider.GEMINI,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class TestGEMINI(unittest.TestCase):
|
|
65
|
+
|
|
66
|
+
def test_tool_with_many_arguments(self):
|
|
67
|
+
|
|
68
|
+
vectara_corpus_key = "vectara-docs_1"
|
|
69
|
+
vectara_api_key = "zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA"
|
|
70
|
+
vec_factory = VectaraToolFactory(vectara_corpus_key, vectara_api_key)
|
|
71
|
+
|
|
72
|
+
class QueryToolArgs(BaseModel):
|
|
73
|
+
arg1: str = Field(description="the first argument", examples=["val1"])
|
|
74
|
+
arg2: str = Field(description="the second argument", examples=["val2"])
|
|
75
|
+
arg3: str = Field(description="the third argument", examples=["val3"])
|
|
76
|
+
arg4: str = Field(description="the fourth argument", examples=["val4"])
|
|
77
|
+
arg5: str = Field(description="the fifth argument", examples=["val5"])
|
|
78
|
+
arg6: str = Field(description="the sixth argument", examples=["val6"])
|
|
79
|
+
arg7: str = Field(description="the seventh argument", examples=["val7"])
|
|
80
|
+
arg8: str = Field(description="the eighth argument", examples=["val8"])
|
|
81
|
+
arg9: str = Field(description="the ninth argument", examples=["val9"])
|
|
82
|
+
arg10: str = Field(description="the tenth argument", examples=["val10"])
|
|
83
|
+
arg11: str = Field(description="the eleventh argument", examples=["val11"])
|
|
84
|
+
arg12: str = Field(description="the twelfth argument", examples=["val12"])
|
|
85
|
+
arg13: str = Field(
|
|
86
|
+
description="the thirteenth argument", examples=["val13"]
|
|
87
|
+
)
|
|
88
|
+
arg14: str = Field(
|
|
89
|
+
description="the fourteenth argument", examples=["val14"]
|
|
90
|
+
)
|
|
91
|
+
arg15: str = Field(description="the fifteenth argument", examples=["val15"])
|
|
92
|
+
|
|
93
|
+
query_tool_1 = vec_factory.create_rag_tool(
|
|
94
|
+
tool_name="rag_tool",
|
|
95
|
+
tool_description="""
|
|
96
|
+
A dummy tool that takes 15 arguments and returns a response (str) to the user query based on the data in this corpus.
|
|
97
|
+
We are using this tool to test the tool factory works and does not crash with OpenAI.
|
|
98
|
+
""",
|
|
99
|
+
tool_args_schema=QueryToolArgs,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
agent = Agent(
|
|
103
|
+
tools=[query_tool_1],
|
|
104
|
+
topic="Sample topic",
|
|
105
|
+
custom_instructions="Call the tool with 15 arguments",
|
|
106
|
+
agent_config=fc_config_gemini,
|
|
107
|
+
)
|
|
108
|
+
res = agent.chat("What is the stock price?")
|
|
109
|
+
self.assertTrue(
|
|
110
|
+
any(sub in str(res) for sub in ["I don't know", "I do not have"])
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
unittest.main()
|
|
@@ -54,13 +54,6 @@ def get_valid_years() -> list[str]:
|
|
|
54
54
|
return years
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
config_gemini = AgentConfig(
|
|
58
|
-
agent_type=AgentType.FUNCTION_CALLING,
|
|
59
|
-
main_llm_provider=ModelProvider.GEMINI,
|
|
60
|
-
tool_llm_provider=ModelProvider.GEMINI,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
57
|
fc_config_groq = AgentConfig(
|
|
65
58
|
agent_type=AgentType.FUNCTION_CALLING,
|
|
66
59
|
main_llm_provider=ModelProvider.GROQ,
|
|
@@ -251,17 +251,19 @@ class TestToolsPackage(unittest.TestCase):
|
|
|
251
251
|
arg11: str = Field(description="the eleventh argument", examples=["val11"])
|
|
252
252
|
arg12: str = Field(description="the twelfth argument", examples=["val12"])
|
|
253
253
|
arg13: str = Field(description="the thirteenth argument", examples=["val13"])
|
|
254
|
+
arg14: str = Field(description="the fourteenth argument", examples=["val14"])
|
|
255
|
+
arg15: str = Field(description="the fifteenth argument", examples=["val15"])
|
|
254
256
|
|
|
255
257
|
query_tool_1 = vec_factory.create_rag_tool(
|
|
256
258
|
tool_name="rag_tool",
|
|
257
259
|
tool_description="""
|
|
258
|
-
A dummy tool that takes
|
|
260
|
+
A dummy tool that takes 15 arguments and returns a response (str) to the user query based on the data in this corpus.
|
|
259
261
|
We are using this tool to test the tool factory works and does not crash with OpenAI.
|
|
260
262
|
""",
|
|
261
263
|
tool_args_schema=QueryToolArgs,
|
|
262
264
|
)
|
|
263
265
|
|
|
264
|
-
# Test with
|
|
266
|
+
# Test with 15 arguments to make sure no issues occur
|
|
265
267
|
config = AgentConfig(
|
|
266
268
|
agent_type=AgentType.OPENAI
|
|
267
269
|
)
|
|
@@ -272,9 +274,9 @@ class TestToolsPackage(unittest.TestCase):
|
|
|
272
274
|
agent_config=config,
|
|
273
275
|
)
|
|
274
276
|
res = agent.chat("What is the stock price for Yahoo on 12/31/22?")
|
|
275
|
-
self.
|
|
277
|
+
self.assertNotIn("maximum length of 1024 characters", str(res))
|
|
276
278
|
|
|
277
|
-
# Same test but with GROQ
|
|
279
|
+
# Same test but with GROQ, should not have this limit
|
|
278
280
|
config = AgentConfig(
|
|
279
281
|
agent_type=AgentType.FUNCTION_CALLING,
|
|
280
282
|
main_llm_provider=ModelProvider.GROQ,
|
|
@@ -283,13 +285,13 @@ class TestToolsPackage(unittest.TestCase):
|
|
|
283
285
|
agent = Agent(
|
|
284
286
|
tools=[query_tool_1],
|
|
285
287
|
topic="Sample topic",
|
|
286
|
-
custom_instructions="Call the tool with
|
|
288
|
+
custom_instructions="Call the tool with 15 arguments for GROQ",
|
|
287
289
|
agent_config=config,
|
|
288
290
|
)
|
|
289
291
|
res = agent.chat("What is the stock price?")
|
|
290
292
|
self.assertNotIn("maximum length of 1024 characters", str(res))
|
|
291
293
|
|
|
292
|
-
# Same test but with ANTHROPIC
|
|
294
|
+
# Same test but with ANTHROPIC, should not have this limit
|
|
293
295
|
config = AgentConfig(
|
|
294
296
|
agent_type=AgentType.FUNCTION_CALLING,
|
|
295
297
|
main_llm_provider=ModelProvider.ANTHROPIC,
|
|
@@ -298,38 +300,12 @@ class TestToolsPackage(unittest.TestCase):
|
|
|
298
300
|
agent = Agent(
|
|
299
301
|
tools=[query_tool_1],
|
|
300
302
|
topic="Sample topic",
|
|
301
|
-
custom_instructions="Call the tool with
|
|
303
|
+
custom_instructions="Call the tool with 15 arguments for ANTHROPIC",
|
|
302
304
|
agent_config=config,
|
|
303
305
|
)
|
|
304
306
|
res = agent.chat("What is the stock price?")
|
|
305
|
-
# ANTHROPIC does not have that 1024 limit
|
|
306
307
|
self.assertIn("stock price", str(res))
|
|
307
308
|
|
|
308
|
-
# But using Compact_docstring=True, we can pass 13 arguments successfully.
|
|
309
|
-
vec_factory = VectaraToolFactory(
|
|
310
|
-
vectara_corpus_key, vectara_api_key, compact_docstring=True
|
|
311
|
-
)
|
|
312
|
-
query_tool_2 = vec_factory.create_rag_tool(
|
|
313
|
-
tool_name="rag_tool",
|
|
314
|
-
tool_description="""
|
|
315
|
-
A dummy tool that takes 15 arguments and returns a response (str) to the user query based on the data in this corpus.
|
|
316
|
-
We are using this tool to test the tool factory works and doesn not crash with OpenAI.
|
|
317
|
-
""",
|
|
318
|
-
tool_args_schema=QueryToolArgs,
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
config = AgentConfig()
|
|
322
|
-
agent = Agent(
|
|
323
|
-
tools=[query_tool_2],
|
|
324
|
-
topic="Sample topic",
|
|
325
|
-
custom_instructions="Call the tool with 15 arguments",
|
|
326
|
-
agent_config=config,
|
|
327
|
-
)
|
|
328
|
-
res = agent.chat("What is the stock price?")
|
|
329
|
-
self.assertTrue(
|
|
330
|
-
any(sub in str(res) for sub in ["I don't know", "stock price"])
|
|
331
|
-
)
|
|
332
|
-
|
|
333
309
|
def test_public_repo(self):
|
|
334
310
|
vectara_corpus_key = "vectara-docs_1"
|
|
335
311
|
vectara_api_key = "zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA"
|