hyperforge-google 1.0.0.post29__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.
- hyperforge_google-1.0.0.post29/PKG-INFO +20 -0
- hyperforge_google-1.0.0.post29/README.md +1 -0
- hyperforge_google-1.0.0.post29/pyproject.toml +37 -0
- hyperforge_google-1.0.0.post29/setup.cfg +4 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google/__init__.py +4 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google/agent.py +199 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google/config.py +38 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google/driver.py +36 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google/py.typed +0 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google.egg-info/PKG-INFO +20 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google.egg-info/SOURCES.txt +13 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google.egg-info/dependency_links.txt +1 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google.egg-info/requires.txt +2 -0
- hyperforge_google-1.0.0.post29/src/hyperforge_google.egg-info/top_level.txt +1 -0
- hyperforge_google-1.0.0.post29/tests/test_google.py +91 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_google
|
|
3
|
+
Version: 1.0.0.post29
|
|
4
|
+
Summary: Google Search Hyperforge agent
|
|
5
|
+
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://progress.com
|
|
8
|
+
Project-URL: Repository, https://github.com/nuclia/hyperforge
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: <4,>=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: hyperforge
|
|
18
|
+
Requires-Dist: google-genai
|
|
19
|
+
|
|
20
|
+
# Google Hyperforge agents
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Google Hyperforge agents
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hyperforge_google"
|
|
7
|
+
version = "1.0.0.post29"
|
|
8
|
+
license = "Apache-2.0"
|
|
9
|
+
description = "Google Search Hyperforge agent"
|
|
10
|
+
authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python",
|
|
14
|
+
"Programming Language :: Python :: 3.10",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
19
|
+
]
|
|
20
|
+
requires-python = ">=3.10, <4"
|
|
21
|
+
dependencies = ["hyperforge", "google-genai"]
|
|
22
|
+
|
|
23
|
+
[dependency-groups]
|
|
24
|
+
dev = [
|
|
25
|
+
"mypy",
|
|
26
|
+
"pytest",
|
|
27
|
+
"pytest-asyncio",
|
|
28
|
+
"pytest-recording",
|
|
29
|
+
"ty",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://progress.com"
|
|
34
|
+
Repository = "https://github.com/nuclia/hyperforge"
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# GOOD REFERENCE: https://github.com/philschmid/gemini-samples/blob/main/examples/gemini-google-search.ipynb
|
|
2
|
+
|
|
3
|
+
from time import time
|
|
4
|
+
from typing import Any, ClassVar, Dict, List, Optional, Tuple, cast
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
from google.genai.types import (
|
|
8
|
+
GenerateContentConfig,
|
|
9
|
+
GoogleSearch,
|
|
10
|
+
ThinkingConfig,
|
|
11
|
+
Tool,
|
|
12
|
+
)
|
|
13
|
+
from hyperforge.agent import Agent
|
|
14
|
+
from hyperforge.configure import agent
|
|
15
|
+
from hyperforge.context.agent import ContextAgent
|
|
16
|
+
from hyperforge.definition import FunctionDefinition
|
|
17
|
+
from hyperforge.manager import Manager
|
|
18
|
+
from hyperforge.memory.memory import Chunk, Context, QuestionMemory
|
|
19
|
+
from hyperforge.utils.http import safe_http_client
|
|
20
|
+
|
|
21
|
+
from hyperforge_google.config import GoogleAgentConfig
|
|
22
|
+
from hyperforge_google.driver import GoogleDriver
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@agent(
|
|
26
|
+
id="google",
|
|
27
|
+
agent_type="context",
|
|
28
|
+
title="Google Search",
|
|
29
|
+
description="Use Google Search to get information from the internet to answer questions.",
|
|
30
|
+
config_schema=GoogleAgentConfig,
|
|
31
|
+
)
|
|
32
|
+
class GoogleAgent(ContextAgent, Agent[GoogleAgentConfig]):
|
|
33
|
+
__published_functions__: ClassVar[Dict[str, FunctionDefinition]] = {
|
|
34
|
+
"internet_search": FunctionDefinition(
|
|
35
|
+
name="internet_search",
|
|
36
|
+
description="Performs an internet search using Google Search to get context to answer questions.",
|
|
37
|
+
parameters={
|
|
38
|
+
"question": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "The question to search for on the internet.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
google_search_tool: Optional[Tool] = None
|
|
46
|
+
|
|
47
|
+
async def inner_from_config(
|
|
48
|
+
self, config: GoogleAgentConfig, agent_id: Optional[str] = None
|
|
49
|
+
):
|
|
50
|
+
await self.context_from_config(config)
|
|
51
|
+
self.google_search_tool = Tool(google_search=GoogleSearch())
|
|
52
|
+
|
|
53
|
+
def driver(self, manager: Manager) -> GoogleDriver:
|
|
54
|
+
return cast(GoogleDriver, manager.drivers[self.config.source])
|
|
55
|
+
|
|
56
|
+
async def internet_search(
|
|
57
|
+
self,
|
|
58
|
+
question: str,
|
|
59
|
+
memory: QuestionMemory,
|
|
60
|
+
manager: Manager,
|
|
61
|
+
question_uuid: Optional[str] = None,
|
|
62
|
+
flow_id: Optional[str] = None,
|
|
63
|
+
) -> Context:
|
|
64
|
+
if question_uuid is None:
|
|
65
|
+
question_uuid = uuid4().hex
|
|
66
|
+
|
|
67
|
+
driver = self.driver(manager)
|
|
68
|
+
t0 = time()
|
|
69
|
+
assert self.google_search_tool is not None, "google_search_tool not initialized"
|
|
70
|
+
response = await driver.client.aio.models.generate_content(
|
|
71
|
+
model=self.config.gen_model_id,
|
|
72
|
+
contents=question,
|
|
73
|
+
config=GenerateContentConfig(
|
|
74
|
+
tools=[self.google_search_tool],
|
|
75
|
+
response_modalities=["TEXT"],
|
|
76
|
+
thinking_config=ThinkingConfig(include_thoughts=True),
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
if (
|
|
80
|
+
response is not None
|
|
81
|
+
and response.usage_metadata is not None
|
|
82
|
+
and response.usage_metadata.total_token_count is not None
|
|
83
|
+
and response.usage_metadata.prompt_token_count is not None
|
|
84
|
+
):
|
|
85
|
+
tokens = response.usage_metadata.total_token_count * 0.05
|
|
86
|
+
input_tokens = response.usage_metadata.prompt_token_count * 0.05
|
|
87
|
+
output_tokens = tokens - input_tokens
|
|
88
|
+
else:
|
|
89
|
+
input_tokens = 0.5
|
|
90
|
+
output_tokens = 0.5
|
|
91
|
+
context = Context(
|
|
92
|
+
agent_id=self.config.id or self.agent_id,
|
|
93
|
+
original_question_uuid=memory.original_question_uuid,
|
|
94
|
+
actual_question_uuid=question_uuid,
|
|
95
|
+
question=question,
|
|
96
|
+
source="google",
|
|
97
|
+
agent="google",
|
|
98
|
+
title=self.config.title
|
|
99
|
+
if self.config.title
|
|
100
|
+
else "Internet search with Google",
|
|
101
|
+
)
|
|
102
|
+
http_client = safe_http_client()
|
|
103
|
+
chunks: Dict[int, str] = {}
|
|
104
|
+
answer = ""
|
|
105
|
+
reasoning = ""
|
|
106
|
+
count = 0
|
|
107
|
+
if (
|
|
108
|
+
response
|
|
109
|
+
and response.candidates
|
|
110
|
+
and len(response.candidates) > 0
|
|
111
|
+
and response.candidates[0].content
|
|
112
|
+
and response.candidates[0].content.parts
|
|
113
|
+
):
|
|
114
|
+
candidate = response.candidates[0]
|
|
115
|
+
for each in response.candidates[0].content.parts:
|
|
116
|
+
if each.thought is True and each.text is not None:
|
|
117
|
+
reasoning += each.text
|
|
118
|
+
elif each.text is not None:
|
|
119
|
+
answer += each.text
|
|
120
|
+
if (
|
|
121
|
+
candidate.grounding_metadata
|
|
122
|
+
and candidate.grounding_metadata.grounding_chunks
|
|
123
|
+
):
|
|
124
|
+
for chunk_id, chunk in enumerate(
|
|
125
|
+
candidate.grounding_metadata.grounding_chunks
|
|
126
|
+
):
|
|
127
|
+
if chunk.web is not None and chunk.web.uri is not None:
|
|
128
|
+
resp = await http_client.get(chunk.web.uri)
|
|
129
|
+
chunks[chunk_id] = resp.headers.get("location", "")
|
|
130
|
+
|
|
131
|
+
if (
|
|
132
|
+
candidate.grounding_metadata
|
|
133
|
+
and candidate.grounding_metadata.grounding_supports
|
|
134
|
+
):
|
|
135
|
+
for ground in candidate.grounding_metadata.grounding_supports:
|
|
136
|
+
if ground.grounding_chunk_indices:
|
|
137
|
+
url = [
|
|
138
|
+
chunks[indice] for indice in ground.grounding_chunk_indices
|
|
139
|
+
]
|
|
140
|
+
else:
|
|
141
|
+
url = []
|
|
142
|
+
if ground.segment and ground.segment.text:
|
|
143
|
+
text = ground.segment.text
|
|
144
|
+
else:
|
|
145
|
+
text = ""
|
|
146
|
+
count += 1
|
|
147
|
+
context.chunks.append(
|
|
148
|
+
Chunk(
|
|
149
|
+
chunk_id=uuid4().hex,
|
|
150
|
+
text=text,
|
|
151
|
+
labels=[],
|
|
152
|
+
url=url,
|
|
153
|
+
origin_agent=self.config.module,
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
# if candidate.grounding_metadata.web_search_queries:
|
|
157
|
+
# for query in candidate.grounding_metadata.web_search_queries:
|
|
158
|
+
# # Queries
|
|
159
|
+
await memory.add_answer(
|
|
160
|
+
answer,
|
|
161
|
+
module=self.config.module,
|
|
162
|
+
agent_path=f"/context/{self.config.id if self.config.id else 'default'}",
|
|
163
|
+
)
|
|
164
|
+
context.summary = answer
|
|
165
|
+
await memory.add_step(
|
|
166
|
+
step_module=self.config.module,
|
|
167
|
+
step_title=self.step_title("Search results"),
|
|
168
|
+
step_agent_path=f"/context/{self.config.id if self.config.id else 'default'}",
|
|
169
|
+
step_reason=reasoning,
|
|
170
|
+
step_value=f"{count} results found",
|
|
171
|
+
timeit=time() - t0,
|
|
172
|
+
input_nuclia_tokens=input_tokens,
|
|
173
|
+
output_nuclia_tokens=output_tokens,
|
|
174
|
+
)
|
|
175
|
+
return context
|
|
176
|
+
|
|
177
|
+
async def _get_question_context(
|
|
178
|
+
self,
|
|
179
|
+
memory: QuestionMemory,
|
|
180
|
+
manager: Manager,
|
|
181
|
+
question_uuid: str,
|
|
182
|
+
question: str,
|
|
183
|
+
flow_id: str,
|
|
184
|
+
extra_context: Optional[Dict[str, Any]] = None,
|
|
185
|
+
) -> List[Tuple[str, str]]:
|
|
186
|
+
context = await self.internet_search(
|
|
187
|
+
question=question,
|
|
188
|
+
memory=memory,
|
|
189
|
+
manager=manager,
|
|
190
|
+
question_uuid=question_uuid,
|
|
191
|
+
)
|
|
192
|
+
missing = await self.save_ctx_and_return_missing(
|
|
193
|
+
context=context,
|
|
194
|
+
question=question,
|
|
195
|
+
memory=memory,
|
|
196
|
+
manager=manager,
|
|
197
|
+
flow_id=flow_id,
|
|
198
|
+
)
|
|
199
|
+
return [missing] if missing is not None else []
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from typing import ClassVar, Literal, Optional, Tuple
|
|
2
|
+
|
|
3
|
+
from hyperforge.context.config import ContextAgentConfig
|
|
4
|
+
from hyperforge.driver import DriverConfig, EncryptedPayload
|
|
5
|
+
from hyperforge.utils import WidgetType
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
from pydantic.config import ConfigDict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class GoogleInnerConfig(EncryptedPayload):
|
|
11
|
+
encrypted_fields: ClassVar[list[str]] = ["api_key", "credentials"]
|
|
12
|
+
|
|
13
|
+
api_key: Optional[str] = None
|
|
14
|
+
credentials: Optional[str] = None
|
|
15
|
+
vertexai: bool = False
|
|
16
|
+
project: Optional[str] = None
|
|
17
|
+
location: Optional[str] = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GoogleDriverConfig(DriverConfig[GoogleInnerConfig]):
|
|
21
|
+
model_config = ConfigDict(title="Google Gemini")
|
|
22
|
+
provider: Literal["google"] = "google"
|
|
23
|
+
config: GoogleInnerConfig
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GoogleAgentConfig(ContextAgentConfig):
|
|
27
|
+
model_config = ConfigDict(title="Google Gemini")
|
|
28
|
+
module: Literal["google"] = "google"
|
|
29
|
+
gen_model_id: str = "gemini-2.5-flash"
|
|
30
|
+
source: str = "google"
|
|
31
|
+
published_functions: Optional[Tuple[str, ...]] = Field(
|
|
32
|
+
default=("internet_search",),
|
|
33
|
+
title="Published functions",
|
|
34
|
+
description="List of functions published by this agent to be used by other agents in the chain",
|
|
35
|
+
json_schema_extra={
|
|
36
|
+
"widget": WidgetType.NOT_SHOWN,
|
|
37
|
+
},
|
|
38
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from google.genai import Client
|
|
2
|
+
from hyperforge.configure import driver
|
|
3
|
+
from hyperforge.driver import Driver
|
|
4
|
+
from typing_extensions import Self
|
|
5
|
+
|
|
6
|
+
from hyperforge_google.config import GoogleDriverConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@driver(
|
|
10
|
+
id="google",
|
|
11
|
+
title="Google Driver",
|
|
12
|
+
description="Driver for interacting with the Google API.",
|
|
13
|
+
config_schema=GoogleDriverConfig,
|
|
14
|
+
)
|
|
15
|
+
class GoogleDriver(Driver):
|
|
16
|
+
client: Client
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
async def init(cls, driver: GoogleDriverConfig) -> Self:
|
|
20
|
+
creds = None
|
|
21
|
+
if driver.config.vertexai:
|
|
22
|
+
from google.auth import load_credentials_from_file
|
|
23
|
+
|
|
24
|
+
creds, _ = load_credentials_from_file(driver.config.credentials)
|
|
25
|
+
client = Client(
|
|
26
|
+
vertexai=driver.config.vertexai,
|
|
27
|
+
credentials=creds,
|
|
28
|
+
api_key=driver.config.api_key,
|
|
29
|
+
project=driver.config.project,
|
|
30
|
+
location=driver.config.location,
|
|
31
|
+
)
|
|
32
|
+
return cls(
|
|
33
|
+
client=client,
|
|
34
|
+
name=driver.name,
|
|
35
|
+
provider=driver.provider,
|
|
36
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_google
|
|
3
|
+
Version: 1.0.0.post29
|
|
4
|
+
Summary: Google Search Hyperforge agent
|
|
5
|
+
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://progress.com
|
|
8
|
+
Project-URL: Repository, https://github.com/nuclia/hyperforge
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: <4,>=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: hyperforge
|
|
18
|
+
Requires-Dist: google-genai
|
|
19
|
+
|
|
20
|
+
# Google Hyperforge agents
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/hyperforge_google/__init__.py
|
|
4
|
+
src/hyperforge_google/agent.py
|
|
5
|
+
src/hyperforge_google/config.py
|
|
6
|
+
src/hyperforge_google/driver.py
|
|
7
|
+
src/hyperforge_google/py.typed
|
|
8
|
+
src/hyperforge_google.egg-info/PKG-INFO
|
|
9
|
+
src/hyperforge_google.egg-info/SOURCES.txt
|
|
10
|
+
src/hyperforge_google.egg-info/dependency_links.txt
|
|
11
|
+
src/hyperforge_google.egg-info/requires.txt
|
|
12
|
+
src/hyperforge_google.egg-info/top_level.txt
|
|
13
|
+
tests/test_google.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge_google
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from hyperforge.configure import get_driver_config_instance, load_all_configurations
|
|
6
|
+
from hyperforge.manager import Manager
|
|
7
|
+
from hyperforge.memory import Context
|
|
8
|
+
from hyperforge.memory.memory import EphemeralSessionMemory
|
|
9
|
+
from hyperforge.minimal_fixtures import cassette_nua_key
|
|
10
|
+
from hyperforge.models import MemoryConfig, Rules
|
|
11
|
+
from hyperforge_google.agent import GoogleAgent
|
|
12
|
+
from hyperforge_google.config import GoogleAgentConfig
|
|
13
|
+
from nuclia.lib.nua import AsyncNuaClient
|
|
14
|
+
|
|
15
|
+
NUA_KEY = os.environ.get(
|
|
16
|
+
"NUA_KEY",
|
|
17
|
+
) or cassette_nua_key("https://europe-1.nuclia.cloud/")
|
|
18
|
+
|
|
19
|
+
pytestmark = [
|
|
20
|
+
pytest.mark.vcr(
|
|
21
|
+
ignore_localhost=True,
|
|
22
|
+
match_on=["scheme", "host", "port", "path"],
|
|
23
|
+
),
|
|
24
|
+
pytest.mark.asyncio,
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DRIVERS = [
|
|
29
|
+
{
|
|
30
|
+
"provider": "google",
|
|
31
|
+
"identifier": "google-01",
|
|
32
|
+
"name": "google",
|
|
33
|
+
"config": {
|
|
34
|
+
"vertexai": False,
|
|
35
|
+
"api_key": os.environ.get("GOOGLE_API_KEY", "DUMMY_API_KEY"),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def _run_question(
|
|
42
|
+
drivers: list[dict],
|
|
43
|
+
question: str,
|
|
44
|
+
) -> list[Context]:
|
|
45
|
+
"""Build a manager from driver configs, run the agent, return contexts."""
|
|
46
|
+
load_all_configurations("hyperforge_google")
|
|
47
|
+
# Google agent doesn't use nua — construct client directly with test values
|
|
48
|
+
nua = AsyncNuaClient(region="europe-1", account="test", token=NUA_KEY)
|
|
49
|
+
manager = await Manager.from_config(
|
|
50
|
+
drivers=[get_driver_config_instance(d) for d in drivers],
|
|
51
|
+
nua=nua,
|
|
52
|
+
)
|
|
53
|
+
config = GoogleAgentConfig.model_validate(
|
|
54
|
+
{
|
|
55
|
+
"module": "google",
|
|
56
|
+
"title": "Google Agent",
|
|
57
|
+
"source": "google-01",
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
agent = GoogleAgent(config=config)
|
|
61
|
+
await agent.inner_from_config(config)
|
|
62
|
+
|
|
63
|
+
session = EphemeralSessionMemory.from_config(
|
|
64
|
+
config=MemoryConfig(),
|
|
65
|
+
agent_id="test",
|
|
66
|
+
workflow_id="test",
|
|
67
|
+
rules=Rules(),
|
|
68
|
+
)
|
|
69
|
+
session.init("test-session")
|
|
70
|
+
memory = session.start_question(question)
|
|
71
|
+
|
|
72
|
+
flow_id = uuid4().hex
|
|
73
|
+
await agent.get_question_context(
|
|
74
|
+
memory=memory,
|
|
75
|
+
manager=manager,
|
|
76
|
+
question_uuid=memory.original_question_uuid,
|
|
77
|
+
question=question,
|
|
78
|
+
flow_id=flow_id,
|
|
79
|
+
)
|
|
80
|
+
return memory.get_agent_contexts(flow_id=flow_id, agent_id=agent.agent_id)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
async def test_google():
|
|
84
|
+
contexts = await _run_question(
|
|
85
|
+
DRIVERS,
|
|
86
|
+
"What is Nuclia?",
|
|
87
|
+
)
|
|
88
|
+
assert len(contexts) > 0
|
|
89
|
+
all_text = " ".join(chunk.text for ctx in contexts for chunk in ctx.chunks).lower()
|
|
90
|
+
summary = " ".join(ctx.summary for ctx in contexts if ctx.summary).lower()
|
|
91
|
+
assert "rag" in all_text or "ai" in all_text or "rag" in summary or "ai" in summary
|