vectara-agentic 0.1.27__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

tests/test_agent.py CHANGED
@@ -1,9 +1,10 @@
1
1
  import unittest
2
2
  from datetime import date
3
3
 
4
- from vectara_agentic.agent import _get_prompt, Agent, AgentType, FunctionTool
4
+ from vectara_agentic.agent import _get_prompt, Agent, AgentType
5
5
  from vectara_agentic.agent_config import AgentConfig
6
6
  from vectara_agentic.types import ModelProvider, ObserverType
7
+ from vectara_agentic.tools import ToolsFactory
7
8
 
8
9
  class TestAgentPackage(unittest.TestCase):
9
10
  def test_get_prompt(self):
@@ -23,16 +24,11 @@ class TestAgentPackage(unittest.TestCase):
23
24
  def mult(x, y):
24
25
  return x * y
25
26
 
26
- tools = [
27
- FunctionTool.from_defaults(
28
- fn=mult, name="mult", description="Multiplication functions"
29
- )
30
- ]
27
+ tools = [ToolsFactory().create_tool(mult)]
31
28
  topic = "AI"
32
29
  custom_instructions = "Always do as your mother tells you!"
33
30
  agent = Agent(tools, topic, custom_instructions)
34
31
  self.assertEqual(agent.agent_type, AgentType.OPENAI)
35
- self.assertEqual(agent.tools, tools)
36
32
  self.assertEqual(agent._topic, topic)
37
33
  self.assertEqual(agent._custom_instructions, custom_instructions)
38
34
 
@@ -40,7 +36,7 @@ class TestAgentPackage(unittest.TestCase):
40
36
  self.assertEqual(
41
37
  agent.chat(
42
38
  "What is 5 times 10. Only give the answer, nothing else"
43
- ).replace("$", "\\$"),
39
+ ).response.replace("$", "\\$"),
44
40
  "50",
45
41
  )
46
42
 
@@ -48,11 +44,7 @@ class TestAgentPackage(unittest.TestCase):
48
44
  def mult(x, y):
49
45
  return x * y
50
46
 
51
- tools = [
52
- FunctionTool.from_defaults(
53
- fn=mult, name="mult", description="Multiplication functions"
54
- )
55
- ]
47
+ tools = [ToolsFactory().create_tool(mult)]
56
48
  topic = "AI topic"
57
49
  instructions = "Always do as your father tells you, if your mother agrees!"
58
50
  config = AgentConfig(
@@ -70,7 +62,6 @@ class TestAgentPackage(unittest.TestCase):
70
62
  custom_instructions=instructions,
71
63
  agent_config=config
72
64
  )
73
- self.assertEqual(agent.tools, tools)
74
65
  self.assertEqual(agent._topic, topic)
75
66
  self.assertEqual(agent._custom_instructions, instructions)
76
67
  self.assertEqual(agent.agent_type, AgentType.REACT)
@@ -78,19 +69,18 @@ class TestAgentPackage(unittest.TestCase):
78
69
  self.assertEqual(agent.agent_config.main_llm_provider, ModelProvider.ANTHROPIC)
79
70
  self.assertEqual(agent.agent_config.tool_llm_provider, ModelProvider.TOGETHER)
80
71
 
81
- # To run this test, you must have OPENAI_API_KEY in your environment
72
+ # To run this test, you must have ANTHROPIC_API_KEY and TOGETHER_API_KEY in your environment
82
73
  self.assertEqual(
83
74
  agent.chat(
84
75
  "What is 5 times 10. Only give the answer, nothing else"
85
- ).replace("$", "\\$"),
76
+ ).response.replace("$", "\\$"),
86
77
  "50",
87
78
  )
88
79
 
89
80
  def test_from_corpus(self):
90
81
  agent = Agent.from_corpus(
91
82
  tool_name="RAG Tool",
92
- vectara_customer_id="4584783",
93
- vectara_corpus_id="4",
83
+ vectara_corpus_key="corpus_key",
94
84
  vectara_api_key="api_key",
95
85
  data_description="information",
96
86
  assistant_specialty="question answering",
@@ -102,8 +92,7 @@ class TestAgentPackage(unittest.TestCase):
102
92
  def test_serialization(self):
103
93
  agent = Agent.from_corpus(
104
94
  tool_name="RAG Tool",
105
- vectara_customer_id="4584783",
106
- vectara_corpus_id="4",
95
+ vectara_corpus_key="corpus_key",
107
96
  vectara_api_key="api_key",
108
97
  data_description="information",
109
98
  assistant_specialty="question answering",
tests/test_tools.py CHANGED
@@ -8,15 +8,13 @@ from llama_index.core.tools import FunctionTool
8
8
 
9
9
  class TestToolsPackage(unittest.TestCase):
10
10
  def test_vectara_tool_factory(self):
11
- vectara_customer_id = "4584783"
12
- vectara_corpus_id = "4"
11
+ vectara_corpus_key = "corpus_key"
13
12
  vectara_api_key = "api_key"
14
13
  vec_factory = VectaraToolFactory(
15
- vectara_customer_id, vectara_corpus_id, vectara_api_key
14
+ vectara_corpus_key, vectara_api_key
16
15
  )
17
16
 
18
- self.assertEqual(vectara_customer_id, vec_factory.vectara_customer_id)
19
- self.assertEqual(vectara_corpus_id, vec_factory.vectara_corpus_id)
17
+ self.assertEqual(vectara_corpus_key, vec_factory.vectara_corpus_key)
20
18
  self.assertEqual(vectara_api_key, vec_factory.vectara_api_key)
21
19
 
22
20
  class QueryToolArgs(BaseModel):
@@ -59,16 +57,14 @@ class TestToolsPackage(unittest.TestCase):
59
57
  self.assertEqual(arxiv_tool.metadata.tool_type, ToolType.QUERY)
60
58
 
61
59
  def test_public_repo(self):
62
- vectara_customer_id = "1366999410"
63
- vectara_corpus_id = "1"
60
+ vectara_corpus_key = "vectara-docs_1"
64
61
  vectara_api_key = "zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA"
65
62
 
66
63
  class QueryToolArgs(BaseModel):
67
64
  query: str = Field(description="The user query")
68
65
 
69
66
  agent = Agent.from_corpus(
70
- vectara_customer_id=vectara_customer_id,
71
- vectara_corpus_id=vectara_corpus_id,
67
+ vectara_corpus_key=vectara_corpus_key,
72
68
  vectara_api_key=vectara_api_key,
73
69
  tool_name="ask_vectara",
74
70
  data_description="data from Vectara website",
@@ -146,7 +146,8 @@ class AgentCallbackHandler(BaseCallbackHandler):
146
146
  if EventPayload.MESSAGES in payload:
147
147
  response = str(payload.get(EventPayload.RESPONSE))
148
148
  if response and response not in ["None", "assistant: None"]:
149
- self.fn(AgentStatusType.AGENT_UPDATE, response)
149
+ if self.fn:
150
+ self.fn(AgentStatusType.AGENT_UPDATE, response)
150
151
  else:
151
152
  print(f"No messages or prompt found in payload {payload}")
152
153
 
@@ -156,23 +157,27 @@ class AgentCallbackHandler(BaseCallbackHandler):
156
157
  tool = payload.get(EventPayload.TOOL)
157
158
  if tool:
158
159
  tool_name = tool.name
159
- self.fn(
160
- AgentStatusType.TOOL_CALL,
161
- f"Executing '{tool_name}' with arguments: {fcall}",
162
- )
160
+ if self.fn:
161
+ self.fn(
162
+ AgentStatusType.TOOL_CALL,
163
+ f"Executing '{tool_name}' with arguments: {fcall}",
164
+ )
163
165
  elif EventPayload.FUNCTION_OUTPUT in payload:
164
166
  response = str(payload.get(EventPayload.FUNCTION_OUTPUT))
165
- self.fn(AgentStatusType.TOOL_OUTPUT, response)
167
+ if self.fn:
168
+ self.fn(AgentStatusType.TOOL_OUTPUT, response)
166
169
  else:
167
170
  print(f"No function call or output found in payload {payload}")
168
171
 
169
172
  def _handle_agent_step(self, payload: dict) -> None:
170
173
  if EventPayload.MESSAGES in payload:
171
174
  msg = str(payload.get(EventPayload.MESSAGES))
172
- self.fn(AgentStatusType.AGENT_STEP, msg)
175
+ if self.fn:
176
+ self.fn(AgentStatusType.AGENT_STEP, msg)
173
177
  elif EventPayload.RESPONSE in payload:
174
178
  response = str(payload.get(EventPayload.RESPONSE))
175
- self.fn(AgentStatusType.AGENT_STEP, response)
179
+ if self.fn:
180
+ self.fn(AgentStatusType.AGENT_STEP, response)
176
181
  else:
177
182
  print(f"No messages or prompt found in payload {payload}")
178
183
 
@@ -181,10 +186,11 @@ class AgentCallbackHandler(BaseCallbackHandler):
181
186
  if EventPayload.MESSAGES in payload:
182
187
  response = str(payload.get(EventPayload.RESPONSE))
183
188
  if response and response not in ["None", "assistant: None"]:
184
- if inspect.iscoroutinefunction(self.fn):
185
- await self.fn(AgentStatusType.AGENT_UPDATE, response)
186
- else:
187
- self.fn(AgentStatusType.AGENT_UPDATE, response)
189
+ if self.fn:
190
+ if inspect.iscoroutinefunction(self.fn):
191
+ await self.fn(AgentStatusType.AGENT_UPDATE, response)
192
+ else:
193
+ self.fn(AgentStatusType.AGENT_UPDATE, response)
188
194
  else:
189
195
  print(f"No messages or prompt found in payload {payload}")
190
196
 
@@ -194,37 +200,41 @@ class AgentCallbackHandler(BaseCallbackHandler):
194
200
  tool = payload.get(EventPayload.TOOL)
195
201
  if tool:
196
202
  tool_name = tool.name
203
+ if self.fn:
204
+ if inspect.iscoroutinefunction(self.fn):
205
+ await self.fn(
206
+ AgentStatusType.TOOL_CALL,
207
+ f"Executing '{tool_name}' with arguments: {fcall}",
208
+ )
209
+ else:
210
+ self.fn(
211
+ AgentStatusType.TOOL_CALL,
212
+ f"Executing '{tool_name}' with arguments: {fcall}",
213
+ )
214
+ elif EventPayload.FUNCTION_OUTPUT in payload:
215
+ if self.fn:
216
+ response = str(payload.get(EventPayload.FUNCTION_OUTPUT))
197
217
  if inspect.iscoroutinefunction(self.fn):
198
- await self.fn(
199
- AgentStatusType.TOOL_CALL,
200
- f"Executing '{tool_name}' with arguments: {fcall}",
201
- )
218
+ await self.fn(AgentStatusType.TOOL_OUTPUT, response)
202
219
  else:
203
- self.fn(
204
- AgentStatusType.TOOL_CALL,
205
- f"Executing '{tool_name}' with arguments: {fcall}",
206
- )
207
- elif EventPayload.FUNCTION_OUTPUT in payload:
208
- response = str(payload.get(EventPayload.FUNCTION_OUTPUT))
209
- if inspect.iscoroutinefunction(self.fn):
210
- await self.fn(AgentStatusType.TOOL_OUTPUT, response)
211
- else:
212
- self.fn(AgentStatusType.TOOL_OUTPUT, response)
220
+ self.fn(AgentStatusType.TOOL_OUTPUT, response)
213
221
  else:
214
222
  print(f"No function call or output found in payload {payload}")
215
223
 
216
224
  async def _ahandle_agent_step(self, payload: dict) -> None:
217
225
  if EventPayload.MESSAGES in payload:
218
- msg = str(payload.get(EventPayload.MESSAGES))
219
- if inspect.iscoroutinefunction(self.fn):
220
- await self.fn(AgentStatusType.AGENT_STEP, msg)
221
- else:
222
- self.fn(AgentStatusType.AGENT_STEP, msg)
226
+ if self.fn:
227
+ msg = str(payload.get(EventPayload.MESSAGES))
228
+ if inspect.iscoroutinefunction(self.fn):
229
+ await self.fn(AgentStatusType.AGENT_STEP, msg)
230
+ else:
231
+ self.fn(AgentStatusType.AGENT_STEP, msg)
223
232
  elif EventPayload.RESPONSE in payload:
224
- response = str(payload.get(EventPayload.RESPONSE))
225
- if inspect.iscoroutinefunction(self.fn):
226
- await self.fn(AgentStatusType.AGENT_STEP, response)
227
- else:
228
- self.fn(AgentStatusType.AGENT_STEP, response)
233
+ if self.fn:
234
+ response = str(payload.get(EventPayload.RESPONSE))
235
+ if inspect.iscoroutinefunction(self.fn):
236
+ await self.fn(AgentStatusType.AGENT_STEP, response)
237
+ else:
238
+ self.fn(AgentStatusType.AGENT_STEP, response)
229
239
  else:
230
240
  print(f"No messages or prompt found in payload {payload}")
@@ -1,4 +1,4 @@
1
1
  """
2
2
  Define the version of the package.
3
3
  """
4
- __version__ = "0.1.27"
4
+ __version__ = "0.2.0"
vectara_agentic/agent.py CHANGED
@@ -294,28 +294,42 @@ class Agent:
294
294
  tool_name: str,
295
295
  data_description: str,
296
296
  assistant_specialty: str,
297
- vectara_customer_id: str = str(os.environ.get("VECTARA_CUSTOMER_ID", "")),
298
- vectara_corpus_id: str = str(os.environ.get("VECTARA_CORPUS_ID", "")),
297
+ vectara_corpus_key: str = str(os.environ.get("VECTARA_CORPUS_KEY", "")),
299
298
  vectara_api_key: str = str(os.environ.get("VECTARA_API_KEY", "")),
300
299
  agent_progress_callback: Optional[Callable[[AgentStatusType, str], None]] = None,
301
300
  query_logging_callback: Optional[Callable[[str, str], None]] = None,
302
301
  verbose: bool = False,
303
302
  vectara_filter_fields: list[dict] = [],
303
+ vectara_offset: int = 0,
304
304
  vectara_lambda_val: float = 0.005,
305
- vectara_reranker: str = "mmr",
305
+ vectara_semantics: str = "default",
306
+ vectara_custom_dimensions: Dict = {},
307
+ vectara_reranker: str = "slingshot",
306
308
  vectara_rerank_k: int = 50,
309
+ vectara_rerank_limit: Optional[int] = None,
310
+ vectara_rerank_cutoff: Optional[float] = None,
311
+ vectara_diversity_bias: float = 0.2,
312
+ vectara_udf_expression: str = None,
313
+ vectara_rerank_chain: List[Dict] = None,
307
314
  vectara_n_sentences_before: int = 2,
308
315
  vectara_n_sentences_after: int = 2,
309
316
  vectara_summary_num_results: int = 10,
310
- vectara_summarizer: str = "vectara-summary-ext-24-05-sml",
317
+ vectara_summarizer: str = "vectara-summary-ext-24-05-med-omni",
318
+ vectara_summary_response_language: str = "eng",
319
+ vectara_summary_prompt_text: Optional[str] = None,
320
+ vectara_max_response_chars: Optional[int] = None,
321
+ vectara_max_tokens: Optional[int] = None,
322
+ vectara_temperature: Optional[float] = None,
323
+ vectara_frequency_penalty: Optional[float] = None,
324
+ vectara_presence_penalty: Optional[float] = None,
325
+ vectara_save_history: bool = False,
311
326
  ) -> "Agent":
312
327
  """
313
328
  Create an agent from a single Vectara corpus
314
329
 
315
330
  Args:
316
331
  tool_name (str): The name of Vectara tool used by the agent
317
- vectara_customer_id (str): The Vectara customer ID.
318
- vectara_corpus_id (str): The Vectara corpus ID (or comma separated list of IDs).
332
+ vectara_corpus_key (str): The Vectara corpus key (or comma separated list of keys).
319
333
  vectara_api_key (str): The Vectara API key.
320
334
  agent_progress_callback (Callable): A callback function the code calls on any agent updates.
321
335
  query_logging_callback (Callable): A callback function the code calls upon completion of a query
@@ -324,21 +338,41 @@ class Agent:
324
338
  verbose (bool, optional): Whether to print verbose output.
325
339
  vectara_filter_fields (List[dict], optional): The filterable attributes
326
340
  (each dict maps field name to Tuple[type, description]).
327
- vectara_lambda_val (float, optional): The lambda value for Vectara hybrid search.
328
- vectara_reranker (str, optional): The Vectara reranker name (default "mmr")
341
+ vectara_offset (int, optional): Number of results to skip.
342
+ vectara_lambda_val (float, optional): Lambda value for Vectara hybrid search.
343
+ vectara_semantics: (str, optional): Indicates whether the query is intended as a query or response.
344
+ vectara_custom_dimensions: (Dict, optional): Custom dimensions for the query.
345
+ vectara_reranker (str, optional): The Vectara reranker name (default "slingshot")
329
346
  vectara_rerank_k (int, optional): The number of results to use with reranking.
347
+ vetara_rerank_limit: (int, optional): The maximum number of results to return after reranking.
348
+ vectara_rerank_cutoff: (float, optional): The minimum score threshold for results to include after
349
+ reranking.
350
+ vectara_diversity_bias (float, optional): The MMR diversity bias.
351
+ vectara_udf_expression (str, optional): The user defined expression for reranking results.
352
+ vectara_rerank_chain (List[Dict], optional): A list of Vectara rerankers to be applied sequentially.
330
353
  vectara_n_sentences_before (int, optional): The number of sentences before the matching text
331
354
  vectara_n_sentences_after (int, optional): The number of sentences after the matching text.
332
355
  vectara_summary_num_results (int, optional): The number of results to use in summarization.
333
356
  vectara_summarizer (str, optional): The Vectara summarizer name.
357
+ vectara_summary_response_language (str, optional): The response language for the Vectara summary.
358
+ vectara_summary_prompt_text (str, optional): The custom prompt, using appropriate prompt variables and
359
+ functions.
360
+ vectara_max_response_chars (int, optional): The desired maximum number of characters for the generated
361
+ summary.
362
+ vectara_max_tokens (int, optional): The maximum number of tokens to be returned by the LLM.
363
+ vectara_temperature (float, optional): The sampling temperature; higher values lead to more randomness.
364
+ vectara_frequency_penalty (float, optional): How much to penalize repeating tokens in the response,
365
+ higher values reducing likelihood of repeating the same line.
366
+ vectara_presence_penalty (float, optional): How much to penalize repeating tokens in the response,
367
+ higher values increasing the diversity of topics.
368
+ vectara_save_history (bool, optional): Whether to save the query in history.
334
369
 
335
370
  Returns:
336
371
  Agent: An instance of the Agent class.
337
372
  """
338
373
  vec_factory = VectaraToolFactory(
339
374
  vectara_api_key=vectara_api_key,
340
- vectara_customer_id=vectara_customer_id,
341
- vectara_corpus_id=vectara_corpus_id,
375
+ vectara_corpus_key=vectara_corpus_key,
342
376
  )
343
377
  field_definitions = {}
344
378
  field_definitions["query"] = (str, Field(description="The user query")) # type: ignore
@@ -350,7 +384,7 @@ class Agent:
350
384
  query_args = create_model("QueryArgs", **field_definitions) # type: ignore
351
385
 
352
386
  vectara_tool = vec_factory.create_rag_tool(
353
- tool_name=tool_name or f"vectara_{vectara_corpus_id}",
387
+ tool_name=tool_name or f"vectara_{vectara_corpus_key}",
354
388
  tool_description=f"""
355
389
  Given a user query,
356
390
  returns a response (str) to a user question about {data_description}.
@@ -358,13 +392,28 @@ class Agent:
358
392
  tool_args_schema=query_args,
359
393
  reranker=vectara_reranker,
360
394
  rerank_k=vectara_rerank_k,
395
+ rerank_limit=vectara_rerank_limit,
396
+ rerank_cutoff=vectara_rerank_cutoff,
397
+ mmr_diversity_bias=vectara_diversity_bias,
398
+ udf_expression=vectara_udf_expression,
399
+ rerank_chain=vectara_rerank_chain,
361
400
  n_sentences_before=vectara_n_sentences_before,
362
401
  n_sentences_after=vectara_n_sentences_after,
402
+ offset=vectara_offset,
363
403
  lambda_val=vectara_lambda_val,
404
+ semantics=vectara_semantics,
405
+ custom_dimensions=vectara_custom_dimensions,
364
406
  summary_num_results=vectara_summary_num_results,
365
407
  vectara_summarizer=vectara_summarizer,
408
+ summary_response_lang=vectara_summary_response_language,
409
+ vectara_prompt_text=vectara_summary_prompt_text,
410
+ max_response_chars=vectara_max_response_chars,
411
+ max_tokens=vectara_max_tokens,
412
+ temperature=vectara_temperature,
413
+ frequency_penalty=vectara_frequency_penalty,
414
+ presence_penalty=vectara_presence_penalty,
415
+ save_history=vectara_save_history,
366
416
  include_citations=True,
367
- verbose=verbose,
368
417
  )
369
418
 
370
419
  assistant_instructions = f"""
@@ -74,7 +74,7 @@ class DBLoadUniqueValues(DBTool):
74
74
  """
75
75
  A tool to list all unique values for each column in a set of columns of a database table.
76
76
  """
77
- def __call__(self, table_name: str, columns: list[str], num_vals: int = 200) -> dict:
77
+ def __call__(self, table_name: str, columns: list[str], num_vals: int = 200) -> Any:
78
78
  """
79
79
  Fetches the first num_vals unique values from the specified columns of the database table.
80
80
 
@@ -84,7 +84,7 @@ class DBLoadUniqueValues(DBTool):
84
84
  num_vals (int): The number of unique values to fetch for each column. Default is 200.
85
85
 
86
86
  Returns:
87
- dict: A dictionary containing the unique values for each column.
87
+ Any: the result of the database query
88
88
  """
89
89
  res = {}
90
90
  try:
vectara_agentic/tools.py CHANGED
@@ -7,7 +7,7 @@ import re
7
7
  import importlib
8
8
  import os
9
9
 
10
- from typing import Callable, List, Dict, Any, Optional, Type
10
+ from typing import Callable, List, Dict, Any, Optional, Union, Type
11
11
  from pydantic import BaseModel, Field
12
12
  from pydantic_core import PydanticUndefined
13
13
 
@@ -127,7 +127,7 @@ class VectaraTool(FunctionTool):
127
127
  break
128
128
  return is_equal
129
129
 
130
- def _build_filter_string(kwargs: Dict[str, Any], tool_args_type: Dict[str, str], fixed_filter: str) -> str:
130
+ def _build_filter_string(kwargs: Dict[str, Any], tool_args_type: Dict[str, dict], fixed_filter: str) -> str:
131
131
  """
132
132
  Build filter string for Vectara from kwargs
133
133
  """
@@ -141,7 +141,9 @@ def _build_filter_string(kwargs: Dict[str, Any], tool_args_type: Dict[str, str],
141
141
 
142
142
  # Determine the prefix for the key. Valid values are "doc" or "part"
143
143
  # default to 'doc' if not specified
144
- prefix = tool_args_type.get(key, "doc")
144
+ tool_args_dict = tool_args_type.get(key, {'type': 'doc', 'is_list': False})
145
+ prefix = tool_args_dict.get(key, "doc")
146
+ is_list = tool_args_dict.get('is_list', False)
145
147
 
146
148
  if prefix not in ["doc", "part"]:
147
149
  raise ValueError(
@@ -231,14 +233,23 @@ def _build_filter_string(kwargs: Dict[str, Any], tool_args_type: Dict[str, str],
231
233
  filter_parts.append(f"{prefix}.{key}{matched_operator}'{rhs}'")
232
234
  else:
233
235
  if val_str.isdigit() or is_float(val_str):
234
- filter_parts.append(f"{prefix}.{key}={val_str}")
236
+ if is_list:
237
+ filter_parts.append(f"({val_str} IN {prefix}.{key})")
238
+ else:
239
+ filter_parts.append(f"{prefix}.{key}={val_str}")
235
240
  elif val_str.lower() in ["true", "false"]:
236
241
  # This is to handle boolean values.
237
242
  # This is not complete solution - the best solution would be to test if the field is boolean
238
243
  # That can be done after we move to APIv2
239
- filter_parts.append(f"{prefix}.{key}={val_str.lower()}")
244
+ if is_list:
245
+ filter_parts.append(f"({val_str.lower()} IN {prefix}.{key})")
246
+ else:
247
+ filter_parts.append(f"{prefix}.{key}={val_str.lower()}")
240
248
  else:
241
- filter_parts.append(f"{prefix}.{key}='{val_str}'")
249
+ if is_list:
250
+ filter_parts.append(f"('{val_str}' IN {prefix}.{key})")
251
+ else:
252
+ filter_parts.append(f"{prefix}.{key}='{val_str}'")
242
253
 
243
254
  filter_str = " AND ".join(filter_parts)
244
255
  return f"({fixed_filter}) AND ({filter_str})" if fixed_filter else filter_str
@@ -250,21 +261,18 @@ class VectaraToolFactory:
250
261
 
251
262
  def __init__(
252
263
  self,
253
- vectara_customer_id: str = str(os.environ.get("VECTARA_CUSTOMER_ID", "")),
254
- vectara_corpus_id: str = str(os.environ.get("VECTARA_CORPUS_ID", "")),
264
+ vectara_corpus_key: str = str(os.environ.get("VECTARA_CORPUS_KEY", "")),
255
265
  vectara_api_key: str = str(os.environ.get("VECTARA_API_KEY", "")),
256
266
  ) -> None:
257
267
  """
258
268
  Initialize the VectaraToolFactory
259
269
  Args:
260
- vectara_customer_id (str): The Vectara customer ID.
261
- vectara_corpus_id (str): The Vectara corpus ID (or comma separated list of IDs).
270
+ vectara_corpus_key (str): The Vectara corpus key (or comma separated list of keys).
262
271
  vectara_api_key (str): The Vectara API key.
263
272
  """
264
- self.vectara_customer_id = vectara_customer_id
265
- self.vectara_corpus_id = vectara_corpus_id
273
+ self.vectara_corpus_key = vectara_corpus_key
266
274
  self.vectara_api_key = vectara_api_key
267
- self.num_corpora = len(vectara_corpus_id.split(","))
275
+ self.num_corpora = len(vectara_corpus_key.split(","))
268
276
 
269
277
  def create_search_tool(
270
278
  self,
@@ -273,12 +281,20 @@ class VectaraToolFactory:
273
281
  tool_args_schema: type[BaseModel],
274
282
  tool_args_type: Dict[str, str] = {},
275
283
  fixed_filter: str = "",
276
- lambda_val: float = 0.005,
277
- reranker: str = "mmr",
284
+ lambda_val: Union[List[float], float] = 0.005,
285
+ semantics: Union[List[str] | str] = "default",
286
+ custom_dimensions: Union[List[Dict], Dict] = {},
287
+ offset: int = 0,
288
+ n_sentences_before: int = 2,
289
+ n_sentences_after: int = 2,
290
+ reranker: str = "slingshot",
278
291
  rerank_k: int = 50,
292
+ rerank_limit: Optional[int] = None,
293
+ rerank_cutoff: Optional[float] = None,
279
294
  mmr_diversity_bias: float = 0.2,
280
295
  udf_expression: str = None,
281
296
  rerank_chain: List[Dict] = None,
297
+ save_history: bool = False,
282
298
  verbose: bool = False,
283
299
  ) -> VectaraTool:
284
300
  """
@@ -290,9 +306,18 @@ class VectaraToolFactory:
290
306
  tool_args_schema (BaseModel): The schema for the tool arguments.
291
307
  tool_args_type (Dict[str, str], optional): The type of each argument (doc or part).
292
308
  fixed_filter (str, optional): A fixed Vectara filter condition to apply to all queries.
293
- lambda_val (float, optional): Lambda value for the Vectara query.
309
+ lambda_val (Union[List[float] | float], optional): Lambda value (or list of values for each corpora)
310
+ for the Vectara query, when using hybrid search.
311
+ semantics (Union[List[str], str], optional): Indicates whether the query is intended as a query or response.
312
+ Include list if using multiple corpora specifying the query type for each corpus.
313
+ custom_dimensions (Union[List[Dict] | Dict], optional): Custom dimensions for the query (for each corpora).
314
+ offset (int, optional): Number of results to skip.
315
+ n_sentences_before (int, optional): Number of sentences before the matching document part.
316
+ n_sentences_after (int, optional): Number of sentences after the matching document part.
294
317
  reranker (str, optional): The reranker mode.
295
318
  rerank_k (int, optional): Number of top-k documents for reranking.
319
+ rerank_limit (int, optional): Maximum number of results to return after reranking.
320
+ rerank_cutoff (float, optional): Minimum score threshold for results to include after reranking.
296
321
  mmr_diversity_bias (float, optional): MMR diversity bias.
297
322
  udf_expression (str, optional): the user defined expression for reranking results.
298
323
  rerank_chain (List[Dict], optional): A list of rerankers to be applied sequentially.
@@ -300,6 +325,7 @@ class VectaraToolFactory:
300
325
  and any other parameters (e.g. "limit" or "cutoff" for any type,
301
326
  "diversity_bias" for mmr, and "user_function" for udf).
302
327
  If using slingshot/multilingual_reranker_v1, it must be first in the list.
328
+ save_history (bool, optional): Whether to save the query in history.
303
329
  verbose (bool, optional): Whether to print verbose output.
304
330
 
305
331
  Returns:
@@ -308,8 +334,7 @@ class VectaraToolFactory:
308
334
 
309
335
  vectara = VectaraIndex(
310
336
  vectara_api_key=self.vectara_api_key,
311
- vectara_customer_id=self.vectara_customer_id,
312
- vectara_corpus_id=self.vectara_corpus_id,
337
+ vectara_corpus_key=self.vectara_corpus_key,
313
338
  x_source_str="vectara-agentic",
314
339
  )
315
340
 
@@ -341,11 +366,19 @@ class VectaraToolFactory:
341
366
  similarity_top_k=top_k,
342
367
  reranker=reranker,
343
368
  rerank_k=rerank_k if rerank_k * self.num_corpora <= 100 else int(100 / self.num_corpora),
369
+ rerank_limit=rerank_limit,
370
+ rerank_cutoff=rerank_cutoff,
344
371
  mmr_diversity_bias=mmr_diversity_bias,
345
372
  udf_expression=udf_expression,
346
373
  rerank_chain=rerank_chain,
347
374
  lambda_val=lambda_val,
375
+ semantics=semantics,
376
+ custom_dimensions=custom_dimensions,
377
+ offset=offset,
348
378
  filter=filter_string,
379
+ n_sentences_before=n_sentences_before,
380
+ n_sentences_after=n_sentences_after,
381
+ save_history=save_history,
349
382
  x_source_str="vectara-agentic",
350
383
  verbose=verbose,
351
384
  )
@@ -415,21 +448,32 @@ class VectaraToolFactory:
415
448
  tool_name: str,
416
449
  tool_description: str,
417
450
  tool_args_schema: type[BaseModel],
418
- tool_args_type: Dict[str, str] = {},
451
+ tool_args_type: Dict[str, dict] = {},
419
452
  fixed_filter: str = "",
420
- vectara_summarizer: str = "vectara-summary-ext-24-05-sml",
453
+ vectara_summarizer: str = "vectara-summary-ext-24-05-med-omni",
421
454
  vectara_prompt_text: str = None,
422
455
  summary_num_results: int = 5,
423
456
  summary_response_lang: str = "eng",
424
457
  n_sentences_before: int = 2,
425
458
  n_sentences_after: int = 2,
426
- lambda_val: float = 0.005,
427
- reranker: str = "mmr",
459
+ offset: int = 0,
460
+ lambda_val: Union[List[float], float] = 0.005,
461
+ semantics: Union[List[str] | str] = "default",
462
+ custom_dimensions: Union[List[Dict], Dict] = {},
463
+ reranker: str = "slingshot",
428
464
  rerank_k: int = 50,
465
+ rerank_limit: Optional[int] = None,
466
+ rerank_cutoff: Optional[float] = None,
429
467
  mmr_diversity_bias: float = 0.2,
430
468
  udf_expression: str = None,
431
469
  rerank_chain: List[Dict] = None,
470
+ max_response_chars: Optional[int] = None,
471
+ max_tokens: Optional[int] = None,
472
+ temperature: Optional[float] = None,
473
+ frequency_penalty: Optional[float] = None,
474
+ presence_penalty: Optional[float] = None,
432
475
  include_citations: bool = True,
476
+ save_history: bool = False,
433
477
  fcs_threshold: float = 0.0,
434
478
  verbose: bool = False,
435
479
  ) -> VectaraTool:
@@ -440,27 +484,46 @@ class VectaraToolFactory:
440
484
  tool_name (str): The name of the tool.
441
485
  tool_description (str): The description of the tool.
442
486
  tool_args_schema (BaseModel): The schema for the tool arguments.
443
- tool_args_type (Dict[str, str], optional): The type of each argument (doc or part).
487
+ tool_args_type (Dict[str, dict], optional): attributes for each argument where they key is the field name
488
+ and the value is a dictionary with the following keys:
489
+ - 'type': the type of each filter attribute in Vectara (doc or part).
490
+ - 'is_list': whether the filterable attribute is a list.
444
491
  fixed_filter (str, optional): A fixed Vectara filter condition to apply to all queries.
445
492
  vectara_summarizer (str, optional): The Vectara summarizer to use.
446
493
  vectara_prompt_text (str, optional): The prompt text for the Vectara summarizer.
447
494
  summary_num_results (int, optional): The number of summary results.
448
495
  summary_response_lang (str, optional): The response language for the summary.
496
+ summary_prompt_text (str, optional): The custom prompt, using appropriate prompt variables and functions.
449
497
  n_sentences_before (int, optional): Number of sentences before the summary.
450
498
  n_sentences_after (int, optional): Number of sentences after the summary.
451
- lambda_val (float, optional): Lambda value for the Vectara query.
499
+ offset (int, optional): Number of results to skip.
500
+ lambda_val (Union[List[float] | float], optional): Lambda value (or list of values for each corpora)
501
+ for the Vectara query, when using hybrid search.
502
+ semantics (Union[List[str], str], optional): Indicates whether the query is intended as a query or response.
503
+ Include list if using multiple corpora specifying the query type for each corpus.
504
+ custom_dimensions (Union[List[Dict] | Dict], optional): Custom dimensions for the query (for each corpora).
452
505
  reranker (str, optional): The reranker mode.
453
506
  rerank_k (int, optional): Number of top-k documents for reranking.
507
+ rerank_limit (int, optional): Maximum number of results to return after reranking.
508
+ rerank_cutoff (float, optional): Minimum score threshold for results to include after reranking.
454
509
  mmr_diversity_bias (float, optional): MMR diversity bias.
455
- udf_expression (str, optional): the user defined expression for reranking results.
510
+ udf_expression (str, optional): The user defined expression for reranking results.
456
511
  rerank_chain (List[Dict], optional): A list of rerankers to be applied sequentially.
457
512
  Each dictionary should specify the "type" of reranker (mmr, slingshot, udf)
458
513
  and any other parameters (e.g. "limit" or "cutoff" for any type,
459
514
  "diversity_bias" for mmr, and "user_function" for udf).
460
515
  If using slingshot/multilingual_reranker_v1, it must be first in the list.
516
+ max_response_chars (int, optional): The desired maximum number of characters for the generated summary.
517
+ max_tokens (int, optional): The maximum number of tokens to be returned by the LLM.
518
+ temperature (float, optional): The sampling temperature; higher values lead to more randomness.
519
+ frequency_penalty (float, optional): How much to penalize repeating tokens in the response,
520
+ higher values reducing likelihood of repeating the same line.
521
+ presence_penalty (float, optional): How much to penalize repeating tokens in the response,
522
+ higher values increasing the diversity of topics.
461
523
  include_citations (bool, optional): Whether to include citations in the response.
462
524
  If True, uses markdown vectara citations that requires the Vectara scale plan.
463
- fcs_threshold (float, optional): a threshold for factual consistency.
525
+ save_history (bool, optional): Whether to save the query in history.
526
+ fcs_threshold (float, optional): A threshold for factual consistency.
464
527
  If set above 0, the tool notifies the calling agent that it "cannot respond" if FCS is too low.
465
528
  verbose (bool, optional): Whether to print verbose output.
466
529
 
@@ -470,8 +533,7 @@ class VectaraToolFactory:
470
533
 
471
534
  vectara = VectaraIndex(
472
535
  vectara_api_key=self.vectara_api_key,
473
- vectara_customer_id=self.vectara_customer_id,
474
- vectara_corpus_id=self.vectara_corpus_id,
536
+ vectara_corpus_key=self.vectara_corpus_key,
475
537
  x_source_str="vectara-agentic",
476
538
  )
477
539
 
@@ -506,15 +568,26 @@ class VectaraToolFactory:
506
568
  prompt_text=vectara_prompt_text,
507
569
  reranker=reranker,
508
570
  rerank_k=rerank_k if rerank_k * self.num_corpora <= 100 else int(100 / self.num_corpora),
571
+ rerank_limit=rerank_limit,
572
+ rerank_cutoff=rerank_cutoff,
509
573
  mmr_diversity_bias=mmr_diversity_bias,
510
574
  udf_expression=udf_expression,
511
575
  rerank_chain=rerank_chain,
512
576
  n_sentence_before=n_sentences_before,
513
577
  n_sentence_after=n_sentences_after,
578
+ offset=offset,
514
579
  lambda_val=lambda_val,
580
+ semantics=semantics,
581
+ custom_dimensions=custom_dimensions,
515
582
  filter=filter_string,
516
- citations_style="MARKDOWN" if include_citations else None,
583
+ max_response_chars=max_response_chars,
584
+ max_tokens=max_tokens,
585
+ temperature=temperature,
586
+ frequency_penalty=frequency_penalty,
587
+ presence_penalty=presence_penalty,
588
+ citations_style="markdown" if include_citations else None,
517
589
  citations_url_pattern="{doc.url}" if include_citations else None,
590
+ save_history=save_history,
518
591
  x_source_str="vectara-agentic",
519
592
  verbose=verbose,
520
593
  )
@@ -557,7 +630,7 @@ class VectaraToolFactory:
557
630
  + ".\n"
558
631
  )
559
632
  fcs = response.metadata["fcs"] if "fcs" in response.metadata else 0.0
560
- if fcs < fcs_threshold:
633
+ if fcs and fcs < fcs_threshold:
561
634
  msg = f"Could not answer the query due to suspected hallucination (fcs={fcs})."
562
635
  return ToolOutput(
563
636
  tool_name=rag_function.__name__,
vectara_agentic/types.py CHANGED
@@ -47,8 +47,8 @@ class AgentStatusType(Enum):
47
47
  class LLMRole(Enum):
48
48
  """Enumeration for different types of LLM roles."""
49
49
 
50
- MAIN: str = "MAIN"
51
- TOOL: str = "TOOL"
50
+ MAIN = "MAIN"
51
+ TOOL = "TOOL"
52
52
 
53
53
 
54
54
  class ToolType(Enum):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: vectara_agentic
3
- Version: 0.1.27
3
+ Version: 0.2.0
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
@@ -17,7 +17,7 @@ Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: llama-index==0.12.11
20
- Requires-Dist: llama-index-indices-managed-vectara==0.3.1
20
+ Requires-Dist: llama-index-indices-managed-vectara==0.4.0
21
21
  Requires-Dist: llama-index-agent-llm-compiler==0.3.0
22
22
  Requires-Dist: llama-index-agent-lats==0.3.0
23
23
  Requires-Dist: llama-index-agent-openai==0.4.3
@@ -0,0 +1,21 @@
1
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ tests/test_agent.py,sha256=bhKwmWsYTwTCrI-D4hXGKZPPDzgOJF3XtjhYo-bV2xc,3963
3
+ tests/test_tools.py,sha256=Nn8iTabsCspABdt3eW13lAy8GJL1xRS42XQxBhwN__I,2762
4
+ vectara_agentic/__init__.py,sha256=ADH4fPKLbpGNYYYszv3c3QDOjPToPE_qh3LpkH_seCU,430
5
+ vectara_agentic/_callback.py,sha256=jpzHqnl297k2qajYc-6nkPtIPtgVLpVWYEISHS7ySlM,9186
6
+ vectara_agentic/_observability.py,sha256=HeQYJIkqPLW3EWHiXHatkaJzo08IQGESKujdeWTuRgk,3805
7
+ vectara_agentic/_prompts.py,sha256=mgGx3zUJPtpS1epBLtl0BnoLeE7wb6AX1SX6dFNaTTQ,6368
8
+ vectara_agentic/_version.py,sha256=BLvF264tVnfoZW3j2NXD3gU6WcA1j4dfS2TtMqZ6oJs,65
9
+ vectara_agentic/agent.py,sha256=57VftipZRZXAwf6LXdyY0zsyCInLcR0ZGvYr1SwTakI,29354
10
+ vectara_agentic/agent_config.py,sha256=9P9lyFAAXLX1ft2dBQ6tYN7dKzp7SC7B-h-DnhUHsSg,2941
11
+ vectara_agentic/agent_endpoint.py,sha256=QIMejCLlpW2qzXxeDAxv3anF46XMDdVMdKGWhJh3azY,1996
12
+ vectara_agentic/db_tools.py,sha256=3_hPrutNIGEeU2kH503GjcYbtAMsK6BidQLIm6DT6C8,3591
13
+ vectara_agentic/tools.py,sha256=xhi8lvs351_8WQPQu6oOMdwond9MqqqVt9RHR4NjazI,39238
14
+ vectara_agentic/tools_catalog.py,sha256=O3vYFpZ5EQeh37X70TiHepXFGN5yGk4_d7CkrkLeUhk,5205
15
+ vectara_agentic/types.py,sha256=8yeRHr1iYV9lmsWUwtfreHUvYaw1u9CSiQIhBkjcWxc,1579
16
+ vectara_agentic/utils.py,sha256=eDEOUpCkb0r216LxSLkamll2NmJhu76Z1TgQFbAVq7A,4690
17
+ vectara_agentic-0.2.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
18
+ vectara_agentic-0.2.0.dist-info/METADATA,sha256=iHGfo8TF7CfneXOKNTXdWoYDuiOILc77uru_HzPX1H0,20564
19
+ vectara_agentic-0.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
+ vectara_agentic-0.2.0.dist-info/top_level.txt,sha256=Y7TQTFdOYGYodQRltUGRieZKIYuzeZj2kHqAUpfCUfg,22
21
+ vectara_agentic-0.2.0.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- tests/test_agent.py,sha256=8LQlny0rIuVa13LGtebG0vatES6Ln7gmenbSwX-ctrY,4260
3
- tests/test_tools.py,sha256=2ofZYz3Q-YMSxjpiEg1VNUlA9gMjvNAcJAO2Ucd0eVE,2969
4
- vectara_agentic/__init__.py,sha256=ADH4fPKLbpGNYYYszv3c3QDOjPToPE_qh3LpkH_seCU,430
5
- vectara_agentic/_callback.py,sha256=OBiHk_OJZTS3iKz_LigfEjnl_p5V90XYsQC0vEYVSPo,8782
6
- vectara_agentic/_observability.py,sha256=HeQYJIkqPLW3EWHiXHatkaJzo08IQGESKujdeWTuRgk,3805
7
- vectara_agentic/_prompts.py,sha256=mgGx3zUJPtpS1epBLtl0BnoLeE7wb6AX1SX6dFNaTTQ,6368
8
- vectara_agentic/_version.py,sha256=GEtlQ0AzDcdXdoBw5AdY2tskbBPt_CIbCorCmGmpY4I,66
9
- vectara_agentic/agent.py,sha256=PnBKpHOs8TgUxSoLRqsXygRxK64cdybM2kpwawEH7ps,26059
10
- vectara_agentic/agent_config.py,sha256=9P9lyFAAXLX1ft2dBQ6tYN7dKzp7SC7B-h-DnhUHsSg,2941
11
- vectara_agentic/agent_endpoint.py,sha256=QIMejCLlpW2qzXxeDAxv3anF46XMDdVMdKGWhJh3azY,1996
12
- vectara_agentic/db_tools.py,sha256=kCEENzmnorm8i-k4Kpd4KLJt1QWh_ZlAyX1aG-tzET0,3619
13
- vectara_agentic/tools.py,sha256=Rr1N-gKbxTSjpn2FMg6JPDSueXBtcQsrVMummbmrULg,34428
14
- vectara_agentic/tools_catalog.py,sha256=O3vYFpZ5EQeh37X70TiHepXFGN5yGk4_d7CkrkLeUhk,5205
15
- vectara_agentic/types.py,sha256=00wm3YsJRyddvIBzeVjF3qklA38NuTkCvy_B-e68v6c,1589
16
- vectara_agentic/utils.py,sha256=eDEOUpCkb0r216LxSLkamll2NmJhu76Z1TgQFbAVq7A,4690
17
- vectara_agentic-0.1.27.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
18
- vectara_agentic-0.1.27.dist-info/METADATA,sha256=bBV3Fxae95yg_qikzLgZqCXTU_bM3hhcsBGGuPZBDxk,20565
19
- vectara_agentic-0.1.27.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
- vectara_agentic-0.1.27.dist-info/top_level.txt,sha256=Y7TQTFdOYGYodQRltUGRieZKIYuzeZj2kHqAUpfCUfg,22
21
- vectara_agentic-0.1.27.dist-info/RECORD,,