mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-11-05 19:04:13 +00:00
186 lines
6.0 KiB
Python
186 lines
6.0 KiB
Python
from types import SimpleNamespace
|
|
from contextlib import contextmanager
|
|
|
|
import pytest
|
|
|
|
from agent_framework.rag.rag_service import RagService
|
|
|
|
|
|
def _settings(**overrides):
|
|
data = dict(
|
|
RAG_PROVIDER="kbdb", RAG_TOP_K=5,
|
|
KBDB_DB_USER="kb_user", KBDB_DB_PASSWORD="kb_pwd", KBDB_DB_DSN="kb_tp",
|
|
KBDB_DB_WALLET_LOCATION=None, KBDB_DB_WALLET_PASSWORD=None,
|
|
ADB_USER=None, ADB_PASSWORD=None, ADB_DSN=None,
|
|
ADB_WALLET_LOCATION=None, ADB_WALLET_PASSWORD=None,
|
|
KBDB_SEARCH_TYPE="hybrid", KBDB_NODE_EXPANSION=True,
|
|
KBDB_NODE_MAX_RELATED=8, KBDB_GRAPH_CROSS_REF=False,
|
|
KBDB_MAX_CROSS_REF_HOPS=1, KBDB_DOCUMENT_TYPE="customer_safe",
|
|
KBDB_METADATA_JSON=None, KBDB_MIN_SCORE=None,
|
|
KBDB_IDENTIFY_DOCUMENT=True, KBDB_STORE_QUERY=True, KBDB_IDENTIFY_TOP_N=3,
|
|
)
|
|
data.update(overrides)
|
|
return SimpleNamespace(**data)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_kbdb_provider_adapts_serving_envelope(monkeypatch):
|
|
service = RagService(_settings())
|
|
|
|
def fake_search(query, k):
|
|
return {
|
|
"search_type": "hybrid", "confidence": "high", "low_confidence": False,
|
|
"top_score": 78.4, "warnings": [],
|
|
"seeds": [{"unit_id": 11, "rank": 1, "score": 78.4}],
|
|
"units": [
|
|
{"unit_id": 10, "content": "passo anterior", "provenance": "parent"},
|
|
{"unit_id": 11, "content": "resposta principal", "provenance": "seed"},
|
|
],
|
|
"documents": [{"document_id": 7, "title": "Politica"}],
|
|
}
|
|
|
|
monkeypatch.setattr(service._kbdb, "_search_sync", fake_search)
|
|
result = await service.retrieve("qual a regra?", namespace="billing_agent")
|
|
|
|
assert [d.id for d in result.documents] == ["10", "11"]
|
|
assert result.documents[1].score == 78.4
|
|
assert result.metadata["provider"] == "kbdb"
|
|
assert result.metadata["confidence"] == "high"
|
|
assert "resposta principal" in result.as_prompt_context()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_kbdb_provider_is_serving_only():
|
|
service = RagService(_settings())
|
|
with pytest.raises(RuntimeError, match="serving-only"):
|
|
await service.add_documents(["texto"])
|
|
|
|
|
|
def test_kbdb_connection_uses_same_wallet_semantics_without_adb_fallback(monkeypatch):
|
|
import sys
|
|
from agent_framework.rag.kbdb_service import KbdbRagService
|
|
|
|
captured = {}
|
|
|
|
class Defaults:
|
|
fetch_lobs = True
|
|
|
|
class Connection:
|
|
def close(self):
|
|
captured["closed"] = True
|
|
|
|
class FakeOracleDb:
|
|
defaults = Defaults()
|
|
|
|
@staticmethod
|
|
def connect(**kwargs):
|
|
captured.update(kwargs)
|
|
return Connection()
|
|
|
|
monkeypatch.setitem(sys.modules, "oracledb", FakeOracleDb)
|
|
settings = _settings(
|
|
KBDB_DB_USER="kb_user",
|
|
KBDB_DB_PASSWORD="kb_pwd",
|
|
KBDB_DB_DSN="kb_tp",
|
|
KBDB_DB_WALLET_LOCATION="/wallet/kb",
|
|
KBDB_DB_WALLET_PASSWORD="wallet_pwd",
|
|
ADB_USER="framework_user",
|
|
ADB_PASSWORD="framework_pwd",
|
|
ADB_DSN="framework_high",
|
|
ADB_WALLET_LOCATION="/wallet/framework",
|
|
ADB_WALLET_PASSWORD="framework_wallet_pwd",
|
|
)
|
|
|
|
service = KbdbRagService(settings)
|
|
with service._connect():
|
|
pass
|
|
|
|
assert captured["user"] == "kb_user"
|
|
assert captured["password"] == "kb_pwd"
|
|
assert captured["dsn"] == "kb_tp"
|
|
assert captured["config_dir"] == "/wallet/kb"
|
|
assert captured["wallet_location"] == "/wallet/kb"
|
|
assert captured["wallet_password"] == "wallet_pwd"
|
|
assert captured["closed"] is True
|
|
|
|
|
|
def test_kbdb_does_not_fallback_to_framework_adb_credentials():
|
|
from agent_framework.rag.kbdb_service import KbdbRagService
|
|
|
|
settings = _settings(
|
|
KBDB_DB_USER=None,
|
|
KBDB_DB_PASSWORD=None,
|
|
KBDB_DB_DSN=None,
|
|
ADB_USER="framework_user",
|
|
ADB_PASSWORD="framework_pwd",
|
|
ADB_DSN="framework_high",
|
|
)
|
|
with pytest.raises(RuntimeError, match="KBDB_DB_USER"):
|
|
KbdbRagService(settings)
|
|
|
|
|
|
def test_kbdb_discovers_number_flags_and_clob_output(monkeypatch):
|
|
import sys
|
|
from agent_framework.rag.kbdb_service import KbdbRagService
|
|
|
|
captured = {}
|
|
|
|
class Var:
|
|
def __init__(self, value=None):
|
|
self.value = value
|
|
|
|
def getvalue(self):
|
|
return self.value
|
|
|
|
class Cursor:
|
|
def execute(self, statement):
|
|
captured["signature_query"] = statement
|
|
|
|
def fetchall(self):
|
|
names = [
|
|
("P_SEARCH_TYPE", "VARCHAR2"), ("P_QUERY", "VARCHAR2"),
|
|
("P_TOP_K", "NUMBER"), ("P_NODE_EXPANSION", "NUMBER"),
|
|
("P_NODE_MAX_RELATED", "NUMBER"), ("P_DOCUMENT_TYPE", "VARCHAR2"),
|
|
("P_METADATA", "CLOB"), ("P_IDENTIFY_DOCUMENT", "NUMBER"),
|
|
("P_STORE_QUERY", "NUMBER"), ("P_IDENTIFY_TOP_N", "NUMBER"),
|
|
("P_RESULT", "CLOB"),
|
|
]
|
|
return [
|
|
(name, index, "OUT" if index == 11 else "IN", data_type, None)
|
|
for index, (name, data_type) in enumerate(names, start=1)
|
|
]
|
|
|
|
def var(self, data_type, size=None):
|
|
captured["out_type"] = data_type
|
|
return Var('{"units": [], "seeds": []}')
|
|
|
|
def callproc(self, name, binds):
|
|
captured["procedure"] = name
|
|
captured["binds"] = binds
|
|
|
|
class Connection:
|
|
def cursor(self):
|
|
return Cursor()
|
|
|
|
class FakeOracleDb:
|
|
DB_TYPE_JSON = "JSON"
|
|
DB_TYPE_CLOB = "CLOB"
|
|
DB_TYPE_VARCHAR = "VARCHAR"
|
|
|
|
service = KbdbRagService(_settings())
|
|
|
|
@contextmanager
|
|
def connect():
|
|
yield Connection()
|
|
|
|
monkeypatch.setitem(sys.modules, "oracledb", FakeOracleDb)
|
|
monkeypatch.setattr(service, "_connect", connect)
|
|
|
|
result = service._search_sync("como funciona?", 5)
|
|
|
|
assert result == {"units": [], "seeds": []}
|
|
assert captured["procedure"] == "PKG_KB_SERVING.search_knowledge_base"
|
|
assert captured["binds"][3] == 1
|
|
assert captured["binds"][7:10] == [1, 1, 3]
|
|
assert captured["out_type"] == "CLOB"
|