Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions .scripts/changelog/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
OWNER = "confident-ai"
REPO = "deepeval"

START_MARKER = "<!-- DeepEval release notes start -->"
START_MARKER = "{/* DeepEval release notes start */}"
LEGACY_START_MARKER = "<!-- DeepEval release notes start -->"

CATEGORY_ORDER = [
"Backward Incompatible Change",
Expand Down Expand Up @@ -148,21 +149,25 @@ class AiMonthSummary(BaseModel):
# - Prefer the stable marker (lets humans edit the visible link/text)
# - Fall back to parsing the link if the marker is missing
BULLET_PR_RE = re.compile(r"\[#(\d+)\]\(")
BULLET_PR_MARKER_RE = re.compile(r"<!--\s*pr:(\d+)\s*-->")
BULLET_PR_MARKER_RE = re.compile(
r"(?:<!--\s*pr:(\d+)\s*-->|\{/\*\s*pr:(\d+)\s*\*/\})"
)
BULLET_TAIL_RE = re.compile(
r"\s*\(\[#\d+\]\([^)]+\)\)\s*<!--\s*pr:\d+\s*-->.*$"
r"\s*\(\[#\d+\]\([^)]+\)\)\s*(?:<!--\s*pr:\d+\s*-->|\{/\*\s*pr:\d+\s*\*/\}).*$"
)

# Optional ignore list to be placed right after START_MARKER to avoid confusing the parser:
# add a list of PR numbers you would like to be excluded from the generated changelog.
# <!-- changelog-ignore:
# {/* changelog-ignore:
# - 1234
# - 5678
# -->
# */}
IGNORE_BLOCK_TOP_RE = re.compile(
r"(?is)^\s*<!--\s*changelog-ignore:.*?-->\s*\n*"
r"(?is)^\s*(?:<!--\s*changelog-ignore:.*?-->|\{/\*\s*changelog-ignore:.*?\*/\})\s*\n*"
)
IGNORE_BLOCK_ANY_RE = re.compile(
r"(?is)(?:<!--\s*changelog-ignore:(.*?)-->|\{/\*\s*changelog-ignore:(.*?)\*/\})"
)
IGNORE_BLOCK_ANY_RE = re.compile(r"(?is)<!--\s*changelog-ignore:(.*?)-->")

###############
# Git helpers #
Expand Down Expand Up @@ -761,8 +766,16 @@ def _pull_top_ignore_block(s: str) -> Tuple[str, str]:
rest = s2[matched.end() :]
return ignore_block.rstrip("\n") + "\n", rest

if START_MARKER in text:
before, _, after = text.partition(START_MARKER)
marker_in_text = next(
(
marker
for marker in (START_MARKER, LEGACY_START_MARKER)
if marker in text
),
None,
)
if marker_in_text:
before, _, after = text.partition(marker_in_text)
ignore_block, rest = _pull_top_ignore_block(after)
prefix = before.rstrip() + "\n\n" + START_MARKER + "\n"
if ignore_block:
Expand Down Expand Up @@ -792,21 +805,21 @@ def _pull_top_ignore_block(s: str) -> Tuple[str, str]:

def parse_ignore_prs(text: str) -> set[int]:
"""
Parse PR numbers from one or more `<!-- changelog-ignore: ... -->` HTML comment blocks.
Parse PR numbers from one or more changelog-ignore comment blocks.

Should be placed immediately after the `START_MARKER`, for example:

<!-- changelog-ignore:
{/* changelog-ignore:
- 1234
- 5678
-->
*/}

Lines may contain comments which can be used to document why a PR is being ignored
Any integers found in the block are treated as PR numbers.
"""
ignored: set[int] = set()
for matched in IGNORE_BLOCK_ANY_RE.finditer(text):
block = matched.group(1)
block = next(group for group in matched.groups() if group is not None)
for line in block.splitlines():
line = line.strip()
if not line or line.startswith("#"):
Expand Down Expand Up @@ -875,7 +888,7 @@ def parse_body(body: str) -> ChangelogIndex:
)
if not matched:
continue
pr = int(matched.group(1))
pr = int(next(group for group in matched.groups() if group))
idx[month][category][version][pr] = line.rstrip()

return idx
Expand Down Expand Up @@ -1143,7 +1156,7 @@ def _tick() -> None:
author = f" ({user_display})"
line = (
f"- {title_out} ([#{pr_num}](https://github.com/{OWNER}/{REPO}/pull/{pr_num})) "
f"<!-- pr:{pr_num} -->{author}"
f"{{/* pr:{pr_num} */}}{author}"
)
idx[month][category][tag][pr_num] = line
_status(f"[{tag}] PR #{pr_num}: done")
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ authors:
- family-names: Vongthongsri
given-names: Kritin
title: deepeval
version: 3.9.7
date-released: "2026-03-30"
version: 3.9.8
date-released: "2026-04-26"
url: https://confident-ai.com
repository-code: https://github.com/confident-ai/deepeval
license: Apache-2.0
Expand Down
2 changes: 1 addition & 1 deletion deepeval/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__: str = "3.9.7"
__version__: str = "3.9.8"
4 changes: 4 additions & 0 deletions docs/components/mdx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import LinkCards from "@site/src/components/LinkCards";
import TechStackCards from "@site/src/components/TechStackCards";
import { FAQs } from "@site/src/components/FAQ";
import BlogPostMeta from "@site/src/components/BlogPostMeta";
import ChangelogContributors from "@site/src/components/ChangelogContributors";
import RepoContributors from "@site/src/sections/home/RepoContributors";

function DefaultLLMModel() {
return <code>{DEFAULT_LLM_MODEL}</code>;
Expand Down Expand Up @@ -45,6 +47,8 @@ export function getMDXComponents(components?: MDXComponents) {
TechStackCards,
FAQs,
BlogPostMeta,
ChangelogContributors,
RepoContributors,
DefaultLLMModel,
...components,
} satisfies MDXComponents;
Expand Down
16 changes: 16 additions & 0 deletions docs/content/changelog/changelog-2024.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ title: 🐲 2024
sidebar_label: 🐲 2024
---

2024 was all about building DeepEval into a complete evaluation framework:

- **DeepEval 2.0** shipped with refreshed packaging, broader Python support, and smoother installs
- **Red teaming** expanded with broader vulnerability coverage, stronger attack generation, and updated safety graders
- **Dataset generation** became more practical with richer synthesizer, dataset, and golden-management workflows
- **Metric coverage** grew across RAG, summarization, hallucination, bias, toxicity, and custom LLM-as-a-judge use cases
- **Provider flexibility** improved with custom OpenAI endpoints, local model options, and broader model configuration
- **Documentation** matured with clearer getting-started flows, dataset tutorials, and platform guidance
- **Reliability** improved through dependency updates, packaging fixes, and better evaluation ergonomics

## Thank you to our contributors

First things first, DeepEval exists because of everyone who opened issues, reviewed changes, wrote docs, and merged code this year. Thank you for shaping every release with us.

<ChangelogContributors year={2024} limit={96} />

{/* DeepEval release notes start */}

## December
Expand Down
7 changes: 7 additions & 0 deletions docs/content/changelog/changelog-2025.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ sidebar_label: 🐍 2025
- **Reliability** improved with better async handling, timeouts, and retries
- **Documentation** expanded with comprehensive tutorials to help teams ship confidently


## Thank you to our contributors

First things first, DeepEval exists because of everyone who opened issues, reviewed changes, wrote docs, and merged code this year. Thank you for shaping every release with us.

<ChangelogContributors year={2025} limit={96} />

## December

December strengthened evaluation, multimodal support, and prompt optimization. Multimodal test cases now flow through standard evaluation paths with better placeholder detection, Azure OpenAI support, and clearer validation errors. Prompt optimization expanded with GEPA plus new algorithms, alongside more consistent schema-based outputs and broader provider configuration via typed `Settings`.
Expand Down
Loading
Loading