AI가 작성한 정규표현식을 일치·불일치 예제로 검증하기
AI가 만든 정규표현식을 완성된 규칙이 아니라 초안으로 취급합니다. 작은 합성 테스트 표를 만들고 예상 결과와 실제 매칭 결과를 비교한 뒤, 수정된 패턴과 검토 보고서를 확인합니다.
AI에게 원하는 출력 구조의 예시를 먼저 보여준 뒤, 반환된 JSON을 실제 사용 전에 자동 검증합니다. 작은 합성 업무 티켓 데이터로 형식 예시와 검증 스크립트를 함께 사용하는 방법을 확인합니다.
이런 분께 맞아요반복 업무를 AI로 구조화하면서 자유 형식 문장 대신 예측 가능한 기계 판독형 출력을 얻고 싶은 사람을 위한 안내입니다.
짧은 업무 지원 티켓을 구조화된 레코드로 변환한다고 가정합니다. 각 결과에는 ticket_id, priority, owner_team, action의 네 키만 정확히 있어야 합니다. priority는 LOW, MEDIUM, HIGH 중 하나이며 owner_team은 IT, FACILITIES, FINANCE 중 하나여야 합니다. 네 값 모두 비어 있지 않은 문자열이어야 합니다.
중요한 점은 AI 응답과 별개로 출력 규칙을 먼저 정의하는 것입니다. AI는 후보 레코드를 생성하고, 실제로 요구한 구조를 만족하는지는 검증 스크립트가 판단합니다.
아래 티켓은 이 글을 위해 작성한 합성 데이터입니다. 사람이 직접 의도된 구조화 결과를 판단할 수 있도록 단순하게 구성했습니다.
| ticket_id | 합성 티켓 내용 | 예상 분류 |
|---|---|---|
| T101 | Payroll spreadsheet cannot be opened before today's payment run. | HIGH · FINANCE |
| T102 | Meeting room B light is flickering but the room is still usable. | LOW · FACILITIES |
| T103 | New employee laptop cannot connect to the office Wi-Fi. | MEDIUM · IT |
이 튜토리얼에서는 예상 action도 미리 고정합니다. T101은 Check payroll workbook access, T102는 Inspect meeting room B light, T103은 Troubleshoot laptop Wi-Fi connection입니다. 이 값들은 합성 연습을 위한 정답이며 실제 지원 업무의 일반 규칙이 아닙니다.
퓨샷 프롬프트는 새로운 입력을 주기 전에 완료된 예시를 하나 이상 보여주는 방식입니다. 아래 예시는 분류 방식뿐 아니라 정확한 JSON 구조도 보여줍니다. 실제 검사 대상 3개와는 다른 합성 티켓을 예시로 사용합니다.
Convert each ticket into a JSON object.
Rules:
- Return one JSON array only.
- Do not add explanations or Markdown.
- Use exactly these keys in every object: ticket_id, priority, owner_team, action.
- priority must be LOW, MEDIUM, or HIGH.
- owner_team must be IT, FACILITIES, or FINANCE.
Example 1 input:
Ticket ID: E001
Text: Printer on floor 2 is out of paper.
Example 1 output:
{"ticket_id":"E001","priority":"LOW","owner_team":"IT","action":"Refill or check floor 2 printer"}
Example 2 input:
Ticket ID: E002
Text: Expense approval file is unavailable before today's reimbursement deadline.
Example 2 output:
{"ticket_id":"E002","priority":"HIGH","owner_team":"FINANCE","action":"Check expense approval file access"}
Now process these tickets:
T101: Payroll spreadsheet cannot be opened before today's payment run.
T102: Meeting room B light is flickering but the room is still usable.
T103: New employee laptop cannot connect to the office Wi-Fi.
예시는 단순히 필드 이름만 보여주지 않습니다. 대문자 분류값, 짧은 action 문장, JSON 문자열 표기, 주변 설명을 넣지 않는 방식까지 보여줍니다. 따라서 원하는 출력 형태에 대한 모호함을 줄일 수 있습니다.
이 합성 연습에서의 예상 답은 아래 JSON 배열입니다. 실제 AI 응답은 검증 전에 ai_output.json으로 저장하세요. 잘못된 응답을 먼저 사람이 수정하면 안 됩니다. 원래 응답이 규칙을 따랐는지 확인하는 것이 검증기의 목적입니다.
[
{
"ticket_id": "T101",
"priority": "HIGH",
"owner_team": "FINANCE",
"action": "Check payroll workbook access"
},
{
"ticket_id": "T102",
"priority": "LOW",
"owner_team": "FACILITIES",
"action": "Inspect meeting room B light"
},
{
"ticket_id": "T103",
"priority": "MEDIUM",
"owner_team": "IT",
"action": "Troubleshoot laptop Wi-Fi connection"
}
]
객체는 정확히 3개이고 전체 필드 값은 12개입니다. 허용된 priority 세 종류가 각각 한 번씩 나오고, 허용된 owner_team 세 종류도 각각 한 번씩 나옵니다.
다음 스크립트를 check_ai_output.py로 저장하세요. JSON 문법, 배열 길이, 정확한 키, 데이터 형식, 허용 분류값, 티켓 ID, 합성 예제의 예상 분류를 검사합니다. AI 응답을 파싱한 뒤 검토용 CSV를 작성합니다.
import csv
import json
from pathlib import Path
SOURCE = Path("ai_output.json")
OUTPUT_DIR = Path("outputs") / "few_shot_check_result"
REPORT = OUTPUT_DIR / "format_check.csv"
EXPECTED = {
"T101": ("HIGH", "FINANCE", "Check payroll workbook access"),
"T102": ("LOW", "FACILITIES", "Inspect meeting room B light"),
"T103": ("MEDIUM", "IT", "Troubleshoot laptop Wi-Fi connection"),
}
REQUIRED_KEYS = {"ticket_id", "priority", "owner_team", "action"}
PRIORITIES = {"LOW", "MEDIUM", "HIGH"}
TEAMS = {"IT", "FACILITIES", "FINANCE"}
def main() -> None:
if not SOURCE.is_file():
raise FileNotFoundError(f"AI output not found: {SOURCE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
with SOURCE.open("r", encoding="utf-8") as stream:
data = json.load(stream)
if not isinstance(data, list):
raise ValueError("Top-level JSON value must be an array.")
if len(data) != len(EXPECTED):
raise ValueError(f"Expected {len(EXPECTED)} objects, got {len(data)}.")
rows = []
seen = set()
for index, item in enumerate(data, start=1):
errors = []
if not isinstance(item, dict):
raise ValueError(f"Item {index} is not a JSON object.")
if set(item) != REQUIRED_KEYS:
errors.append("keys")
for key in REQUIRED_KEYS:
if key not in item or not isinstance(item.get(key), str) or not item.get(key).strip():
errors.append(f"invalid_{key}")
ticket_id = item.get("ticket_id", "")
if ticket_id in seen:
errors.append("duplicate_ticket_id")
seen.add(ticket_id)
if item.get("priority") not in PRIORITIES:
errors.append("priority")
if item.get("owner_team") not in TEAMS:
errors.append("owner_team")
expected = EXPECTED.get(ticket_id)
if expected is None:
errors.append("unexpected_ticket_id")
else:
actual = (
item.get("priority"),
item.get("owner_team"),
item.get("action"),
)
if actual != expected:
errors.append("content_mismatch")
rows.append({
"item": index,
"ticket_id": ticket_id,
"status": "PASS" if not errors else "FAIL",
"errors": ";".join(errors),
})
missing_ids = set(EXPECTED) - seen
if missing_ids:
raise ValueError(f"Missing ticket IDs: {sorted(missing_ids)}")
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
with REPORT.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(
stream,
fieldnames=["item", "ticket_id", "status", "errors"],
)
writer.writeheader()
writer.writerows(rows)
failures = sum(row["status"] == "FAIL" for row in rows)
print(f"Objects checked: {len(rows)}.")
print(f"Passed: {len(rows) - failures}; failed: {failures}.")
print(f"Report: {REPORT.as_posix()}")
if failures:
raise RuntimeError("AI output failed one or more checks.")
if __name__ == "__main__":
main()
ai_output.json이 합성 예제의 예상 출력과 정확히 같다면 객체 3개가 모두 통과해야 합니다. 아래 콘솔 출력은 손으로 도출한 예상값이며 실제 실행 로그가 아닙니다.
Objects checked: 3.
Passed: 3; failed: 0.
Report: outputs/few_shot_check_result/format_check.csv| 문제 | 검증에서 나타나야 하는 결과 |
|---|---|
| AI가 JSON 앞에 설명 문장을 추가 | 파일 전체가 하나의 유효한 JSON 값이 아니므로 json.load가 실패합니다. |
| 객체 하나에서 priority 대신 urgency 사용 | 정확한 키 검사에 실패합니다. |
| priority가 urgent | 허용값 검사에 실패합니다. |
| T103이 두 번 등장 | 중복 ticket_id 검사에 실패하고 다른 예상 ID가 누락될 수도 있습니다. |
| JSON 구조는 맞지만 분류가 틀림 | 이 합성 연습에서는 content_mismatch가 기록됩니다. |
퓨샷 프롬프트는 지시를 명확하게 만드는 데 도움이 되지만 결정적인 출력 보장을 제공하지는 않습니다. AI 시스템, 설정, 대화 문맥, 이후 프롬프트가 달라지면 결과도 달라질 수 있습니다. 여러 번 성공했더라도 검증기를 유지하세요.
이 예제는 작은 스키마를 직접 작성한 Python 조건으로 검증합니다. 더 큰 실제 스키마에서는 정식 스키마 도구와 별도의 의미 검증이 필요할 수 있습니다. 또한 JSON이 유효하다는 것은 형식이 맞다는 뜻일 뿐이며, AI가 만든 분류 자체가 사실이나 업무적으로 올바르다는 보장은 아닙니다.
2026-09-20 · 예제 수동 검토 · 대상: Python 3.12 · 표준 라이브러리: csv, json, pathlib · 실행하지 않음
설명과 예제는 직접 작성했습니다. 관련 동작과 개념은 아래 공식 자료에서 확인할 수 있습니다.