Download test_10_qna_hf.py from jarnil/byteastra: direct link, hf CLI and curl.
- Browser
- Download file 11.6 kB
-
https://huggingface.co/spaces/jarnil/byteastra/resolve/main/test_10_qna_hf.py
- Command line
-
hf download hf://spaces/jarnil/byteastra/test_10_qna_hf.py
-
curl -L -o test_10_qna_hf.py https://huggingface.co/spaces/jarnil/byteastra/resolve/main/test_10_qna_hf.py
11.6 kB
| import asyncio | |
| import time | |
| import json | |
| import urllib.request | |
| import ssl | |
| import sys | |
| sys.stdout.reconfigure(encoding='utf-8', write_through=True) | |
| # Wrap print to flush immediately | |
| import builtins | |
| _print = builtins.print | |
| def print(*args, **kwargs): | |
| kwargs['flush'] = True | |
| _print(*args, **kwargs) | |
| builtins.print = print | |
| QUESTIONS = [ | |
| # ── EASY (1-5) ────────────────────────────────────────────────────────── | |
| ("easy", 1, "What is Ayurveda?"), | |
| ("easy", 2, "What are the three Doshas?"), | |
| ("easy", 3, "What is Vata dosha?"), | |
| ("easy", 4, "What are the seven Dhatus?"), | |
| ("easy", 5, "What is Agni in Ayurveda?"), | |
| # ── MEDIUM (6-10) ─────────────────────────────────────────────────────── | |
| ("medium", 6, "List the five subtypes of Vata with their locations and functions."), | |
| ("medium", 7, "List the five subtypes of Pitta with their locations and functions."), | |
| ("medium", 8, "List the five subtypes of Kapha with their locations and functions."), | |
| ("medium", 9, "Explain the 13 types of Agni with their roles in digestion."), | |
| ("medium", 10, "What is Basti therapy and what dosha does it primarily treat?"), | |
| # ── HARD (11-15) ──────────────────────────────────────────────────────── | |
| ("hard", 11, "Explain the Dhatu-Agni pathway: how Rasa Dhatu transforms into Shukra Dhatu step by step."), | |
| ("hard", 12, "Describe Samprapti (pathogenesis) with all six stages of disease development."), | |
| ("hard", 13, "Explain the role of Ojas in immunity and its relationship to all seven Dhatus."), | |
| ("hard", 14, "Describe the Ashtavidha Pariksha (eightfold examination) in detail."), | |
| ("hard", 15, "What are the contraindications of Vamana therapy?"), | |
| # ── VERY TOUGH (16-20) ────────────────────────────────────────────────── | |
| ("very_tough", 16, "Explain the concept of Tridosha Siddhanta and how the interaction of three Doshas maintains homeostasis."), | |
| ("very_tough", 17, "Describe the complete pathogenesis (Samprapti) of Jwara (fever) including all stages."), | |
| ("very_tough", 18, "Describe the Srotas, their Mula (root), Marga (path) and Mukha (opening) for all 13 Srotamsi."), | |
| ("very_tough", 19, "Explain the theory of Loka-Purusha Samya (macrocosm-microcosm relationship)."), | |
| ("very_tough", 20, "What is Swasthavritta? Describe all its components including Dinacharya, Ritucharya and Sadvritta."), | |
| ] | |
| BASE_URL = "https://jarnil-byteastra.hf.space" | |
| RESULTS = [] | |
| # SSL Context to bypass cert verification for local curl/urllib if needed | |
| ctx = ssl.create_default_context() | |
| ctx.check_hostname = False | |
| ctx.verify_mode = ssl.CERT_NONE | |
| def create_session() -> str: | |
| print(f"Creating test session on HF Space...") | |
| url = f"{BASE_URL}/sessions" | |
| data = json.dumps({ | |
| "domain": "ayurveda", | |
| "title": "HF QNA Stress Test Session", | |
| "user_id": "hf_tester" | |
| }).encode("utf-8") | |
| req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}, method="POST") | |
| with urllib.request.urlopen(req, context=ctx) as response: | |
| res = json.loads(response.read().decode("utf-8")) | |
| print(f"Session created: {res['id']}") | |
| return res["id"] | |
| async def run_one(session_id, level, qnum, query, log_file): | |
| url = f"{BASE_URL}/chat" | |
| payload = { | |
| "session_id": session_id, | |
| "message": query, | |
| "stream": True | |
| } | |
| start = time.time() | |
| first_tok = None | |
| words = 0 | |
| full = [] | |
| grounded = False | |
| citations = 0 | |
| error = None | |
| try: | |
| # We run the request inside a thread pool because urllib is blocking, | |
| # or we use standard async fetch if possible. | |
| # To keep it standard library without dependencies (like httpx or aiohttp), | |
| # we do a synchronous streaming read in a thread. | |
| loop = asyncio.get_event_loop() | |
| def perform_request(): | |
| nonlocal first_tok, words, grounded, citations, error | |
| data = json.dumps(payload).encode("utf-8") | |
| req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"}, method="POST") | |
| try: | |
| with urllib.request.urlopen(req, context=ctx, timeout=60.0) as response: | |
| # Read line by line (SSE format) | |
| for line in response: | |
| line_str = line.decode("utf-8").strip() | |
| if line_str.startswith("data:"): | |
| evt_data = json.loads(line_str[5:]) | |
| evt_type = evt_data.get("type") | |
| if evt_type == "citations": | |
| grounded = evt_data.get("is_grounded", False) | |
| citations = len(evt_data.get("citations", [])) | |
| elif evt_type == "delta": | |
| c = evt_data.get("content", "") | |
| if c: | |
| if first_tok is None: | |
| first_tok = time.time() - start | |
| words += len(c.split()) | |
| full.append(c) | |
| elif evt_type == "error": | |
| error = evt_data.get("error") | |
| except Exception as e: | |
| error = str(e) | |
| await loop.run_in_executor(None, perform_request) | |
| except Exception as e: | |
| error = str(e) | |
| total = time.time() - start | |
| response = "".join(full).strip() | |
| # Quality heuristics | |
| has_heading = "##" in response or "###" in response | |
| has_list = "- " in response or "1." in response | |
| has_sanskrit = any(w in response for w in ["Agni","Dosha","Dhatu","Vata","Pitta","Kapha","Ama","Ojas"]) | |
| score_hint = "GOOD" if (words > 80 and has_heading and has_list and has_sanskrit) else ("PARTIAL" if words > 40 else "SHORT") | |
| ttft_str = f"{first_tok:.2f}s" if first_tok else "N/A" | |
| result = { | |
| "level": level, | |
| "q": qnum, | |
| "query": query, | |
| "grounded": grounded, | |
| "citations": citations, | |
| "ttft": round(first_tok, 2) if first_tok else None, | |
| "total_s": round(total, 2), | |
| "words": words, | |
| "quality": score_hint, | |
| "error": error, | |
| "response": response, | |
| "response_preview": response[:200] + "..." if len(response) > 200 else response, | |
| } | |
| RESULTS.append(result) | |
| print(f"[Q{qnum:02d} | {level.upper():<10}] TTFT: {ttft_str:<6} | Total: {total:.1f}s | Words: {words:<4} | Quality: {score_hint:<7} | Grounded: {str(grounded):<5} | Citations: {citations:<2} | Query: {query}") | |
| # Log to file | |
| log_file.write(f"======================================================================\n") | |
| log_file.write(f"QUESTION {qnum:02d} | Level: {level.upper()} | Citations: {citations} | Grounded: {grounded}\n") | |
| log_file.write(f"TTFT: {ttft_str} | Total Time: {total:.2f}s | Word Count: {words} | Quality: {score_hint}\n") | |
| log_file.write(f"Query: {query}\n") | |
| log_file.write(f"----------------------------------------------------------------------\n") | |
| if error: | |
| log_file.write(f"ERROR: {error}\n") | |
| else: | |
| log_file.write(f"{response}\n") | |
| log_file.write(f"======================================================================\n\n") | |
| log_file.flush() | |
| return result | |
| async def main(): | |
| print("="*85) | |
| print("ByteAstra 20-Question BAMS Stress Test (Hugging Face Space API Endpoint)") | |
| print("="*85) | |
| try: | |
| session_id = create_session() | |
| except Exception as e: | |
| print(f"Failed to start session on Hugging Face Space: {e}") | |
| sys.exit(1) | |
| log_path = r"c:\Risu Solutions\ByteAstra\backend\stress_qna_log_hf.txt" | |
| with open(log_path, "w", encoding="utf-8") as log_file: | |
| log_file.write("======================================================================\n") | |
| log_file.write("BYTEASTRA BAMS 20-QUESTION STRESS TEST QNA LOG (HF SPACE)\n") | |
| log_file.write(f"Executed At: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") | |
| log_file.write("======================================================================\n\n") | |
| for level, qnum, query in QUESTIONS: | |
| await run_one(session_id, level, qnum, query, log_file) | |
| await asyncio.sleep(1.0) # brief pause between queries | |
| # Final summary table | |
| print("\n" + "="*85) | |
| print("FINAL METRICS TABLE (HUGGING FACE SPACE)") | |
| print("="*85) | |
| print(f"| {'Q#':<2} | {'Difficulty':<10} | {'TTFT':<7} | {'Total Time':<10} | {'Words':<5} | {'Grounded':<8} | {'Citations':<9} | {'Quality':<7} |") | |
| print(f"|---|------------|---------|------------|-------|----------|-----------|---------|") | |
| for r in RESULTS: | |
| ttft_val = f"{r['ttft']:.2f}s" if r['ttft'] else "N/A" | |
| tot_val = f"{r['total_s']:.1f}s" | |
| print(f"| {r['q']:02d} | {r['level']:<10} | {ttft_val:<7} | {tot_val:<10} | {r['words']:<5} | {str(r['grounded']):<8} | {r['citations']:<9} | {r['quality']:<7} |") | |
| # Aggregate levels | |
| print("\n" + "="*85) | |
| print("AGGREGATED METRICS BY LEVEL") | |
| print("="*85) | |
| by_level = {} | |
| for r in RESULTS: | |
| by_level.setdefault(r["level"], []).append(r) | |
| for level in ["easy", "medium", "hard", "very_tough"]: | |
| group = by_level.get(level, []) | |
| if not group: | |
| continue | |
| grounded_pct = sum(1 for r in group if r["grounded"]) / len(group) * 100 | |
| good_pct = sum(1 for r in group if r["quality"] == "GOOD") / len(group) * 100 | |
| avg_time = sum(r["total_s"] for r in group) / len(group) | |
| valid_ttfts = [r["ttft"] for r in group if r["ttft"] is not None] | |
| avg_ttft = sum(valid_ttfts) / len(valid_ttfts) if valid_ttfts else 0.0 | |
| avg_words = sum(r["words"] for r in group) / len(group) | |
| errors = sum(1 for r in group if r["error"]) | |
| print(f"{level.upper():<10} | Grounded={grounded_pct:.0f}% | Good={good_pct:.0f}% | AvgTTFT={avg_ttft:.2f}s | AvgTime={avg_time:.1f}s | AvgWords={avg_words:.0f} | Errors={errors}") | |
| total_grounded = sum(1 for r in RESULTS if r["grounded"]) | |
| total_good = sum(1 for r in RESULTS if r["quality"] == "GOOD") | |
| total_errors = sum(1 for r in RESULTS if r["error"]) | |
| avg_t = sum(r["total_s"] for r in RESULTS) / len(RESULTS) | |
| all_ttfts = [r["ttft"] for r in RESULTS if r["ttft"] is not None] | |
| avg_ttft_all = sum(all_ttfts) / len(all_ttfts) if all_ttfts else 0.0 | |
| print(f"\nOVERALL | Grounded={total_grounded/len(RESULTS)*100:.0f}% | Good={total_good/len(RESULTS)*100:.0f}% | AvgTTFT={avg_ttft_all:.2f}s | AvgTime={avg_t:.1f}s | Errors={total_errors}") | |
| # Save JSON | |
| with open(r"c:\Risu Solutions\ByteAstra\backend\stress_results_hf.json", "w", encoding="utf-8") as f: | |
| json.dump(RESULTS, f, indent=2) | |
| print(f"\nRaw metrics saved to: c:\\Risu Solutions\\ByteAstra\\backend\\stress_results_hf.json") | |
| print(f"Full Q&A logs saved to: {log_path}") | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |