Skip to main content

kocer

한국어 · English

PyPI Python tests

한국어 STT용 CER: 글자가 아니라 읽기가 같은지로 채점합니다. 띄어쓰기·문장부호·숫자 표기(3개 = 세 개)·영문 약어(AI = 에이아이) 차이는 오류로 세지 않습니다.

설치 없이 브라우저에서 써보기 → 정답과 STT 출력을 붙여넣으면 기존 CER, kocer CER, 오류 분해가 바로 나옵니다.

공개 한국어 ASR 모델 7개 설정의 기존 CER 오류를 띄어쓰기·문장부호·숫자/영문·진짜 오류로 나눈 누적 막대. 모델에 따라 46~64%가 표기 차이다.

위 그림의 막대 하나를 내 모델 출력으로 한 줄에 얻습니다. 기존 CER은 그대로 두고, 그 오류가 어디서 왔는지 나눠 보여줍니다.

기존 CER은 정답과 받아쓰기를 글자 그대로 비교한 값입니다. 띄어쓰기와 문장부호도 글자로 셉니다. jiwer의 cer()와 Hugging Face evaluate의 cer가 이렇게 계산하고, 아래 출력의 raw CER이 이 값입니다.

>>> import kocer
>>> print(kocer.breakdown(refs, hyps))      # whisper-large-v3, Zeroth test 457발화
raw CER 6.88%  →  kocer CER 2.90%   (1,753 raw errors, 457 pairs, kocer 0.5.0)
띄어쓰기       704   40%  ████████████████
문장부호       226   13%  █████
숫자·영문      263   15%  ██████
진짜 오류      560   32%  █████████████

왜 필요한가

정답이 "세 시에 만나"인데 모델이 "3시에 만나"라고 받아쓰면, 맞은 걸까요? 사람이 보면 맞았습니다. 그런데 기존 CER은 글자가 다르니 틀렸다고 셉니다. 띄어쓰기와 문장부호를 빼고 재는 nlptutti 같은 한국어 도구도 숫자 표기 차이는 그대로 오류로 셉니다.

이게 진짜 문제가 되는 건 모델을 비교할 때입니다. 숫자를 아라비아로 쓰는 모델과 한글로 쓰는 모델이 있으면, 정답 전사가 어느 쪽으로 적혀 있느냐에 따라 이기는 쪽이 바뀝니다. 실력이 아니라 숫자 쓰는 습관을 비교하게 되는 겁니다.

실제로 확인한 사례입니다. 같은 두 모델의 같은 받아쓰기 결과를, 정답의 숫자 표기만 바꿔서 채점했습니다.

정답 전사의 숫자 표기 띄어쓰기·문장부호를 뺀 CER의 결론 kocer의 결론
아라비아 숫자 (3시) 새 모델이 더 좋다 새 모델이 더 좋다
한글 (세 시) 새 모델이 더 나쁘다 새 모델이 더 좋다

띄어쓰기와 문장부호를 빼고 재도, 정답을 어떻게 적었느냐에 따라 정반대 결론이 나옵니다. kocer는 같은 말을 다르게 적은 것을 맞은 것으로 보기 때문에, 어느 쪽 정답으로 재도 같은 결론이 나옵니다.

그래서 비슷한 모델끼리, 특히 새 버전이 숫자 쓰는 습관을 바꿨을 때 필요합니다. 모델끼리 실력 차이가 크면 어떤 도구로 재도 순위는 거의 같습니다. 차이가 우연으로 설명되는지는 kocer.compare()로 확인할 수 있습니다.

자세한 숫자
  • 데이터: AI-Hub KsponSpeech 평가셋 중 숫자가 든 628발화. 이 데이터는 숫자를 (3시)/(세 시)처럼 두 가지로 적어 두어서, 같은 음성에 대해 두 정답을 만들 수 있습니다.
  • 모델: 원래 모델 Qwen/Qwen3-ASR-1.7B와, 이를 한국어 데이터로 추가 학습한 새 모델 TeamUNIVA/qwen3_asr_1.7b_ko.
  • 띄어쓰기·문장부호를 뺀 CER(nlptutti 방식): 정답이 3시면 새 모델이 8.50%p 좋고, 세 시면 4.13%p 나쁩니다.
  • kocer: 정답이 3시면 새 모델이 2.36%p 좋고, 세 시여도 2.41%p 좋습니다.
  • 네 값 모두 문장 단위 paired bootstrap 95% 신뢰구간이 0을 벗어납니다.
  • AI-Hub 전화 음성(숫자가 든 408발화)에서도 같은 일이 생깁니다. 띄어쓰기·문장부호를 뺀 CER로는 정답이 3시면 새 모델이 6.58%p 좋고, 세 시면 0.47%p 차이로 구분되지 않습니다. kocer로는 3.77%p, 3.66%p로 둘 다 새 모델이 좋습니다.

자세한 내용은 benchmarks/에 있습니다.

설치

pip install kocer          # 순수 파이썬, 의존성 없음
pip install "kocer[fast]"  # rapidfuzz로 수십 배 빠름. 많이 재거나 긴 글을 잴 때 권장

사용

import kocer

kocer.cer("사과 세 개 주세요", "사과 3개 주세요")    # 0.0
kocer.cer(refs, hyps)                                 # 리스트는 코퍼스 단위 (jiwer와 같은 집계)

r = kocer.measure("세 시 삼십 분", "3시 30분")
r.cer, r.raw_cer                                      # 0.0, 0.625  (정규화 후, 정규화 전)

print(kocer.breakdown(refs, hyps))                    # 오류를 종류별로 분해 (위 출력)
print(kocer.compare(refs, {"새 모델": new, "이전 모델": old}))   # 모델 비교: 순위와 차이의 95% 신뢰구간
kocer.cer("유니스트 입학", "UNIST 입학", aliases={"UNIST": "유니스트"})   # 단어처럼 읽는 약어
kocer.cer("(7시)/(일곱 시)에 만나", "7시에 만나")    # 0.0  AI-Hub 이중 표기는 양쪽 다 정답
kocer.cer("b/ 그거+ 그거 *좋아", "그거 그거 좋아", aihub=True)   # 0.0  AI-Hub 원본 전사를 정제 없이
kocer ref.txt hyp.txt          # 줄 단위 쌍. raw CER, kocer CER, 오류 분해
kocer ref.txt hyp.txt --diff   # 틀린 글자만 색으로 표시
kocer ref.txt new.txt old.txt  # 결과 파일이 둘 이상이면 모델 비교
API 전체
kocer.wer(ref, hyp)

r = kocer.measure("세 시 삼십 분", "3시 30분")
r.ops         # {'S': 0, 'D': 0, 'I': 0}
r.alignment   # [('H', '세', '세'), ...]
r.chosen_ref  # 숫자 후보 중 실제로 채택된 정답
r.chosen_hyp  # '세시 삼십분'
r.ref_len     # 5: 분모. 정답을 정규화한 글자 수로, 결과가 무엇이든 같다

b = kocer.breakdown(refs, hyps)
b.spacing, b.punctuation, b.numbers_letters, b.remaining   # 합이 b.raw_errors
b.shares                          # 비율
b.cer                             # {'raw':…, 'nospace':…, 'nopunct':…, 'kocer':…}

c = kocer.compare(refs, {"A": hyps_a, "B": hyps_b, "C": hyps_c}, n_boot=2000, seed=0)
c.cer                             # 시스템별 CER
c.difference("A", "B")            # (CER A − CER B, 95% 하한, 상한). 문장 단위 paired bootstrap, 순서 무관
c.significant("A", "B")           # 차이가 0이 아닌가
c.ranks["A"]                      # (순위 하한, 상한, 1위 확률)
print(c)                          # 표로 출력. numpy가 있으면 빠르게, 없으면 순수 파이썬으로 계산

kocer.cer("엘지 트윈스", "LG 트윈스")      # 0.0  대문자 연속은 철자 읽기
kocer.cer("케이비오 리그", "KBO 리그")      # 0.0

기존 도구와 비교

jiwer, nlptutti, kocer는 모두 같은 편집거리로 CER을 계산합니다. 다른 건 무엇을 오류로 세느냐입니다. jiwer는 띄어쓰기·문장부호도 오류로 세고, nlptutti는 그 둘은 무시하지만 숫자·영문 표기 차이는 셉니다. kocer는 숫자와 영문 약어 읽기까지 같은 말로 봅니다.

정답 STT 결과 jiwer nlptutti kocer
네, 알겠습니다. 네 알겠습니다 0.222 0.000 0.000
사과 세 개 주세요 사과 3개 주세요 0.200 0.143 0.000
세 시 삼십 분 3시 30분 0.625 0.600 0.000
이천이십사 년 십이 월 2024년 12월 0.750 0.778 0.000
에이아이 모델 AI 모델 0.571 0.667 0.000
사과 세 개 주세요 사과 네 개 주세요 0.100 0.143 0.143
세 시 삼십 분 3시 13분 0.625 0.600 0.400

마지막 두 줄은 진짜 인식 오류이고, kocer도 오류로 셉니다. jiwer 4.0.0, nlptutti 0.0.0.24, kocer 0.5.0, 모두 기본 설정.

개체명·키워드 평가나 품질 게이트(기준 점수로 CI 막기)가 필요하면 nlptutti가 낫습니다. 두 도구를 같이 써도 됩니다.

기능 비교표
jiwer nlptutti kocer
띄어쓰기·문장부호 무시 직접 설정 기본 기본
숫자 읽기 차이 무시 (3개 = 세 개) 없음 없음 기본
영문 약어 읽기 차이 무시 (AI = 에이아이) 없음 없음 기본, 사용자 사전 지원
정규화 전·후 CER을 한 번에 반환 없음 없음 raw_cer, cer
오류를 띄어쓰기·문장부호·숫자·진짜 오류로 분해 없음 없음 breakdown()
여러 모델 비교, 쌍별 신뢰구간 없음 있음 compare()
품질 게이트 (기준 점수로 CI 막기) 없음 있음 없음
개체명·키워드 오류율 없음 있음 없음
지원 지표 WER, CER, MER, WIL, WIP CER, WER, CRR CER, WER
필수 의존성 rapidfuzz, click jiwer 없음

오십 퍼센트 / 50%도 jiwer와 nlptutti는 1.000, kocer는 0.000입니다.

채점 규칙

kocer는 글자가 같은지가 아니라 읽으면 같은 말인지를 잽니다. 띄어쓰기와 문장부호를 지우고, 숫자·영문 약어·단위는 가능한 읽기 중 CER이 가장 낮은 것을 고릅니다. 모든 단계는 끌 수 있고, 정규화 전 CER(raw_cer)을 항상 같이 돌려줍니다. 정규화가 실제 오류를 숨길 수 있고, 자막처럼 표기 자체가 결과물인 경우도 있으니 두 값을 같이 보고하세요.

단계별 설정, 숫자 후보 규칙, 계산식
단계 기본 끄기 예
유니코드 NFKC, 폭 없는 문자 제거 켬 - 자모 분리 입력, 전각 AI = AI, ㎞ = km, BOM·\u200b 제거
문장부호 제거 켬 punct=False 네, 알겠습니다. = 네 알겠습니다
필러 제거 (음, 어, 그) 끔 fillers=True 실제 단어 "그"도 지워질 수 있어 기본은 끔
영문 약어·단위 켬 letters=False AI = ai = 에이아이, CEO = 씨이오, NASA = 나사, 50% = 오십 퍼센트 = 50프로, 5m = 오 미터, 5㎡ = 오 제곱미터, 100W = 백 와트, 2GB = 이 기가바이트, C4 = 씨포
숫자 후보 전개 켬 numbers=False 3개 = 세 개, 3층 = 삼 층, 3:30 = 세 시 삼십 분, -5도 = 영하 오 도, $100 = 백 달러, 6월 = 유월, 1만 = 만, 1/2 = 이분의 일
AI-Hub 이중 표기 켬 dual=False (7시)/(일곱 시) = 7시 = 일곱 시
AI-Hub 잡음 태그·표시 제거 끔 aihub=True로 켬 b/, n/, 어/, +, *, (NO:), /(noise), @웃음 제거. 가림 태그 @이름1, &이름&은 남김(한계 참고). 일반 텍스트의 C++를 지키려고 기본은 끔
공백 제거 CER만 - WER은 공백 유지. WER은 숫자 후보도 기본으로 끔(3개 → 세 개는 어절 수가 바뀜)

normalize=False면 jiwer와 같은 순수 CER을 돌려줍니다(앞뒤 공백만 뗌).

숫자: 정답 하나가 아니라 후보 집합. 숫자는 조수사에 따라 읽기가 달라서(3개 = 세 개, 3층 = 삼 층) 규칙 하나로 정답을 만들 수 없습니다. 숫자마다 {원문 숫자, 한자어 읽기, 고유어 읽기, 자릿수 읽기} 후보를 만들고 CER이 최소가 되는 조합을 고릅니다.

  • 조수사 사전(counters.py)에 있으면 그 읽기만, 없으면 두 읽기를 모두 허용합니다. 고유어 조수사라도 20 이상이면 한자어 읽기도 받습니다(35명 = 삼십오 명 = 서른다섯 명).
  • 반대 방향(정답이 한글 수사, 결과가 숫자)도 처리합니다.
  • 전화번호·연도는 자릿수 읽기(010 = 공일공 = 영일영, 2024 = 이공이사)도 후보입니다. 두세 자리 숫자의 자릿수 읽기는 조수사가 붙지 않을 때만 받습니다: 34일과 삼 사 일(3~4일)은 다른 말입니다.
  • 고유어 읽기는 1~99까지이고, 관형형(세, 스무)과 단독형(셋, 스물)을 모두 넣습니다. 소수점은 점만 받고 구어 쩜은 받지 않습니다. 6월 = 유월, 10월 = 시월, 1번째 = 첫 번째.
  • 정답 후보와 결과 후보를 함께 전부 맞춰 보고 오류가 가장 적은 쌍을 고릅니다(조합 4,096개까지). 그보다 많으면 원문에서 시작해 한 구간씩 바꿔 보고 나아질 때만 받아들이는 근사를 쓰므로, 숫자를 그대로 둔 채점보다 나빠지지 않습니다.

계산식. CER = (치환 + 삭제 + 삽입) / 정답 글자 수. 정규화는 정답과 결과에 같은 순서로 적용하고, 공백을 뺀 글자 단위로 셉니다. 분모(ref_len)는 정답을 적힌 그대로 정규화한 글자 수이고 후보 선택과 무관하므로, 모델이 숫자를 어떻게 썼든 같은 문장은 같은 분모로 채점됩니다(이중 표기는 철자 쪽 길이). raw_cer의 분모는 공백을 포함해 다르니 둘을 비율로 비교하지 말고, 오류 개수가 필요하면 breakdown()을 쓰세요. 결과는 항상 같습니다(결정적).

공개 모델 벤치마크

공개 한국어 ASR 7개 설정을 Zeroth, FLEURS, Common Voice 27, KsponSpeech(합계 7,418발화)에서 돌리고, 같은 출력을 네 단계로 채점했습니다. AI-Hub 전화 음성(1,936발화)에서도 따로 확인했습니다.

  • Zeroth·FLEURS·Common Voice(1,418발화) 기준으로, 기존 CER이 센 오류의 46~65%는 표기 차이였습니다. 대부분은 띄어쓰기와 문장부호입니다.
  • 정답에 이중 표기가 있는 데이터에서는 어느 쪽을 정답으로 고르느냐에 따라 띄어쓰기·문장부호를 뺀 CER이 모델마다 2.9~4.8%p(전화 음성 기준, kocer는 0.09%p 이하) 움직이고, 숫자가 든 문장에서는 두 모델 비교의 방향까지 바뀝니다(위 표). 전체 평균으로 보면 숫자 없는 문장이 많아 차이가 작아집니다.
  • 정규화가 진짜 오류를 숨기지 않는지, 기존 CER > 0이고 kocer CER = 0인 문장 100건을 직접 읽었습니다(그중 14건은 숫자 단계가 작동한 문장). 실제 오류를 숨긴 경우는 0건이었고, 1건은 띄어쓰기에 따라 뜻이 갈리는 동형이의어라 애매했습니다. 0.4.0에서는 숫자·영문 단계가 작동한 문장만 100건 다시 읽었습니다: 숨긴 오류 0건, 애매 1건(같은 유형: 일 세기 전/1세기 전).

모델별 점수, 단계별 CER, 신뢰구간, 디코딩 설정, 재현 스크립트는 benchmarks/에 있습니다. KsponSpeech와 전화 음성 결과는 한국지능정보사회진흥원(NIA)의 AI-Hub에서 제공한 '한국어 음성', '저음질 전화망 음성인식' 데이터를 활용했고, 약관상 숫자 표만 공개합니다.

모델별 kocer CER
모델 Zeroth FLEURS Common Voice 27 KsponSpeech clean / other 전화 (HR)
TeamUNIVA/qwen3_asr_1.7b_ko 2.32 4.19 5.97 6.08 / 6.46 5.69
TeamUNIVA/qwen3_asr_1.7b_ko_beta 2.42 4.25 6.05 6.80 / 7.23 9.05
BuzzASR/korean 3.08 4.28 3.88 10.06 / 9.29 5.31
openai/whisper-large-v3 2.90 4.24 5.80 11.06 / 11.85 4.97
Qwen/Qwen3-ASR-1.7B 2.90 4.25 6.61 8.69 / 8.57 10.69
SenseVoiceSmall (itn 켬) 2.40 6.81 9.68 13.26 / 13.77 21.29
SenseVoiceSmall (itn 끔) 2.41 6.76 9.72 13.07 / 13.67 21.49

단위 %, 총 오류 / 총 정답 글자. KsponSpeech와 전화는 철자 정답 기준. 전화는 AI-Hub 저음질 전화망 검증셋의 HR 분야(구직·교육 문의 통화) 1,936발화입니다. 모든 데이터셋에서 이기는 모델은 없고, 각 모델은 학습 데이터와 가까운 데이터셋에서 강합니다(BuzzASR은 Common Voice, TeamUNIVA는 KsponSpeech로 보임). 전화 음성에서는 whisper-large-v3가 가장 강했고, 낭독체(FLEURS, Common Voice)로 파인튜닝한 BuzzASR은 원래 모델인 whisper-large-v3를 넘지 못했습니다(원인은 확인하지 않음). 디코딩은 모두 greedy이고, BuzzASR을 모델카드 권장 설정(반복 억제)으로 다시 돌리면 다섯 데이터셋 모두 오히려 나빠집니다(자세히).

한계

  • 숫자와 영문 약어가 아닌 표기 차이(구어 축약, 발음대로 적은 표기)는 오류로 셉니다.
  • 영문 약어 처리는 공개 데이터에 영문이 거의 없어 효과를 검증하지 못했습니다. 효과가 확인된 건 숫자입니다.
  • 내장 약어 사전은 16개뿐입니다. 단어처럼 읽는 약어는 aliases로 넘기세요.
  • 단위는 %, 길이·넓이·부피(m, km, m2 …), 무게(g, kg, t), L, 전력(W, kWh), 용량(KBTB), 주파수(HzGHz), ℃·℉, 통화 기호 $ ₩ € £ ¥만 읽습니다. 분수는 1/2 꼴만 읽고 날짜(2026/10/29)는 읽지 않습니다. 조수사 사전도 완전하지 않습니다. tests/cases.tsv에 케이스를 추가하는 PR을 환영합니다.
  • WER은 띄어쓰기 차이를 오류로 셉니다. 한국어에서는 CER을 권합니다.
  • AI-Hub 가림 태그(@이름1, &이름&)는 aihub=True로도 지우지 않습니다. 지우면 모델이 받아쓴 실제 이름이 전부 삽입 오류가 되기 때문입니다. 그런 문장은 빼고 재세요.
  • 긴 글은 kocer[fast]로 재세요(8,200자 한 덩어리 0.03초). rapidfuzz 없이 순수 파이썬으로는 정렬이 글자 수의 제곱에 비례해서, 수천 자를 한 덩어리로 넣으면 느리고 메모리를 많이 씁니다. 그때는 문장 단위로 나눠 넣으세요.

인용과 보고

점수를 적을 때는 버전을 함께 적어 주세요. 정규화 규칙이 버전마다 바뀌어 같은 출력도 점수가 다를 수 있습니다. 0.4.0에서 분모와 후보 규칙이, 0.5.0에서 후보 탐색이 바뀌었으니 다른 마이너 버전의 점수와 섞지 마세요(CHANGELOG). 0.5.0부터 채점 규칙은 동결되어 있고, 점수가 바뀌는 수정은 마이너 버전을 올려서만 합니다. raw_cer도 같이 적으면 다른 도구로 잰 숫자와 비교할 수 있습니다.

CER 6.88% (raw) / 2.90% (kocer 0.5.0)

레포 오른쪽의 "Cite this repository"에서 인용 형식을 복사할 수 있습니다(CITATION.cff).

BibTeX, 관련 연구
@software{kocer,
  author  = {Choi, Kwan-u},
  title   = {kocer: reading-based CER/WER for Korean speech recognition},
  year    = {2026},
  version = {0.5.0},
  url     = {https://github.com/Choi-kwan-u/kocer}
}
  • jiwer: 범용 WER/CER. kocer의 cer()·wer() 시그니처가 이것을 따릅니다.
  • nlptutti: 한국어 STT 평가. 띄어쓰기·문장부호 무시, 시스템 비교 리포트, 개체명 평가.
  • Open ASR Leaderboard의 OIWER: 참조에 허용되는 철자가 여럿일 때 그중 하나와 맞으면 정답으로 치는 방식. kocer의 숫자 후보 집합은 같은 발상을 한국어 숫자·조수사에 적용한 것입니다.
  • "What is lost in Normalization?" (EMNLP 2024): Whisper식 정규화가 비영어권 문자에서 점수를 왜곡한다는 분석.
  • whisper_normalizer: Whisper 논문의 영어·기본 정규화기 구현.

라이선스

MIT


도움이 됐다면 ⭐ 스타를 눌러 주세요. 다른 한국어 STT 연구자들이 이 도구를 찾는 데 도움이 됩니다.

Metadata

Release files for kocer 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kocer 0.5.0
File Size Uploaded Provenance Actions
kocer-0.5.0.tar.gz 1.2 MB With provenance Details for kocer-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for kocer 0.5.0
File Interpreter ABI Platform Actions
kocer-0.5.0-py3-none-any.whl Python 3 none any Details for kocer-0.5.0-py3-none-any.whl

Total release size: 1.2 MB

Release files / kocer-0.5.0.tar.gz

Download URL kocer-0.5.0.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
bc2245d5aa4339073d280b900c2015a2958553dc0dd1226aa3de22d3ec42b29c
BLAKE2b-256 checksum
How to use checksums
f12b1544c5eedd7650e7f70131d619a4c0b35619ba997cc6cf82d6bdae851c55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / kocer-0.5.0-py3-none-any.whl

Download URL kocer-0.5.0-py3-none-any.whl
Size 30.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5dad4bf2e4e6f2af3ce459d78f97cf1011cb019ff802b5037d31bf38efc7318c
BLAKE2b-256 checksum
How to use checksums
c31f449076f9c3e2292b544436c864e26c22dbe18b0e439d3194275fc2219217
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for kocer 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for kocer-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page