evalvault 1.63.0__py3-none-any.whl → 1.63.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -213,7 +213,9 @@ def register_run_commands(
213
213
  None,
214
214
  "--output",
215
215
  "-o",
216
- help="Output file for results (JSON format).",
216
+ help=(
217
+ "Output file for results (JSON format). If .xlsx/.xls, exports Excel via DB save."
218
+ ),
217
219
  ),
218
220
  auto_analyze: bool = typer.Option(
219
221
  False,
@@ -813,6 +815,27 @@ def register_run_commands(
813
815
  if db_path is None:
814
816
  db_path = Path(settings.evalvault_db_path)
815
817
 
818
+ excel_output: Path | None = None
819
+ if output and output.suffix.lower() in {".xlsx", ".xls"}:
820
+ excel_output = output
821
+ output = None
822
+ if db_path is None:
823
+ print_cli_error(
824
+ console,
825
+ "엑셀 출력은 DB 저장이 필요합니다.",
826
+ fixes=["--db <sqlite_path> 옵션을 함께 지정하세요."],
827
+ )
828
+ raise typer.Exit(1)
829
+ print_cli_warning(
830
+ console,
831
+ "엑셀 출력은 DB 저장이 필수이며, 지정한 경로로만 저장됩니다.",
832
+ tips=[
833
+ f"DB 저장 경로: {db_path}",
834
+ "기본 DB 엑셀은 생성하지 않습니다.",
835
+ "필요 시 --db로 경로를 변경하세요.",
836
+ ],
837
+ )
838
+
816
839
  # Override model if specified
817
840
  if model:
818
841
  if _is_oss_open_model(model) and settings.llm_provider != "vllm":
@@ -1954,8 +1977,23 @@ def register_run_commands(
1954
1977
  console,
1955
1978
  storage_cls=SQLiteStorageAdapter,
1956
1979
  prompt_bundle=prompt_bundle,
1980
+ export_excel=excel_output is None,
1957
1981
  )
1958
1982
  _log_duration(console, verbose, "DB 저장 완료", db_started_at)
1983
+ if excel_output:
1984
+ excel_started_at = datetime.now()
1985
+ _log_timestamp(console, verbose, f"엑셀 저장 시작 ({excel_output})")
1986
+ try:
1987
+ storage = SQLiteStorageAdapter(db_path=db_path)
1988
+ storage.export_run_to_excel(result.run_id, excel_output)
1989
+ console.print(f"[green]Excel export saved: {excel_output}[/green]")
1990
+ except Exception as exc:
1991
+ print_cli_warning(
1992
+ console,
1993
+ "엑셀 내보내기에 실패했습니다.",
1994
+ tips=[str(exc)],
1995
+ )
1996
+ _log_duration(console, verbose, "엑셀 저장 완료", excel_started_at)
1959
1997
  if output:
1960
1998
  output_started_at = datetime.now()
1961
1999
  _log_timestamp(console, verbose, f"결과 저장 시작 ({output})")
@@ -2060,7 +2098,9 @@ def register_run_commands(
2060
2098
  None,
2061
2099
  "--output",
2062
2100
  "-o",
2063
- help="Output file for results (JSON format).",
2101
+ help=(
2102
+ "Output file for results (JSON format). If .xlsx/.xls, exports Excel via DB save."
2103
+ ),
2064
2104
  ),
2065
2105
  auto_analyze: bool = typer.Option(
2066
2106
  False,
@@ -2344,7 +2384,9 @@ def register_run_commands(
2344
2384
  None,
2345
2385
  "--output",
2346
2386
  "-o",
2347
- help="Output file for results (JSON format).",
2387
+ help=(
2388
+ "Output file for results (JSON format). If .xlsx/.xls, exports Excel via DB save."
2389
+ ),
2348
2390
  ),
2349
2391
  auto_analyze: bool = typer.Option(
2350
2392
  False,
@@ -430,6 +430,7 @@ def _save_to_db(
430
430
  *,
431
431
  storage_cls: type[SQLiteStorageAdapter] = SQLiteStorageAdapter,
432
432
  prompt_bundle: PromptSetBundle | None = None,
433
+ export_excel: bool = True,
433
434
  ) -> None:
434
435
  """Persist evaluation run (and optional prompt set) to SQLite database."""
435
436
  with console.status(f"[bold green]Saving to database {db_path}..."):
@@ -443,16 +444,17 @@ def _save_to_db(
443
444
  result.run_id,
444
445
  prompt_bundle.prompt_set.prompt_set_id,
445
446
  )
446
- excel_path = db_path.parent / f"evalvault_run_{result.run_id}.xlsx"
447
- try:
448
- storage.export_run_to_excel(result.run_id, excel_path)
449
- console.print(f"[green]Excel export saved: {excel_path}[/green]")
450
- except Exception as exc:
451
- print_cli_warning(
452
- console,
453
- "엑셀 내보내기에 실패했습니다.",
454
- tips=[str(exc)],
455
- )
447
+ if export_excel:
448
+ excel_path = db_path.parent / f"evalvault_run_{result.run_id}.xlsx"
449
+ try:
450
+ storage.export_run_to_excel(result.run_id, excel_path)
451
+ console.print(f"[green]Excel export saved: {excel_path}[/green]")
452
+ except Exception as exc:
453
+ print_cli_warning(
454
+ console,
455
+ "엑셀 내보내기에 실패했습니다.",
456
+ tips=[str(exc)],
457
+ )
456
458
  console.print(f"[green]Results saved to database: {db_path}[/green]")
457
459
  console.print(f"[dim]Run ID: {result.run_id}[/dim]")
458
460
  if prompt_bundle:
@@ -11,7 +11,7 @@ import logging
11
11
  import re
12
12
  from collections.abc import Callable, Sequence
13
13
  from dataclasses import dataclass, field
14
- from typing import TYPE_CHECKING, Any, cast
14
+ from typing import TYPE_CHECKING, Any
15
15
 
16
16
  import numpy as np
17
17
  from scipy import stats
@@ -9,7 +9,7 @@ import logging
9
9
  from collections.abc import Sequence
10
10
  from dataclasses import dataclass, field
11
11
  from pathlib import Path
12
- from typing import TYPE_CHECKING, Any
12
+ from typing import Any
13
13
 
14
14
  import yaml
15
15
 
@@ -622,7 +622,8 @@ class BaseSQLStorageAdapter(ABC):
622
622
  if isinstance(row, dict):
623
623
  return dict(row)
624
624
  if hasattr(row, "keys"):
625
- return {key: row[key] for key in row}
625
+ keys = row.keys()
626
+ return {key: row[key] for key in keys}
626
627
  try:
627
628
  return dict(row)
628
629
  except Exception:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evalvault
3
- Version: 1.63.0
3
+ Version: 1.63.1
4
4
  Summary: RAG evaluation system using Ragas with Phoenix/Langfuse tracing
5
5
  Project-URL: Homepage, https://github.com/ntts9990/EvalVault
6
6
  Project-URL: Documentation, https://github.com/ntts9990/EvalVault#readme
@@ -36,8 +36,8 @@ evalvault/adapters/inbound/cli/commands/method.py,sha256=OWdoofhvsDJchgNKnGGjXfI
36
36
  evalvault/adapters/inbound/cli/commands/phoenix.py,sha256=LQi3KTLq1ybjjBuz92oQ6lYyBS3mHrCHk0qe-7bqB4U,15611
37
37
  evalvault/adapters/inbound/cli/commands/pipeline.py,sha256=NeqWLzO9kRDuZd0pHAIHglP3F7VzoNOU4JI0QcSZ120,7788
38
38
  evalvault/adapters/inbound/cli/commands/prompts.py,sha256=lddde5VbjYaqN_9gHPLNu6DWpg5fE-KqZzjN-XYwvJw,27153
39
- evalvault/adapters/inbound/cli/commands/run.py,sha256=5rWCh8dTVqRgoiKu2Kd_53PxeIh0GRIkULl3GSpoSiU,117412
40
- evalvault/adapters/inbound/cli/commands/run_helpers.py,sha256=cc6oZHJSBJM9cxr928zq3sGrIh73u2vD0z2j9IzbPo4,40236
39
+ evalvault/adapters/inbound/cli/commands/run.py,sha256=X19rgXhajhvZNA4c0JMmzmPatTxhZgfapuW07bZL9xA,119265
40
+ evalvault/adapters/inbound/cli/commands/run_helpers.py,sha256=hu2TioocitUZzGR7HUwZ6gOeEJSvt5tGNjwXOlo4Eic,40336
41
41
  evalvault/adapters/inbound/cli/commands/stage.py,sha256=oRC9c5CysLX90Iy5Ba1pc_00DaOBS78lcBvzkbdrGRM,17123
42
42
  evalvault/adapters/inbound/cli/utils/__init__.py,sha256=QPNKneZS-Z-tTnYYxtgJXgcJWY6puUlRQcKrn7Mlv1M,685
43
43
  evalvault/adapters/inbound/cli/utils/analysis_io.py,sha256=RHkKEq4e-PtbtRDlXAJWU80RYHNPw-O5V9_GujdaGfc,13393
@@ -127,8 +127,8 @@ evalvault/adapters/outbound/domain_memory/domain_memory_schema.sql,sha256=APlNhJ
127
127
  evalvault/adapters/outbound/domain_memory/sqlite_adapter.py,sha256=RWobnFgvxiItxFAr6niY89sT19O-cnExTbP0I7UAY78,85186
128
128
  evalvault/adapters/outbound/improvement/__init__.py,sha256=tXA6vaZOLvqwJpyjGMiC8WrvszMmvUPzJnHjvJhQxSI,1143
129
129
  evalvault/adapters/outbound/improvement/insight_generator.py,sha256=U16l0euCZy0_08Zb_i0eijXSjS5t-iq0iMUfttwPqgI,17636
130
- evalvault/adapters/outbound/improvement/pattern_detector.py,sha256=4Pc5yrsi2warhKdpWxL0Ba9Ms2sCvFeRVWU8jTeALZ8,24608
131
- evalvault/adapters/outbound/improvement/playbook_loader.py,sha256=zXDpiTpYWtQvVrDeo149YHKIyhF6nUP34j0FVnlBCJo,7471
130
+ evalvault/adapters/outbound/improvement/pattern_detector.py,sha256=uFFjWNy8A4KIihw_ANtL6At73RirwNnFnN4rFsEvcXk,24602
131
+ evalvault/adapters/outbound/improvement/playbook_loader.py,sha256=keheUoJn--cjSbdngEAUlkhrc_dYqdrlW_iZAI2R4Y4,7456
132
132
  evalvault/adapters/outbound/improvement/stage_metric_playbook_loader.py,sha256=JdmXQsackWqeWTnULE4gfTK8vAikGR27h-TVc03CGXk,1706
133
133
  evalvault/adapters/outbound/kg/__init__.py,sha256=fUCKOV080ZjiEob9s4TmXWf-IDa6GbIFQMLfH6gFCKg,567
134
134
  evalvault/adapters/outbound/kg/graph_rag_retriever.py,sha256=_6qd8p_2TpHnppv8LUQQPxUdTPoE0QTQ-rCVnY1ap6c,18658
@@ -167,7 +167,7 @@ evalvault/adapters/outbound/report/dashboard_generator.py,sha256=Dcu18NTK4lS8XNK
167
167
  evalvault/adapters/outbound/report/llm_report_generator.py,sha256=HUDA_IPBbl54cyEjTTJzdKTQ6H4IoZi-1VBdVmZf0uI,26593
168
168
  evalvault/adapters/outbound/report/markdown_adapter.py,sha256=5PS72h_qe4ZtYs-umhX5TqQL2k5SuDaCUc6rRw9AKRw,16761
169
169
  evalvault/adapters/outbound/storage/__init__.py,sha256=n5R6thAPTx1leSwv6od6nBWcLWFa-UYD6cOLzN89T8I,614
170
- evalvault/adapters/outbound/storage/base_sql.py,sha256=kWYaiUq5D35iMx34cX3_mjhRZoEXfgQR-tSk3UhbvcE,40792
170
+ evalvault/adapters/outbound/storage/base_sql.py,sha256=7jWtmNDBHncLDABf5ewwQJnfhFjySTfpfDJmEbPBD1w,40823
171
171
  evalvault/adapters/outbound/storage/benchmark_storage_adapter.py,sha256=Qgf9xSSIkYQRpG4uLzcUdoYO9LTQDQ4tFRkkMYer-WA,9803
172
172
  evalvault/adapters/outbound/storage/postgres_adapter.py,sha256=HLaoQ3YJDFwOxeY0S92oPIqb-7EgWSasgt89RM86vr0,47148
173
173
  evalvault/adapters/outbound/storage/postgres_schema.sql,sha256=A9MfO0pjf4kjxoRj2KPI0Gg1cbX13I2YE3oieT-PGiI,8906
@@ -304,8 +304,8 @@ evalvault/reports/__init__.py,sha256=Bb1X4871msAN8I6PM6nKGED3psPwZt88hXZBAOdH06Y
304
304
  evalvault/reports/release_notes.py,sha256=pZj0PBFT-4F_Ty-Kv5P69BuoOnmTCn4kznDcORFJd0w,4011
305
305
  evalvault/scripts/__init__.py,sha256=NwEeIFQbkX4ml2R_PhtIoNtArDSX_suuoymgG_7Kwso,89
306
306
  evalvault/scripts/regression_runner.py,sha256=SxZori5BZ8jVQ057Mf5V5FPgIVDccrV5oRONmnhuk8w,8438
307
- evalvault-1.63.0.dist-info/METADATA,sha256=Kscv51ExIOOosrBnBXI5S1_3V0S2t2nCZhfyssREdg4,23879
308
- evalvault-1.63.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
309
- evalvault-1.63.0.dist-info/entry_points.txt,sha256=Oj9Xc5gYcyUYYNmQfWI8NYGw7nN-3M-h2ipHIMlVn6o,65
310
- evalvault-1.63.0.dist-info/licenses/LICENSE.md,sha256=3RNWY4jjtrQ_yYa-D-7I3XO12Ti7YzxsLV_dpykujvo,11358
311
- evalvault-1.63.0.dist-info/RECORD,,
307
+ evalvault-1.63.1.dist-info/METADATA,sha256=wkxUE5VIFBr2zmdSpRtcGs8Xwbry3ydY7U2XJFEEzjo,23879
308
+ evalvault-1.63.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
309
+ evalvault-1.63.1.dist-info/entry_points.txt,sha256=Oj9Xc5gYcyUYYNmQfWI8NYGw7nN-3M-h2ipHIMlVn6o,65
310
+ evalvault-1.63.1.dist-info/licenses/LICENSE.md,sha256=3RNWY4jjtrQ_yYa-D-7I3XO12Ti7YzxsLV_dpykujvo,11358
311
+ evalvault-1.63.1.dist-info/RECORD,,