vectara-agentic 0.2.14__tar.gz → 0.2.15__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.14/vectara_agentic.egg-info → vectara_agentic-0.2.15}/PKG-INFO +1 -1
- vectara_agentic-0.2.15/tests/test_return_direct.py +49 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_tools.py +1 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_vectara_llms.py +4 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/_observability.py +43 -21
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/_prompts.py +1 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/_version.py +1 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/agent.py +18 -9
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/tool_utils.py +117 -94
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/tools.py +18 -8
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/tools_catalog.py +1 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15/vectara_agentic.egg-info}/PKG-INFO +1 -1
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic.egg-info/SOURCES.txt +1 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/LICENSE +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/MANIFEST.in +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/README.md +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/requirements.txt +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/setup.cfg +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/setup.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/__init__.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/endpoint.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_agent.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_agent_planning.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_agent_type.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_fallback.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_groq.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_private_llm.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_serialization.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/tests/test_workflow.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/__init__.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/_callback.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/agent_config.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/agent_endpoint.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/db_tools.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/llm_utils.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/sub_query_workflow.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/types.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic/utils.py +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic.egg-info/dependency_links.txt +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic.egg-info/requires.txt +0 -0
- {vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from vectara_agentic.agent import Agent
|
|
4
|
+
from vectara_agentic.tools import VectaraToolFactory
|
|
5
|
+
|
|
6
|
+
vectara_corpus_key = "vectara-docs_1"
|
|
7
|
+
vectara_api_key = "zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestAgentPackage(unittest.TestCase):
|
|
11
|
+
|
|
12
|
+
def test_return_direct1(self):
|
|
13
|
+
vec_factory = VectaraToolFactory(vectara_corpus_key, vectara_api_key)
|
|
14
|
+
|
|
15
|
+
query_tool = vec_factory.create_rag_tool(
|
|
16
|
+
tool_name="rag_tool",
|
|
17
|
+
tool_description="""
|
|
18
|
+
A dummy tool for testing return_direct.
|
|
19
|
+
""",
|
|
20
|
+
return_direct=True,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
agent = Agent(
|
|
24
|
+
tools=[query_tool],
|
|
25
|
+
topic="Sample topic",
|
|
26
|
+
custom_instructions="You are a helpful assistant.",
|
|
27
|
+
)
|
|
28
|
+
res = agent.chat("What is Vectara?")
|
|
29
|
+
self.assertIn("Response:", str(res))
|
|
30
|
+
self.assertIn("fcs_score", str(res))
|
|
31
|
+
self.assertIn("References:", str(res))
|
|
32
|
+
|
|
33
|
+
def test_from_corpus(self):
|
|
34
|
+
agent = Agent.from_corpus(
|
|
35
|
+
tool_name="rag_tool",
|
|
36
|
+
vectara_corpus_key=vectara_corpus_key,
|
|
37
|
+
vectara_api_key=vectara_api_key,
|
|
38
|
+
data_description="stuff about Vectara",
|
|
39
|
+
assistant_specialty="question answering",
|
|
40
|
+
return_direct=True,
|
|
41
|
+
)
|
|
42
|
+
res = agent.chat("What is Vectara?")
|
|
43
|
+
self.assertIn("Response:", str(res))
|
|
44
|
+
self.assertIn("fcs_score", str(res))
|
|
45
|
+
self.assertIn("References:", str(res))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
unittest.main()
|
|
@@ -196,7 +196,7 @@ class TestToolsPackage(unittest.TestCase):
|
|
|
196
196
|
custom_instructions="Call the tool with 15 arguments for OPENAI",
|
|
197
197
|
agent_config=config,
|
|
198
198
|
)
|
|
199
|
-
res = agent.chat("What is the stock price?")
|
|
199
|
+
res = agent.chat("What is the stock price for Yahoo on 12/31/22?")
|
|
200
200
|
self.assertIn("maximum length of 1024 characters", str(res))
|
|
201
201
|
|
|
202
202
|
# Same test but with GROQ
|
|
@@ -15,7 +15,10 @@ vectara_api_key = "zqt_UXrBcnI2UXINZkrv4g1tQPhzj02vfdtqYJIDiA"
|
|
|
15
15
|
class TestLLMPackage(unittest.TestCase):
|
|
16
16
|
|
|
17
17
|
def test_vectara_openai(self):
|
|
18
|
-
vec_factory = VectaraToolFactory(
|
|
18
|
+
vec_factory = VectaraToolFactory(
|
|
19
|
+
vectara_corpus_key=vectara_corpus_key,
|
|
20
|
+
vectara_api_key=vectara_api_key
|
|
21
|
+
)
|
|
19
22
|
|
|
20
23
|
self.assertEqual(vectara_corpus_key, vec_factory.vectara_corpus_key)
|
|
21
24
|
self.assertEqual(vectara_api_key, vec_factory.vectara_api_key)
|
|
@@ -12,28 +12,50 @@ def setup_observer(config: AgentConfig, verbose: bool) -> bool:
|
|
|
12
12
|
'''
|
|
13
13
|
Setup the observer.
|
|
14
14
|
'''
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
15
|
+
if config.observer != ObserverType.ARIZE_PHOENIX:
|
|
16
|
+
if verbose:
|
|
17
|
+
print("No Phoenix observer set.")
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
import phoenix as px
|
|
22
|
+
from openinference.instrumentation.llama_index import LlamaIndexInstrumentor
|
|
23
|
+
from phoenix.otel import register
|
|
24
|
+
except ImportError:
|
|
25
|
+
print(
|
|
26
|
+
(
|
|
27
|
+
"Phoenix libraries not found. Please install with"
|
|
28
|
+
"'pip install arize-phoenix openinference-instrumentation-llama-index'"
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
phoenix_endpoint = os.getenv("PHOENIX_ENDPOINT", None)
|
|
34
|
+
if not phoenix_endpoint:
|
|
35
|
+
print("Phoenix endpoint not set. Attempting to launch local Phoenix UI...")
|
|
36
|
+
px.launch_app()
|
|
37
|
+
print("Local Phoenix UI launched. You can view traces at the UI address (usually http://localhost:6006).")
|
|
38
|
+
|
|
39
|
+
if phoenix_endpoint and 'app.phoenix.arize.com' in phoenix_endpoint:
|
|
40
|
+
phoenix_api_key = os.getenv("PHOENIX_API_KEY")
|
|
41
|
+
if not phoenix_api_key:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
"Arize Phoenix API key not set. Please set PHOENIX_API_KEY."
|
|
44
|
+
)
|
|
45
|
+
os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={phoenix_api_key}"
|
|
46
|
+
os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com"
|
|
47
|
+
|
|
48
|
+
reg_kwargs = {
|
|
49
|
+
"endpoint": phoenix_endpoint or 'http://localhost:6006/v1/traces',
|
|
50
|
+
"project_name": "vectara-agentic",
|
|
51
|
+
"batch": True,
|
|
52
|
+
"set_global_tracer_provider": False,
|
|
53
|
+
}
|
|
54
|
+
tracer_provider = register(**reg_kwargs)
|
|
55
|
+
LlamaIndexInstrumentor().instrument(tracer_provider=tracer_provider)
|
|
34
56
|
if verbose:
|
|
35
|
-
print("
|
|
36
|
-
return
|
|
57
|
+
print(f"Phoenix observer configured for project 'vectara-agentic' at endpoint: {reg_kwargs['endpoint']}")
|
|
58
|
+
return True
|
|
37
59
|
|
|
38
60
|
|
|
39
61
|
def _extract_fcs_value(output: Union[str, dict]) -> Optional[float]:
|
|
@@ -5,7 +5,7 @@ This file contains the prompt templates for the different types of agents.
|
|
|
5
5
|
# General (shared) instructions
|
|
6
6
|
GENERAL_INSTRUCTIONS = """
|
|
7
7
|
- Use tools as your main source of information, do not respond without using a tool. Do not respond based on pre-trained knowledge.
|
|
8
|
-
- Use the 'get_bad_topics' tool to determine the topics you are not allowed to discuss or respond to.
|
|
8
|
+
- Use the 'get_bad_topics' (if it exists) tool to determine the topics you are not allowed to discuss or respond to.
|
|
9
9
|
- Before responding to a user query that requires knowledge of the current date, call the 'get_current_date' tool to get the current date.
|
|
10
10
|
Never rely on previous knowledge of the current date.
|
|
11
11
|
Example queries that require the current date: "What is the revenue of Apple last october?" or "What was the stock price 5 days ago?".
|
|
@@ -248,19 +248,25 @@ class Agent:
|
|
|
248
248
|
|
|
249
249
|
if validate_tools:
|
|
250
250
|
prompt = f"""
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
You are provided these tools:
|
|
252
|
+
<tools>{','.join(tool_names)}</tools>
|
|
253
|
+
And these instructions:
|
|
254
|
+
<instructions>
|
|
254
255
|
{self._custom_instructions}
|
|
255
|
-
|
|
256
|
-
Your
|
|
257
|
-
|
|
256
|
+
</instructions>
|
|
257
|
+
Your task is to identify invalid tools.
|
|
258
|
+
A tool is invalid if it is mentioned in the instructions but not in the tools list.
|
|
259
|
+
A tool's name must have at least two characters.
|
|
260
|
+
Your response should be a comma-separated list of the invalid tools.
|
|
261
|
+
If not invalid tools exist, respond with "<OKAY>".
|
|
258
262
|
"""
|
|
259
263
|
llm = get_llm(LLMRole.MAIN, config=self.agent_config)
|
|
260
|
-
|
|
261
|
-
if
|
|
264
|
+
bad_tools_str = llm.complete(prompt).text
|
|
265
|
+
if bad_tools_str and bad_tools_str != "<OKAY>":
|
|
266
|
+
bad_tools = [tool.strip() for tool in bad_tools_str.split(",")]
|
|
267
|
+
numbered = ", ".join(f"({i}) {tool}" for i, tool in enumerate(bad_tools, 1))
|
|
262
268
|
raise ValueError(
|
|
263
|
-
f"The Agent custom instructions mention these invalid tools: {
|
|
269
|
+
f"The Agent custom instructions mention these invalid tools: {numbered}"
|
|
264
270
|
)
|
|
265
271
|
|
|
266
272
|
# Create token counters for the main and tool LLMs
|
|
@@ -689,6 +695,7 @@ class Agent:
|
|
|
689
695
|
vectara_frequency_penalty: Optional[float] = None,
|
|
690
696
|
vectara_presence_penalty: Optional[float] = None,
|
|
691
697
|
vectara_save_history: bool = True,
|
|
698
|
+
return_direct: bool = False,
|
|
692
699
|
) -> "Agent":
|
|
693
700
|
"""
|
|
694
701
|
Create an agent from a single Vectara corpus
|
|
@@ -738,6 +745,7 @@ class Agent:
|
|
|
738
745
|
vectara_presence_penalty (float, optional): How much to penalize repeating tokens in the response,
|
|
739
746
|
higher values increasing the diversity of topics.
|
|
740
747
|
vectara_save_history (bool, optional): Whether to save the query in history.
|
|
748
|
+
return_direct (bool, optional): Whether the agent should return the tool's response directly.
|
|
741
749
|
|
|
742
750
|
Returns:
|
|
743
751
|
Agent: An instance of the Agent class.
|
|
@@ -791,6 +799,7 @@ class Agent:
|
|
|
791
799
|
save_history=vectara_save_history,
|
|
792
800
|
include_citations=True,
|
|
793
801
|
verbose=verbose,
|
|
802
|
+
return_direct=return_direct,
|
|
794
803
|
)
|
|
795
804
|
|
|
796
805
|
assistant_instructions = f"""
|
|
@@ -231,44 +231,119 @@ class VectaraTool(FunctionTool):
|
|
|
231
231
|
return err_output
|
|
232
232
|
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
class EmptyBaseModel(BaseModel):
|
|
235
|
+
"""empty base model"""
|
|
236
|
+
|
|
237
|
+
def _unwrap_default(default):
|
|
238
|
+
# PydanticUndefined means “no default — required”
|
|
239
|
+
return default if default is not PydanticUndefined else inspect.Parameter.empty
|
|
240
|
+
|
|
241
|
+
def _schema_default(default):
|
|
242
|
+
# PydanticUndefined ⇒ Ellipsis (required)
|
|
243
|
+
return default if default is not PydanticUndefined else ...
|
|
244
|
+
|
|
245
|
+
def _make_docstring(
|
|
246
|
+
function: Callable[..., ToolOutput],
|
|
247
|
+
tool_name: str,
|
|
248
|
+
tool_description: str,
|
|
249
|
+
fn_schema: Type[BaseModel],
|
|
250
|
+
all_params: List[inspect.Parameter],
|
|
251
|
+
compact_docstring: bool,
|
|
252
|
+
) -> str:
|
|
253
|
+
params_str = ", ".join(
|
|
254
|
+
f"{p.name}: {p.annotation.__name__ if hasattr(p.annotation, '__name__') else p.annotation}"
|
|
255
|
+
for p in all_params
|
|
256
|
+
)
|
|
257
|
+
signature_line = f"{tool_name}({params_str}) -> dict[str, Any]"
|
|
258
|
+
if compact_docstring:
|
|
259
|
+
doc_lines = [tool_description.strip()]
|
|
260
|
+
else:
|
|
261
|
+
doc_lines = [signature_line, "", tool_description.strip()]
|
|
262
|
+
doc_lines += [
|
|
263
|
+
"",
|
|
264
|
+
"Args:",
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
full_schema = fn_schema.model_json_schema()
|
|
268
|
+
props = full_schema.get("properties", {})
|
|
269
|
+
for prop_name, schema_prop in props.items():
|
|
270
|
+
desc = schema_prop.get("description", "")
|
|
271
|
+
|
|
272
|
+
# pick up any examples you declared on the Field or via schema_extra
|
|
273
|
+
examples = schema_prop.get("examples", [])
|
|
274
|
+
default = schema_prop.get("default", PydanticUndefined)
|
|
275
|
+
|
|
276
|
+
# format the type, default, description, examples
|
|
277
|
+
# find the matching inspect.Parameter so you get its annotation
|
|
278
|
+
param = next((p for p in all_params if p.name == prop_name), None)
|
|
279
|
+
if param and hasattr(param.annotation, "__name__"):
|
|
280
|
+
ty = param.annotation.__name__
|
|
281
|
+
else:
|
|
282
|
+
ty = schema_prop.get("type", "")
|
|
283
|
+
|
|
284
|
+
# inline default if present
|
|
285
|
+
default_txt = f", default={default!r}" if default is not PydanticUndefined else ""
|
|
286
|
+
|
|
287
|
+
# inline examples if any
|
|
288
|
+
if examples:
|
|
289
|
+
examples_txt = ", ".join(repr(e) for e in examples)
|
|
290
|
+
desc = f"{desc} (e.g., {examples_txt})"
|
|
291
|
+
|
|
292
|
+
doc_lines.append(f" - {prop_name} ({ty}{default_txt}): {desc}")
|
|
293
|
+
|
|
294
|
+
doc_lines.append("")
|
|
295
|
+
doc_lines.append("Returns:")
|
|
296
|
+
return_desc = getattr(
|
|
297
|
+
function, "__return_description__", "A dictionary containing the result data."
|
|
298
|
+
)
|
|
299
|
+
doc_lines.append(f" dict[str, Any]: {return_desc}")
|
|
300
|
+
|
|
301
|
+
initial_docstring = "\n".join(doc_lines)
|
|
302
|
+
collapsed_spaces = re.sub(r' {2,}', ' ', initial_docstring)
|
|
303
|
+
final_docstring = re.sub(r'\n{2,}', '\n', collapsed_spaces).strip()
|
|
304
|
+
return final_docstring
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def create_tool_from_dynamic_function(
|
|
235
308
|
function: Callable[..., ToolOutput],
|
|
236
309
|
tool_name: str,
|
|
237
310
|
tool_description: str,
|
|
238
311
|
base_params_model: Type[BaseModel],
|
|
239
312
|
tool_args_schema: Type[BaseModel],
|
|
240
313
|
compact_docstring: bool = False,
|
|
314
|
+
return_direct: bool = False,
|
|
241
315
|
) -> VectaraTool:
|
|
242
|
-
|
|
243
|
-
|
|
316
|
+
"""
|
|
317
|
+
Create a VectaraTool from a dynamic function.
|
|
318
|
+
Args:
|
|
319
|
+
function (Callable[..., ToolOutput]): The function to wrap as a tool.
|
|
320
|
+
tool_name (str): The name of the tool.
|
|
321
|
+
tool_description (str): The description of the tool.
|
|
322
|
+
base_params_model (Type[BaseModel]): The Pydantic model for the base parameters.
|
|
323
|
+
tool_args_schema (Type[BaseModel]): The Pydantic model for the tool arguments.
|
|
324
|
+
compact_docstring (bool): Whether to use a compact docstring format.
|
|
325
|
+
Returns:
|
|
326
|
+
VectaraTool: The created VectaraTool.
|
|
327
|
+
"""
|
|
244
328
|
if tool_args_schema is None:
|
|
245
|
-
|
|
246
|
-
class EmptyBaseModel(BaseModel):
|
|
247
|
-
"""empty base model"""
|
|
248
|
-
|
|
249
329
|
tool_args_schema = EmptyBaseModel
|
|
250
330
|
|
|
331
|
+
if not isinstance(tool_args_schema, type) or not issubclass(tool_args_schema, BaseModel):
|
|
332
|
+
raise TypeError("tool_args_schema must be a Pydantic BaseModel subclass")
|
|
333
|
+
|
|
251
334
|
fields = {}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
)
|
|
256
|
-
default_value = (
|
|
257
|
-
model_field.default
|
|
258
|
-
if model_field.default is not None
|
|
259
|
-
else inspect.Parameter.empty
|
|
260
|
-
)
|
|
335
|
+
base_params = []
|
|
336
|
+
for field_name, field_info in base_params_model.model_fields.items():
|
|
337
|
+
field_type = field_info.annotation
|
|
338
|
+
default_value = _unwrap_default(field_info.default)
|
|
261
339
|
param = inspect.Parameter(
|
|
262
|
-
|
|
340
|
+
field_name,
|
|
263
341
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
264
342
|
default=default_value,
|
|
265
343
|
annotation=field_type,
|
|
266
344
|
)
|
|
267
345
|
base_params.append(param)
|
|
268
|
-
fields[
|
|
269
|
-
field_type,
|
|
270
|
-
model_field.default if model_field.default is not None else ...,
|
|
271
|
-
)
|
|
346
|
+
fields[field_name] = (field_type, _schema_default(field_info.default))
|
|
272
347
|
|
|
273
348
|
# Add tool_args_schema fields to the fields dict if not already included.
|
|
274
349
|
# Also add them to the function signature by creating new inspect.Parameter objects.
|
|
@@ -276,20 +351,16 @@ def _create_tool_from_dynamic_function(
|
|
|
276
351
|
if field_name in fields:
|
|
277
352
|
continue
|
|
278
353
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
fields[field_name] = (field_type, default_value)
|
|
354
|
+
field_type = field_info.annotation
|
|
355
|
+
default_value = _unwrap_default(field_info.default)
|
|
282
356
|
param = inspect.Parameter(
|
|
283
357
|
field_name,
|
|
284
358
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
285
|
-
default=
|
|
286
|
-
default_value
|
|
287
|
-
if default_value is not ...
|
|
288
|
-
else inspect.Parameter.empty
|
|
289
|
-
),
|
|
359
|
+
default=default_value,
|
|
290
360
|
annotation=field_type,
|
|
291
361
|
)
|
|
292
362
|
base_params.append(param)
|
|
363
|
+
fields[field_name] = (field_type, _schema_default(field_info.default))
|
|
293
364
|
|
|
294
365
|
# Create the dynamic schema with both base_params_model and tool_args_schema fields.
|
|
295
366
|
fn_schema = create_model(f"{tool_name}_schema", **fields)
|
|
@@ -304,87 +375,39 @@ def _create_tool_from_dynamic_function(
|
|
|
304
375
|
function.__annotations__["return"] = dict[str, Any]
|
|
305
376
|
function.__name__ = re.sub(r"[^A-Za-z0-9_]", "_", tool_name)
|
|
306
377
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
378
|
+
function.__doc__ = _make_docstring(
|
|
379
|
+
function,
|
|
380
|
+
tool_name, tool_description, fn_schema,
|
|
381
|
+
all_params, compact_docstring
|
|
311
382
|
)
|
|
312
|
-
signature_line = f"{tool_name}({params_str}) -> dict[str, Any]"
|
|
313
|
-
if compact_docstring:
|
|
314
|
-
doc_lines = [
|
|
315
|
-
tool_description.strip(),
|
|
316
|
-
]
|
|
317
|
-
else:
|
|
318
|
-
doc_lines = [
|
|
319
|
-
signature_line,
|
|
320
|
-
"",
|
|
321
|
-
tool_description.strip(),
|
|
322
|
-
]
|
|
323
|
-
doc_lines += [
|
|
324
|
-
"",
|
|
325
|
-
"Args:",
|
|
326
|
-
]
|
|
327
|
-
for param in all_params:
|
|
328
|
-
description = ""
|
|
329
|
-
if param.name in base_params_model.model_fields:
|
|
330
|
-
description = base_params_model.model_fields[param.name].description
|
|
331
|
-
elif param.name in tool_args_schema.model_fields:
|
|
332
|
-
description = tool_args_schema.model_fields[param.name].description
|
|
333
|
-
if not description:
|
|
334
|
-
description = ""
|
|
335
|
-
type_name = (
|
|
336
|
-
param.annotation.__name__
|
|
337
|
-
if hasattr(param.annotation, "__name__")
|
|
338
|
-
else str(param.annotation)
|
|
339
|
-
)
|
|
340
|
-
if (
|
|
341
|
-
param.default is not inspect.Parameter.empty
|
|
342
|
-
and param.default is not PydanticUndefined
|
|
343
|
-
):
|
|
344
|
-
default_text = f", default={param.default!r}"
|
|
345
|
-
else:
|
|
346
|
-
default_text = ""
|
|
347
|
-
doc_lines.append(f" - {param.name} ({type_name}){default_text}: {description}")
|
|
348
|
-
doc_lines.append("")
|
|
349
|
-
doc_lines.append("Returns:")
|
|
350
|
-
return_desc = getattr(
|
|
351
|
-
function, "__return_description__", "A dictionary containing the result data."
|
|
352
|
-
)
|
|
353
|
-
doc_lines.append(f" dict[str, Any]: {return_desc}")
|
|
354
|
-
|
|
355
|
-
initial_docstring = "\n".join(doc_lines)
|
|
356
|
-
collapsed_spaces = re.sub(r' {2,}', ' ', initial_docstring)
|
|
357
|
-
final_docstring = re.sub(r'\n{2,}', '\n', collapsed_spaces).strip()
|
|
358
|
-
function.__doc__ = final_docstring
|
|
359
|
-
|
|
360
383
|
tool = VectaraTool.from_defaults(
|
|
361
384
|
fn=function,
|
|
362
385
|
name=tool_name,
|
|
363
386
|
description=function.__doc__,
|
|
364
387
|
fn_schema=fn_schema,
|
|
365
388
|
tool_type=ToolType.QUERY,
|
|
389
|
+
return_direct=return_direct,
|
|
366
390
|
)
|
|
367
391
|
return tool
|
|
368
392
|
|
|
369
393
|
|
|
370
|
-
|
|
394
|
+
_PARSE_RANGE_REGEX = re.compile(
|
|
395
|
+
r"""
|
|
396
|
+
^([\[\(])\s* # opening bracket
|
|
397
|
+
([+-]?\d+(\.\d*)?)\s*, # first number
|
|
398
|
+
\s*([+-]?\d+(\.\d*)?) # second number
|
|
399
|
+
\s*([\]\)])$ # closing bracket
|
|
400
|
+
""",
|
|
401
|
+
re.VERBOSE,
|
|
402
|
+
)
|
|
371
403
|
|
|
372
404
|
|
|
373
|
-
def _parse_range(val_str: str) ->
|
|
405
|
+
def _parse_range(val_str: str) -> Tuple[float, float, bool, bool]:
|
|
374
406
|
"""
|
|
375
407
|
Parses '[1,10)' or '(0.5, 5]' etc.
|
|
376
408
|
Returns (start, end, start_incl, end_incl) or raises ValueError.
|
|
377
409
|
"""
|
|
378
|
-
m =
|
|
379
|
-
r"""
|
|
380
|
-
^([\[\(])\s* # opening bracket
|
|
381
|
-
([+-]?\d+(\.\d*)?)\s*, # first number
|
|
382
|
-
\s*([+-]?\d+(\.\d*)?) # second number
|
|
383
|
-
\s*([\]\)])$ # closing bracket
|
|
384
|
-
""",
|
|
385
|
-
val_str,
|
|
386
|
-
re.VERBOSE,
|
|
387
|
-
)
|
|
410
|
+
m = _PARSE_RANGE_REGEX.match(val_str)
|
|
388
411
|
if not m:
|
|
389
412
|
raise ValueError(f"Invalid range syntax: {val_str!r}")
|
|
390
413
|
start_inc = m.group(1) == "["
|
|
@@ -426,7 +449,7 @@ def _parse_comparison(val_str: str) -> Tuple[str, Union[float, str, bool]]:
|
|
|
426
449
|
raise ValueError(f"No valid comparison operator at start of {val_str!r}")
|
|
427
450
|
|
|
428
451
|
|
|
429
|
-
def
|
|
452
|
+
def build_filter_string(
|
|
430
453
|
kwargs: Dict[str, Any], tool_args_type: Dict[str, dict], fixed_filter: str
|
|
431
454
|
) -> str:
|
|
432
455
|
"""
|
|
@@ -22,9 +22,9 @@ from .db_tools import DatabaseTools
|
|
|
22
22
|
from .utils import summarize_documents, is_float
|
|
23
23
|
from .agent_config import AgentConfig
|
|
24
24
|
from .tool_utils import (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
VectaraTool
|
|
25
|
+
create_tool_from_dynamic_function,
|
|
26
|
+
build_filter_string,
|
|
27
|
+
VectaraTool,
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
LI_packages = {
|
|
@@ -62,6 +62,7 @@ LI_packages = {
|
|
|
62
62
|
},
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
|
|
65
66
|
class VectaraToolFactory:
|
|
66
67
|
"""
|
|
67
68
|
A factory class for creating Vectara RAG tools.
|
|
@@ -108,6 +109,7 @@ class VectaraToolFactory:
|
|
|
108
109
|
mmr_diversity_bias: float = 0.2,
|
|
109
110
|
udf_expression: str = None,
|
|
110
111
|
rerank_chain: List[Dict] = None,
|
|
112
|
+
return_direct: bool = False,
|
|
111
113
|
save_history: bool = True,
|
|
112
114
|
verbose: bool = False,
|
|
113
115
|
vectara_base_url: str = "https://api.vectara.io",
|
|
@@ -142,6 +144,7 @@ class VectaraToolFactory:
|
|
|
142
144
|
"diversity_bias" for mmr, and "user_function" for udf).
|
|
143
145
|
If using slingshot/multilingual_reranker_v1, it must be first in the list.
|
|
144
146
|
save_history (bool, optional): Whether to save the query in history.
|
|
147
|
+
return_direct (bool, optional): Whether the agent should return the tool's response directly.
|
|
145
148
|
verbose (bool, optional): Whether to print verbose output.
|
|
146
149
|
vectara_base_url (str, optional): The base URL for the Vectara API.
|
|
147
150
|
vectara_verify_ssl (bool, optional): Whether to verify SSL certificates for the Vectara API.
|
|
@@ -177,7 +180,7 @@ class VectaraToolFactory:
|
|
|
177
180
|
else summarize_docs
|
|
178
181
|
)
|
|
179
182
|
try:
|
|
180
|
-
filter_string =
|
|
183
|
+
filter_string = build_filter_string(
|
|
181
184
|
kwargs, tool_args_type, fixed_filter
|
|
182
185
|
)
|
|
183
186
|
except ValueError as e:
|
|
@@ -289,7 +292,7 @@ class VectaraToolFactory:
|
|
|
289
292
|
+ "Use this tool to search for relevant documents, not to ask questions."
|
|
290
293
|
)
|
|
291
294
|
|
|
292
|
-
tool =
|
|
295
|
+
tool = create_tool_from_dynamic_function(
|
|
293
296
|
search_function,
|
|
294
297
|
tool_name,
|
|
295
298
|
search_tool_extra_desc,
|
|
@@ -300,6 +303,7 @@ class VectaraToolFactory:
|
|
|
300
303
|
),
|
|
301
304
|
tool_args_schema,
|
|
302
305
|
compact_docstring=self.compact_docstring,
|
|
306
|
+
return_direct=return_direct,
|
|
303
307
|
)
|
|
304
308
|
return tool
|
|
305
309
|
|
|
@@ -336,6 +340,7 @@ class VectaraToolFactory:
|
|
|
336
340
|
include_citations: bool = True,
|
|
337
341
|
save_history: bool = False,
|
|
338
342
|
fcs_threshold: float = 0.0,
|
|
343
|
+
return_direct: bool = False,
|
|
339
344
|
verbose: bool = False,
|
|
340
345
|
vectara_base_url: str = "https://api.vectara.io",
|
|
341
346
|
vectara_verify_ssl: bool = True,
|
|
@@ -388,6 +393,7 @@ class VectaraToolFactory:
|
|
|
388
393
|
save_history (bool, optional): Whether to save the query in history.
|
|
389
394
|
fcs_threshold (float, optional): A threshold for factual consistency.
|
|
390
395
|
If set above 0, the tool notifies the calling agent that it "cannot respond" if FCS is too low.
|
|
396
|
+
return_direct (bool, optional): Whether the agent should return the tool's response directly.
|
|
391
397
|
verbose (bool, optional): Whether to print verbose output.
|
|
392
398
|
vectara_base_url (str, optional): The base URL for the Vectara API.
|
|
393
399
|
vectara_verify_ssl (bool, optional): Whether to verify SSL certificates for the Vectara API.
|
|
@@ -417,7 +423,7 @@ class VectaraToolFactory:
|
|
|
417
423
|
|
|
418
424
|
query = kwargs.pop("query")
|
|
419
425
|
try:
|
|
420
|
-
filter_string =
|
|
426
|
+
filter_string = build_filter_string(
|
|
421
427
|
kwargs, tool_args_type, fixed_filter
|
|
422
428
|
)
|
|
423
429
|
except ValueError as e:
|
|
@@ -468,7 +474,10 @@ class VectaraToolFactory:
|
|
|
468
474
|
response = vectara_query_engine.query(query)
|
|
469
475
|
|
|
470
476
|
if len(response.source_nodes) == 0:
|
|
471
|
-
msg =
|
|
477
|
+
msg = (
|
|
478
|
+
"Tool failed to generate a response since no matches were found. "
|
|
479
|
+
"Please check the arguments and try again."
|
|
480
|
+
)
|
|
472
481
|
return ToolOutput(
|
|
473
482
|
tool_name=rag_function.__name__,
|
|
474
483
|
content=msg,
|
|
@@ -545,13 +554,14 @@ class VectaraToolFactory:
|
|
|
545
554
|
description="The search query to perform, in the form of a question",
|
|
546
555
|
)
|
|
547
556
|
|
|
548
|
-
tool =
|
|
557
|
+
tool = create_tool_from_dynamic_function(
|
|
549
558
|
rag_function,
|
|
550
559
|
tool_name,
|
|
551
560
|
tool_description,
|
|
552
561
|
RagToolBaseParams,
|
|
553
562
|
tool_args_schema,
|
|
554
563
|
compact_docstring=self.compact_docstring,
|
|
564
|
+
return_direct=return_direct,
|
|
555
565
|
)
|
|
556
566
|
return tool
|
|
557
567
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vectara_agentic-0.2.14 → vectara_agentic-0.2.15}/vectara_agentic.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|