First commit
This commit is contained in:
47
scripts/generate_rag_embeddings.py
Normal file
47
scripts/generate_rag_embeddings.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FRAMEWORK_SRC = ROOT / "agent_framework" / "src"
|
||||
if str(FRAMEWORK_SRC) not in sys.path:
|
||||
sys.path.insert(0, str(FRAMEWORK_SRC))
|
||||
|
||||
from agent_framework.config.settings import get_settings
|
||||
from agent_framework.rag.ingest import ingest_documents_sync, parse_csv
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate RAG embeddings and store document chunks in the configured vector store."
|
||||
)
|
||||
parser.add_argument("--docs-dir", default=None, help="Directory containing Markdown/text/YAML/JSON documents.")
|
||||
parser.add_argument("--namespace", default=None, help="RAG namespace used by the agent profile.")
|
||||
parser.add_argument("--globs", default=None, help="Comma-separated file globs. Example: '*.md,*.txt'.")
|
||||
parser.add_argument("--chunk-size", type=int, default=None, help="Maximum chunk size in characters.")
|
||||
parser.add_argument("--chunk-overlap", type=int, default=None, help="Chunk overlap in characters.")
|
||||
args = parser.parse_args()
|
||||
|
||||
settings = get_settings()
|
||||
result = ingest_documents_sync(
|
||||
settings,
|
||||
docs_dir=args.docs_dir,
|
||||
namespace=args.namespace,
|
||||
file_globs=parse_csv(args.globs, []) or None,
|
||||
chunk_size=args.chunk_size,
|
||||
chunk_overlap=args.chunk_overlap,
|
||||
)
|
||||
|
||||
print("RAG embedding generation completed")
|
||||
print(f" namespace: {result.namespace}")
|
||||
print(f" files read: {result.files_read}")
|
||||
print(f" chunks created: {result.chunks_created}")
|
||||
print(f" documents saved:{result.documents_saved}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
4
scripts/run_ai_gateway.sh
Normal file
4
scripts/run_ai_gateway.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../apps/ai_gateway"
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 9100 --reload
|
||||
8
scripts/run_backend.sh
Normal file
8
scripts/run_backend.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../agent_template_backend"
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -e ../agent_framework --no-build-isolation || pip install -e ../agent_framework
|
||||
pip install -r requirements.txt
|
||||
uvicorn app.main:app --reload --reload-dir app --reload-dir config --port 8000
|
||||
4
scripts/run_frontend.sh
Normal file
4
scripts/run_frontend.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../agent_frontend"
|
||||
python -m http.server 5173
|
||||
4
scripts/run_mcp_gateway.sh
Normal file
4
scripts/run_mcp_gateway.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../apps/mcp_gateway"
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8300 --reload
|
||||
18
scripts/run_mcp_servers.sh
Normal file
18
scripts/run_mcp_servers.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
python -m venv "$ROOT/.venv"
|
||||
source "$ROOT/.venv/bin/activate"
|
||||
pip install -r "$ROOT/mcp/servers/telecom_mcp_server/requirements.txt"
|
||||
pip install -r "$ROOT/mcp/servers/retail_mcp_server/requirements.txt"
|
||||
|
||||
uvicorn --app-dir "$ROOT/mcp/servers/telecom_mcp_server" main:app --host 0.0.0.0 --port 8100 &
|
||||
PID1=$!
|
||||
uvicorn --app-dir "$ROOT/mcp/servers/retail_mcp_server" main:app --host 0.0.0.0 --port 8200 &
|
||||
PID2=$!
|
||||
|
||||
echo "Telecom MCP em http://localhost:8100"
|
||||
echo "Retail MCP em http://localhost:8200"
|
||||
trap 'kill $PID1 $PID2' INT TERM EXIT
|
||||
wait
|
||||
7
scripts/smoke_usage_test.sh
Normal file
7
scripts/smoke_usage_test.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
BASE_URL="${BASE_URL:-http://localhost:8000}"
|
||||
curl -s -X POST "$BASE_URL/gateway/message" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"channel":"web","payload":{"text":"teste smoke","user_id":"smoke-user","session_id":"smoke-session","message_id":"smoke-1"}}' | python -m json.tool
|
||||
curl -s "$BASE_URL/debug/usage" | python -m json.tool
|
||||
252
scripts/sync_pending_topics_to_tuning.py
Normal file
252
scripts/sync_pending_topics_to_tuning.py
Normal file
@@ -0,0 +1,252 @@
|
||||
"""Propaga o contrato nativo de pending_topics às cópias de Tuning-Performance."""
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def replace_once(text: str, old: str, new: str, path: Path) -> str:
|
||||
if old not in text:
|
||||
raise RuntimeError(f"Marcador não encontrado em {path}: {old[:60]!r}")
|
||||
return text.replace(old, new, 1)
|
||||
|
||||
|
||||
def update_state(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if " pending_topics: list[dict[str, Any]]" not in text:
|
||||
text = replace_once(
|
||||
text,
|
||||
" supervisor_results: list[dict[str, Any]]\n",
|
||||
" supervisor_results: list[dict[str, Any]]\n"
|
||||
" pending_topics: list[dict[str, Any]]\n"
|
||||
" handled_topics: list[dict[str, Any]]\n",
|
||||
path,
|
||||
)
|
||||
if " operation_results: dict[str, dict[str, Any]]" not in text:
|
||||
marker = " handled_topics: list[dict[str, Any]]\n"
|
||||
if marker in text:
|
||||
text = text.replace(marker, marker + " operation_results: dict[str, dict[str, Any]]\n", 1)
|
||||
|
||||
if " rag_results: list[dict[str, Any]]" not in text:
|
||||
text = replace_once(
|
||||
text,
|
||||
" mcp_results: list[dict[str, Any]]\n",
|
||||
" mcp_results: list[dict[str, Any]]\n"
|
||||
" rag_results: list[dict[str, Any]]\n",
|
||||
path,
|
||||
)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def update_graph(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if "from agent_framework.routing.pending_topics import drain_pending_topics" in text:
|
||||
return
|
||||
text = replace_once(
|
||||
text,
|
||||
"from agent_framework.routing.enterprise_router import EnterpriseRouter\n",
|
||||
"from agent_framework.routing.enterprise_router import EnterpriseRouter\n"
|
||||
"from agent_framework.routing.pending_topics import drain_pending_topics\n",
|
||||
path,
|
||||
)
|
||||
text = replace_once(
|
||||
text,
|
||||
" } if decision.method == \"continuity\" else {},\n }\n\n async def billing_agent",
|
||||
" } if decision.method == \"continuity\" else {},\n"
|
||||
" \"pending_topics\": (\n"
|
||||
" (decision.metadata or {}).get(\"multi_intent_plan\", {}).get(\"operations\", [])[1:]\n"
|
||||
" if (decision.metadata or {}).get(\"multi_intent_plan\") else []\n"
|
||||
" ),\n"
|
||||
" }\n\n async def billing_agent",
|
||||
path,
|
||||
)
|
||||
marker = " async def output_supervisor(self, state):"
|
||||
before, output = text.split(marker, 1)
|
||||
old = """ if not bool(getattr(self.settings, \"ENABLE_OUTPUT_SUPERVISOR\", True)):
|
||||
return {
|
||||
\"output_guardrails_already_applied\": False,
|
||||
\"supervisor_action\": \"disabled\",
|
||||
\"supervisor_attempt\": int(state.get(\"supervisor_attempt\", 0)),
|
||||
}
|
||||
|
||||
candidate = state.get(\"answer\") or \"\"
|
||||
"""
|
||||
new = """ drained = await drain_pending_topics(
|
||||
state,
|
||||
str(state.get(\"answer\") or \"\"),
|
||||
{
|
||||
\"billing_agent\": self.billing.run,
|
||||
\"product_agent\": self.product.run,
|
||||
\"orders_agent\": self.orders.run,
|
||||
\"support_agent\": self.support.run,
|
||||
},
|
||||
)
|
||||
candidate = drained.answer
|
||||
if not bool(getattr(self.settings, \"ENABLE_OUTPUT_SUPERVISOR\", True)):
|
||||
return {
|
||||
\"answer\": candidate,
|
||||
\"final_answer\": candidate,
|
||||
\"pending_topics\": drained.pending_topics,
|
||||
\"handled_topics\": drained.handled_topics,
|
||||
\"output_guardrails_already_applied\": False,
|
||||
\"supervisor_action\": \"disabled\",
|
||||
\"supervisor_attempt\": int(state.get(\"supervisor_attempt\", 0)),
|
||||
}
|
||||
|
||||
"""
|
||||
output = replace_once(output, old, new, path)
|
||||
output = replace_once(
|
||||
output,
|
||||
" \"output_guardrails_already_applied\": True,\n",
|
||||
" \"output_guardrails_already_applied\": True,\n"
|
||||
" \"pending_topics\": drained.pending_topics,\n"
|
||||
" \"handled_topics\": drained.handled_topics,\n",
|
||||
path,
|
||||
)
|
||||
path.write_text(before + marker + output, encoding="utf-8")
|
||||
|
||||
|
||||
def update_evidence_propagation(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = ' "handled_topics": drained.handled_topics,\n'
|
||||
replacement = marker + ' "mcp_results": drained.mcp_results,\n'
|
||||
if replacement in text:
|
||||
return
|
||||
if marker not in text:
|
||||
raise RuntimeError(f"Marcador de evidências não encontrado em {path}")
|
||||
path.write_text(text.replace(marker, replacement), encoding="utf-8")
|
||||
|
||||
|
||||
def update_guardrail_evidence_context(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = " context = {\n **(state.get(\"context\") or {}),\n"
|
||||
addition = (
|
||||
marker
|
||||
+ ' "evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),\n'
|
||||
+ ' "tool_result": drained.mcp_results or (state.get("context") or {}).get("tool_result"),\n'
|
||||
+ ' "tool_executed": any(isinstance(item, dict) and item.get("ok") for item in drained.mcp_results),\n'
|
||||
+ ' "mcp_results": drained.mcp_results,\n'
|
||||
)
|
||||
if addition in text:
|
||||
return
|
||||
text = replace_once(text, marker, addition, path)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def update_rag_propagation(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
mcp_line = ' "mcp_results": drained.mcp_results,\n'
|
||||
rag_line = mcp_line + ' "rag_results": drained.rag_results,\n'
|
||||
if rag_line not in text:
|
||||
if mcp_line not in text:
|
||||
raise RuntimeError(f"Marcador MCP não encontrado em {path}")
|
||||
text = text.replace(mcp_line, rag_line)
|
||||
text = text.replace(
|
||||
' "evidence": drained.mcp_results or (state.get("context") or {}).get("evidence"),\n',
|
||||
' "evidence": (list(drained.mcp_results) + list(drained.rag_results)) or (state.get("context") or {}).get("evidence"),\n',
|
||||
)
|
||||
marker = ' current_evidence = list(state.get("mcp_results", []) or [])\n'
|
||||
addition = marker + ' current_evidence.extend(state.get("rag_results", []) or [])\n'
|
||||
if marker in text and addition not in text:
|
||||
text = text.replace(marker, addition, 1)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def update_rag_agents(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = ' "rag": rag_metadata,\n'
|
||||
if marker not in text or ' "rag_results": [{\n' in text:
|
||||
return
|
||||
addition = marker + (
|
||||
' "rag_context": rag_context,\n'
|
||||
' "rag_results": [{\n'
|
||||
' "intent": state.get("intent"),\n'
|
||||
' "agent": self.name,\n'
|
||||
' "source_text": str(state.get("sanitized_input") or state.get("user_text") or ""),\n'
|
||||
' "metadata": rag_metadata,\n'
|
||||
' **({"context": rag_context} if rag_context else {}),\n'
|
||||
' }],\n'
|
||||
)
|
||||
path.write_text(text.replace(marker, addition, 1), encoding="utf-8")
|
||||
|
||||
|
||||
def update_rag_http_response(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = ' "mcp_results": result.get("mcp_results"),\n'
|
||||
addition = marker + ' "rag_results": result.get("rag_results"),\n'
|
||||
if addition not in text:
|
||||
text = replace_once(text, marker, addition, path)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def update_rag_telemetry(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = ' "mcp_results": state.get("mcp_results", []),\n'
|
||||
addition = marker + ' "rag_results": state.get("rag_results", []),\n'
|
||||
if addition not in text:
|
||||
text = replace_once(text, marker, addition, path)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def update_rag_env(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if "KBDB_IDENTIFY_DOCUMENT=" in text:
|
||||
return
|
||||
marker = "RAG_FILE_GLOBS=*.md,*.txt,*.yaml,*.yml,*.json\n"
|
||||
settings_block = """
|
||||
# RAG / KBDB
|
||||
# RAG provider: standard (local) ou kbdb (PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE)
|
||||
RAG_PROVIDER=standard
|
||||
# KBDB usa credenciais próprias; não há fallback para ADB_*.
|
||||
KBDB_DB_USER=
|
||||
KBDB_DB_PASSWORD=
|
||||
KBDB_DB_DSN=
|
||||
KBDB_DB_WALLET_LOCATION=
|
||||
KBDB_DB_WALLET_PASSWORD=
|
||||
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=
|
||||
KBDB_MIN_SCORE=
|
||||
KBDB_IDENTIFY_DOCUMENT=true
|
||||
KBDB_STORE_QUERY=true
|
||||
KBDB_IDENTIFY_TOP_N=3
|
||||
RAG_GROUNDED_ONLY=false
|
||||
KBDB_GROUNDED_ONLY=true
|
||||
"""
|
||||
if marker in text:
|
||||
text = text.replace(marker, marker + "\n" + settings_block, 1)
|
||||
else:
|
||||
text = text.rstrip() + "\n\n" + settings_block
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
tuning = ROOT / "Tuning-Performance"
|
||||
states = sorted(tuning.glob("**/app/state.py"))
|
||||
graphs = sorted(tuning.glob("**/app/workflows/agent_graph.py"))
|
||||
agents = sorted(tuning.glob("**/app/agents/*.py"))
|
||||
mains = sorted(tuning.glob("**/app/main.py"))
|
||||
envs = sorted(tuning.glob("**/.env.example"))
|
||||
for path in states:
|
||||
update_state(path)
|
||||
for path in graphs:
|
||||
update_graph(path)
|
||||
update_evidence_propagation(path)
|
||||
update_guardrail_evidence_context(path)
|
||||
update_rag_propagation(path)
|
||||
update_rag_telemetry(path)
|
||||
for path in agents:
|
||||
update_rag_agents(path)
|
||||
for path in mains:
|
||||
update_rag_http_response(path)
|
||||
for path in envs:
|
||||
update_rag_env(path)
|
||||
print(f"pending_topics/RAG sincronizado: {len(states)} states, {len(graphs)} graphs, {len(agents)} agents, {len(mains)} APIs, {len(envs)} envs")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user