"""Explicit live smoke command. Saves outputs only under ignored output/. No credentials, company fields or full request bodies are printed to logs. """ import argparse from dataclasses import replace import json from pathlib import Path from .graph import build_graph from .intent import deepseek_analyzer from .qcc import QccClient, load_config from .recommendation import JsonModel, Recommender from .retrieval import Retriever from .report import export from langgraph.types import Command def main(): parser = argparse.ArgumentParser() parser.add_argument('--mode', choices=('personal', 'enterprise'), required=True) args = parser.parse_args() root = Path(__file__).resolve().parents[2] env = root / '.env' client = QccClient(replace(load_config(env), honor_max_pages=1)) retriever = Retriever(env, root / 'knowledge/prepared/ingestion/manifest.json') retriever.warmup() graph = build_graph(client, deepseek_analyzer(env), retriever=retriever, recommender=Recommender(JsonModel(env))) # Public vendor fixture; never identifies this entity as the user's company. company_name = '企查查科技股份有限公司' question = ('我在青浦失业了,想参加职业技能培训,能得到什么帮助?' if args.mode == 'personal' else company_name + '想在青浦设立分公司,招聘研发人员,有哪些人才或研发支持?') config = {'configurable': {'thread_id': 'live-' + args.mode}, 'recursion_limit': 100} result = graph.invoke({'question': question}, config) clarified = False if result.get('__interrupt__') and args.mode == 'enterprise' and result['__interrupt__'][0].value['kind'] == 'company_need': clarified = True result = graph.invoke(Command(resume={'needs_company': True, 'company_hint': company_name}), config) if result.get('__interrupt__'): value = result['__interrupt__'][0].value if args.mode == 'enterprise' and value['kind'] == 'company_selection': selected = [r for r in value['result']['candidates'] if r['Name'] == company_name] if len(selected) != 1: result = graph.invoke(Command(resume={'action': 'refine', 'keyword': company_name}), config) value = result['__interrupt__'][0].value selected = [r for r in value['result']['candidates'] if r['Name'] == company_name] if len(selected) != 1: raise ValueError('fixture_not_unique') result = graph.invoke(Command(resume={'action': 'select', 'key_no': selected[0]['KeyNo']}), config) else: raise ValueError('unexpected_intent_interrupt') answer = result['recommendation'] html, output_json = export(answer, root / 'output/consultations') print(json.dumps({'mode': args.mode, 'complete': answer['complete'], 'retrieval_analysis_complete': answer['retrieval_analysis_complete'], 'recommendations': len(answer['items']), 'sources': len(answer['sources']), 'analysis_errors': answer['analysis_errors'], 'failed_databases': answer['retrieval']['failed_databases'], 'content_failures': answer['retrieval']['content_failures'], 'qcc_profile_verified': result.get('profile') is not None, 'intent_clarified': clarified, 'html': str(html), 'json': str(output_json)}, ensure_ascii=False), flush=True) if __name__ == '__main__': try: main() except Exception as exc: safe_code = str(exc) if str(exc) in ('fixture_not_unique', 'unexpected_intent_interrupt') else 'live_smoke_failed' print(json.dumps({'error_type': type(exc).__name__, 'status': safe_code}), flush=True) raise SystemExit(1) from None