Files
tianxuan/scripts/test_orch.py
T

65 lines
3.4 KiB
Python

"""Test full LLM orchestrator with actual tools"""
import sys, os, json, asyncio
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ['DJANGO_SETTINGS_MODULE'] = 'tianxuan.settings'
import django; django.setup()
from analysis.session_store import SessionStore
from analysis.data_loader import load_csv_directory
from analysis.tool_registry import handle_call
import urllib.request
store = SessionStore()
store.drop_all()
csv = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data', 'complex_test.csv')
lf, schema, rc, fc, mem = load_csv_directory(csv)
store.store_dataset('ds', lf, schema=schema, metadata={'row_count': rc, 'csv_glob': csv})
TOOLS = [{"type": "function", "function": {
"name": "profile_data", "description": "Get column statistics",
"parameters": {"type": "object", "properties": {"dataset_id": {"type": "string"}}, "required": ["dataset_id"]}
}}, {"type": "function", "function": {
"name": "build_entity_profiles", "description": "Auto-detect entity and aggregate",
"parameters": {"type": "object", "properties": {"dataset_id": {"type": "string"}, "auto_detect": {"type": "boolean"}}, "required": ["dataset_id"]}
}}, {"type": "function", "function": {
"name": "run_clustering", "description": "Run HDBSCAN clustering",
"parameters": {"type": "object", "properties": {"dataset_id": {"type": "string"}, "cluster_columns": {"type": "array", "items": {"type": "string"}}, "algorithm": {"type": "string", "enum": ["hdbscan", "kmeans"]}}, "required": ["dataset_id", "cluster_columns"]}
}}, {"type": "function", "function": {
"name": "extract_features", "description": "Extract distinguishing features",
"parameters": {"type": "object", "properties": {"dataset_id": {"type": "string"}, "cluster_result_id": {"type": "string"}, "method": {"type": "string", "enum": ["zscore", "anova"]}}, "required": ["dataset_id", "cluster_result_id"]}
}}]
def call_llm(messages):
payload = json.dumps({"model": "deepseek-v4-flash", "messages": messages, "tools": TOOLS,
"tool_choice": "auto", "max_tokens": 4096}).encode()
req = urllib.request.Request('https://api.deepseek.com/chat/completions', data=payload,
headers={'Content-Type': 'application/json',
'Authorization': 'Bearer sk-360ef76d59674d6b8bc2eb160327dd39'},
method='POST')
return json.loads(urllib.request.urlopen(req, timeout=30).read())
msgs = [{"role": "user", "content": "Analyze dataset ds. Profile it, build entity profiles, cluster, extract features."}]
for step in range(10):
print(f'\nStep {step + 1}:')
response = call_llm(msgs)
msg = response["choices"][0]["message"]
if "tool_calls" not in msg or not msg["tool_calls"]:
print(f'Done: {msg.get("content", "")[:200]}')
break
for tc in msg["tool_calls"]:
func = tc.get("function", {})
name = func.get("name", "")
try:
args = json.loads(func.get("arguments", "{}"))
except json.JSONDecodeError:
args = {}
print(f' -> {name}({args})')
result = asyncio.run(handle_call(name, args))
content = json.dumps(result, default=str, ensure_ascii=False)[:2000]
print(f' <- {name}: ok' if 'error' not in result else f' <- ERROR: {result["error"]}')
msgs.append({"role": "tool", "tool_call_id": tc["id"], "content": content})