perf_analysis.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import sys, time, json, os
  2. sys.path.insert(0, "/data/knowledge/maritime")
  3. print("=" * 60)
  4. print("RAG Performance Analysis")
  5. print("=" * 60)
  6. # 1. Index load time
  7. from search_engine import _load_index, _get_config, search, tokenize
  8. cfg = _get_config()
  9. print("\n--- Index Loading ---")
  10. t0 = time.time()
  11. idx = _load_index()
  12. t1 = time.time()
  13. print("Load time:", round(t1 - t0, 2), "s")
  14. print("Chunks:", idx["total"])
  15. print("Keywords:", len(idx["keywords"]))
  16. # Index file sizes
  17. for name in ["rag_index.json", "rag_index.keywords.json"]:
  18. path = os.path.join(cfg["base_dir"], name) if "base_dir" in cfg else "/data/knowledge/maritime/" + name
  19. if os.path.exists(path):
  20. size_mb = os.path.getsize(path) / 1024 / 1024
  21. print(f" {name}: {size_mb:.1f} MB")
  22. # 2. Search latency
  23. print("\n--- Search Latency ---")
  24. queries = [
  25. "船舶进出港报告制度",
  26. "海上交通安全法 水污染防治法 船舶管理",
  27. "船员适任证书申请条件",
  28. "2019年船员发展报告",
  29. "琼州海峡定线制",
  30. "上海海事大学船长及格率",
  31. ]
  32. for q in queries:
  33. times = []
  34. for _ in range(3):
  35. t0 = time.time()
  36. results = search(q, top_k=5)
  37. elapsed = time.time() - t0
  38. times.append(elapsed)
  39. avg = sum(times) / len(times)
  40. top_score = results[0]["score"] if results else 0
  41. top_src = results[0]["source"][:40] if results else "N/A"
  42. print(f" Q: {q[:30]:30s} | {avg*1000:6.0f}ms | score={top_score:.1f} | {top_src}")
  43. # 3. Tokenization analysis
  44. print("\n--- Tokenization ---")
  45. for q in ["海上交通安全法", "船员适任证书"]:
  46. tokens = tokenize(q)
  47. print(f" '{q}' -> {len(tokens)} tokens: {tokens[:10]}")
  48. # 4. Keyword index density
  49. print("\n--- Keyword Index Density ---")
  50. kw = idx["keywords"]
  51. lengths = [len(v) for v in kw.values()]
  52. print(f" Total keywords: {len(kw)}")
  53. print(f" Avg postings per keyword: {sum(lengths)/len(lengths):.1f}")
  54. print(f" Max postings: {max(lengths)} (keyword: {[k for k,v in kw.items() if len(v)==max(lengths)][0][:10]})")
  55. print(f" Keywords with 1 posting: {sum(1 for l in lengths if l == 1)}")
  56. print(f" Keywords with >1000 postings: {sum(1 for l in lengths if l > 1000)}")
  57. # 5. Search quality issue: check what "海上交通安全法" retrieves
  58. print("\n--- Search Quality Check ---")
  59. r1 = search("海上交通安全法 船舶 航行", top_k=3)
  60. for i, r in enumerate(r1):
  61. has_law = "海上交通安全法" in r["source"]
  62. print(f" [{i+1}] {'[LAW]' if has_law else '[REF]'} score={r['score']:.1f} {r['source'][:60]}")
  63. # 6. LLM call time (biggest bottleneck)
  64. print("\n--- LLM Inference Time ---")
  65. import urllib.request
  66. body = json.dumps({
  67. "model": "qwen2.5-32b",
  68. "messages": [{"role": "user", "content": "Reply OK in one word"}],
  69. "max_tokens": 5,
  70. }).encode("utf-8")
  71. req = urllib.request.Request("http://127.0.0.1:8000/v1/chat/completions",
  72. data=body, headers={"Content-Type": "application/json"}, method="POST")
  73. t0 = time.time()
  74. with urllib.request.urlopen(req, timeout=30) as resp:
  75. data = json.loads(resp.read())
  76. t1 = time.time()
  77. print(f" Simple query: {(t1-t0)*1000:.0f}ms")
  78. # Longer prompt
  79. body2 = json.dumps({
  80. "model": "qwen2.5-32b",
  81. "messages": [{"role": "user", "content": "用200字概括中国海事法律体系" + "x" * 2000}],
  82. "max_tokens": 500,
  83. }).encode("utf-8")
  84. req2 = urllib.request.Request("http://127.0.0.1:8000/v1/chat/completions",
  85. data=body2, headers={"Content-Type": "application/json"}, method="POST")
  86. t0 = time.time()
  87. with urllib.request.urlopen(req2, timeout=60) as resp:
  88. data2 = json.loads(resp.read())
  89. t1 = time.time()
  90. tokens_out = data2.get("usage", {}).get("completion_tokens", 0)
  91. print(f" Long prompt + 500 tokens: {(t1-t0)*1000:.0f}ms ({tokens_out} output tokens)")
  92. if tokens_out > 0:
  93. print(f" Tokens/sec: {tokens_out/(t1-t0):.1f}")
  94. print("\n--- Summary ---")
  95. print(" Bottleneck: LLM inference (10-20s) >> Index load (once) >> Search (<100ms)")