본문 바로가기
C.W.K.
Stream
Lesson 01 of 04 · published

자기 지시문을 굶긴 브리핑

~13 min · llm, context, bugs, architecture

Level 0미분류
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

모니터링보다 출력이 먼저 알아챘어

예약된 일간 브리핑은 모형한테 하루를 조망해달라고 해. 선반이 뭘 실었는지, 열어본 기사 몇 개가 깊이 뭐라고 했는지, 소셜 네트워크 온도가 어땠는지. 절 셋, 코퍼스 섹션 셋.

어느 아침 브리핑이 지나가듯 말했어. 받은 자료에 온도 샘플이 안 들어와 있다고. 샘플은 수집됐었어. 통계는 네 개라고 했고. 코퍼스엔 없었지. 시스템 전체에서 이 결함을 처음 신고한 게 생성된 텍스트였어. 모니터링이 얼마짜리였는지 정확히 말해주는 대목이야.

딴 데서 자란 게 이걸 깨뜨렸어

조립은 평범했어. 헤드라인 섹션 짓고, 추출본, 그다음 샘플, 이어붙이고, 글자 수 상한으로 자르기. 독자한테 선반이 몇 개일 땐 그게 먹혔지. 그다음 선반이 대충 두 배가 됐고, 그 헤드라인만으로 상한 전체를 넘겼어.

샘플 수집 코드는 아무것도 안 바뀌었어. 아무것도 실패 안 했고. 마지막에 붙은 섹션이 그냥 끝에서 조용히 떨어져 나갔어. 마지막에 붙었다는 이유로. 그리고 마지막에 붙은 게 작고 유일한 것들이었지. 하필 덩치 큰 섹션이 본 행사처럼 느껴져서 먼저 쓰이니까. 꼬리 자르기는 코드 작성 순서로 우선순위를 준다는 거고, 그건 아무것도랑 상관관계가 없어.

먼저 예약하고, 남은 걸 채워

수리는 우선순위를 뒤집어. 작고 대체 불가능한 섹션을 짓고 재. 상한에서 빼. 남은 게 헤드라인 몫이고, 헤드라인이 그걸 명시적으로 채우다가 몫이 떨어지면 멈춰. 나중에 잘리는 게 아니라.

구별을 정확히 적을 값어치가 있어. 두 버전 다 상한 아래 코퍼스를 만들거든. 자르는 버전에선 상한이 어느 섹션이 존재할지 정해. 예산 버전에선 저자가 어느 섹션이 존재할지 정하고 상한은 덩치 큰 쪽이 폭을 얼마나 받을지 정하고. 같은 한도, 반대 의미야.

최후의 안전장치 자르기는 남기되, 표시해

절대적 잘라내기는 여전히 끝에 있어야 해. 예산에도 산수 버그가 있고, 딱딱한 컨텍스트 한계를 넘는 건 짧아진 코퍼스보다 나쁜 실패니까. 차이는 이제 정상 운영에선 거기 닿을 수 없어야 하고, 발동하면 문장 중간에서 끝나는 대신 눈에 보이는 표식을 붙인다는 거야. 스스로를 알리는 잘라내기는 진단이고, 조용한 건 이 강의 전체가 다루는 그 버그야.

맥락이 부족할 땐 배분이 설계 결정이니까, 결정으로 만들어. "그다음 맞게 자름"으로 끝나는 조립은 그 결정을 누군가 코드를 쓴 순서한테 위임한 거고, 제일 작고 제일 유일하고 제일 명시적으로 요구되는 섹션부터 먼저 실패할 거야.

Code

대체 불가능한 건 예약, 덩치 큰 건 예산, 최후의 자르기엔 표식·python
# BEFORE: append, then cut. The cap decides which sections exist.
corpus = header + shelves_section + extracts_section + samples_section
corpus = corpus[:CORPUS_MAX_CHARS]        # <- extracts and samples die here


# AFTER: reserve the small, irreplaceable sections; the bulky one
# fills what remains, round-robin, and stops on its own.
def build_corpus(con) -> tuple[str, dict]:
    stats = {"tabs": 0, "articles": 0, "extracts": 0, "samples": 0}

    # Small, unique, and named by clauses of the instruction -> reserved.
    samples_section = _section("X temperature", _sample_lines(con))
    extracts_section = _section("Opened in depth", _extract_lines(con))
    previous = _section("Yesterday's brief", _prior_brief(con))

    reserved = (len(CORPUS_HEADER) + len(samples_section)
                + len(extracts_section) + len(previous))
    shelf_budget = CORPUS_MAX_CHARS - reserved

    # Bulky and repetitive -> gets the remainder, ROUND-ROBIN so that
    # running out costs depth uniformly instead of erasing whole topics.
    lines, spent, dropped = [], 0, 0
    shelves = [list(s) for s in _shelf_headlines(con)]
    for rank in range(max((len(s) for s in shelves), default=0)):
        for shelf in shelves:
            if rank >= len(shelf):
                continue
            cost = len(shelf[rank]) + 1
            if spent + cost > shelf_budget:
                dropped += 1
                continue
            lines.append(shelf[rank])
            spent += cost
            stats["articles"] += 1

    stats["headlines_dropped"] = dropped      # disclosed, not hidden
    corpus = CORPUS_HEADER + "\n".join([*lines, extracts_section,
                                        samples_section, previous])
    if len(corpus) > CORPUS_MAX_CHARS:        # belt and braces, and LABELLED
        corpus = corpus[:CORPUS_MAX_CHARS] + "\n[corpus truncated]"
    return corpus, stats

External links

Exercise

네 시스템에서 내용을 조립한 다음 한도로 자르는 자리를 찾아. 프롬프트, 로그 줄, 알림, 이메일 요약 같은 거. 어느 섹션이 제일 먼저 사라질지 따져보고, 아래쪽에서 그 섹션이 있다는 데 기대는 게 있는지 확인해. 마지막으로 조립이 얼마나 떨궜는지 보고하게 만들어.
Hint
제일 먼저 사라지는 섹션은 마지막에 붙은 거고, 그건 보통 제일 최근에 추가된 거야. 그리고 최근 추가된 섹션이야말로 다른 코드가 기댈 가능성이 제일 높은 쪽이지. 누가 방금 발견한 요구사항을 만족시키려고 추가된 거니까.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.