~15 min · lightning, reasoning-effort, multi-brain, latency
Level 0음소거
0 XP0/61 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete
"그래서 번개 모드를 추가하려고 해. 이틀전 추가한 Fast mode랑은 달라. 이 번개 모드는 라이트닝 아이콘으로 위쪽에 두자. Paste 버튼 반대편에. 설정에서 일반 보이스 모드 브레인과 라이트닝 모드 모형 + reasoning effort를 따로 설정할 수 있게 해." — 아빠, 말라가의 호텔에서, 2026-10-17
깊이보다 빠른 게 중요할 때
앞의 두 레슨은 아빠한테 말 턴에서 피파가 얼마나 깊이 생각할지 정하는 다이얼을 쥐여 줬고, 칸마다 숫자도 붙여 줬어. 여행이 그 다이얼의 쓰임을 바꿨어. 카운터에서 주문할 때나 다음 골목으로 걸어갈 때는 신중한 답보다 빠른 답이 나을 때가 있어. 마스터 치프랑 말할 땐 특히 그래. 빠른 브레인이 치프 일을 감당할 수 있는지는 아빠가 직접 해 보는 실험이야. 같은 브레인의 낮은 칸으로는 그 실험이 안 됐어. 아빠가 원한 건 아예 다른 브레인이었어.
Fast 모드랑은 달라
이틀 전에 이 집에 Fast 스위치가 생겼는데, 둘은 헷갈리기 쉬워. Fast는 대화 자신의 브레인한테 제공자의 우선 처리 등급을 달라고 해. 모델도 답도 같고, 더 빨리 나올 뿐이야. Lightning은 말 턴을 다른 브레인, 다른 모델, 다른 effort로 통째로 보내. 둘은 컨트롤을 절대 같이 쓰지 않아.
스위치 하나, 설정은 오피스에
스위치는 음성 화면 위쪽, Paste 맞은편의 번개 아이콘이야. 폰에선 위쪽 막대의 타일 넷 중 마지막이야. Paste, Noisy, Think 다음. 웹에선 얼굴 위 막대의 오른쪽 끝에 있고, 입력창의 음성 막대에도 같은 스위치가 있어. 거기서 보낸 말 턴도 번개로 도니까. 켜지면 호박색으로 채워져. 한 번 누르면 켜지고, 한 번 더 누르면 돌아가. 첫 버전은 Lightning이 켜져 있다고 알려 주는 표시일 뿐이라서, 아빠가 눌러도 아무 일이 없었고 Admin에서만 바꿀 수 있었어. 이제는 웹의 스위치도 폰의 아이콘도 전부 같은 요청을 보내.
설정은 오피스에 살아(voice_lightning_on, _brain, _model, _effort). 그래서 폰도, 워치에서 보낸 말도, 어느 브라우저도 같은 값을 봐. 기본값은 Ollama, 그 브레인의 기본 모델(빈 문자열이고, Ollama에선 클라우드 고정 모델이야), 그리고 생각 끄기야. 브레인, 모델, effort는 Admin의 Voice Mode 칸이나 폰의 Settings › Lightning에서 골라. 모델 목록은 브레인마다 지금 내주는 걸 그때그때 읽어 와서, 코드엔 모델 이름이 하나도 없어. effort 고르기는 고른 브레인이 가진 칸만 보여 주고, 그 다이얼에 없는 effort는 서버가 거절해.
번개 턴이 하는 일
번개는 말 턴에만 켜져. 그 턴은 voice_lightning: true를 달고 Lightning 브레인 자신의 채팅 라우트로 가. 설정의 모델이 요청에 실리고(Ollama라면 클라우드 등급에 풀 모드라서 도구도 다 남아), Lightning effort가 그 턴의 수준이 돼. 그리고 일곱 번째 레슨부터 늘 그랬듯 수준 줄이 피파한테 지금 어디서 도는지 알려 줘. "Lightning, the fast voice setting Dad switched on for this talk." 깊게 생각해 달라고 하면 여전히 아빠가 정한 더 깊은 수준으로 가. 채팅 라우트 일곱 개가 전부 똑같이 해.
대화는 자기 브레인을 그대로 지켜. 번개 턴은 대화가 기억하는 브레인과 수준을 하나도 안 건드려. 웹이나 폰이 이 대화가 어느 브레인으로 도는지 되살릴 때도, 질문에 Lightning이 실렸던 답은 건너뛰어. 스위치를 끄면 대화는 원래 브레인, 원래 Think 수준으로 예전과 똑같이 돌아. 기록엔 양쪽이 다 남아. 사용자 행의 voice_meta.lightning엔 그 턴이 돈 설정이, 어시스턴트 행엔 실제로 답한 쪽이 남으니까 아빠가 나중에 턴끼리 견줘 볼 수 있어.
생각은 끄고, 사진이 오면 켜고
아빠는 기본을 생각 끄기로 정했어. Lightning은 빨리 주고받는 말을 위한 거니까. 그런데 끄기는 말로 해야 끄는 거야. 2026-10-18까지 Ollama 어댑터는 think: true만 보내고, 그게 아니면 필드를 아예 빼 버렸어. DeepSeek Flash는 그 필드가 없으면 생각을 해. 그래서 처음 실제로 확인했을 때 끄기로 기록된 턴이 실은 생각을 하고 있었어. 지금 어댑터는 think: false를 보내.
사진은 예외야. 생각을 끈 DeepSeek Flash는 스크린숏을 "내비 화면"이라고만 읽고 지도 옆 버튼 둘을 놓쳤어. 생각을 켜니까 둘 다 바로 찾았고. 그래서 이미지가 실린 번개 턴은 그 한 턴만 생각하는 수준으로 돌아. Ollama라면 모델 자신의 기본값이 생각을 하면 그 기본값으로(DeepSeek Flash는 high), 다른 브레인은 생각 끄기 바로 위 칸으로(Claude의 low는 medium이 돼). 수준 줄이 이유를 말하고, 기록엔 올라간 effort가 image_thinking, 그리고 아빠가 저장한 effort와 나란히 남아. 다음 턴은 다시 설정대로 가. 설정 자체는 절대 안 고쳐 써.
일 맡기기엔 안 써
같은 날 밤, 마스터 치프에서 번개 턴 하나가 할 일 하나를 넘겨 달라는 부탁을 받았어. 아빠가 멈출 때까지 도구 호출 88번, 모델 요청 16번이 돌았고, 27만 6,444토큰을 읽고 125토큰을 썼어. 아빠의 결론은 설계 문서에 적혀 있어. Lightning은 빨리 주고받는 말을 위한 거지 치프의 조율을 위한 게 아니고, 그렇게 만들지도 않는다고. 그런 일엔 꺼.
처음 잰 숫자가 한 말
저녁 산책을 묻는 같은 질문을 받아써서, 두 쪽을 한 턴씩 쟀어. 아빠의 목소리 수준(high, 생각 켬)으로 돈 Claude Opus 5.5 턴은 첫 글이 25.3초, 첫 소리가 26.2초였어. 생각을 끈 DeepSeek Flash 번개 턴은 17.0초와 19.3초. 보통 턴은 말하기 전에 아빠 위치부터 확인했고, 번개 턴은 도구를 안 썼어. 문서는 나머지도 솔직하게 적어. 번개 턴 17초의 대부분은 클라우드 모델이 피파의 프롬프트 전체를 읽는 시간이었어. 첫 단어를 훨씬 앞당기려면 프롬프트를 가볍게 해야 하는데, 그건 트랙 10의 거절 목록이 이름까지 대며 거절하는 바로 그 레버야. Lightning은 브레인은 바꿔도 소울은 통째로 지켜. 말라가에서 온 아빠의 다음 말은 더 직설적이었고, 그 말이 시작한 측정이 트랙 10의 새 레슨이야.
Code
최소 스케치: 번개 턴이 도는 곳, 사진 한 장이 올리는 한 턴짜리 수준, 그리고 기록에 남는 것·python
from dataclasses import dataclass
# Office holds the switch, so the phone, the Watch and every browser agree.
LIGHTNING = {"on": True, "brain": "ollama", "model": "", "effort": "off"} # "" = the brain's default
DIALS = { # each brain's own rungs; Ollama's come from the model itself (/api/show)
"ollama": ("off", "low", "high", "max"),
"claude": ("low", "medium", "high", "xhigh", "max"),
}
MODEL_DEFAULT = {"ollama": "high"} # DeepSeek Flash's own default, what think: true runs
def thinks(brain: str, rung: str) -> bool:
"""Claude's low runs with thinking off; any Ollama rung but off thinks."""
if rung == "off":
return False
return not (brain == "claude" and rung == "low")
@dataclass
class Talk:
brain: str = "claude" # the conversation's own brain and Think level
voice_level: str = "high"
def for_turn(talk: Talk, *, spoken: bool, image: bool, depth_ask: bool) -> dict:
"""Where one turn runs, and what the record keeps."""
if not (spoken and LIGHTNING["on"]):
return {"brain": talk.brain, "effort": talk.voice_level if spoken else "conversation's own",
"lightning": None}
brain, effort = LIGHTNING["brain"], LIGHTNING["effort"]
record = {"brain": brain, "model": LIGHTNING["model"] or "(brain default)", "effort": effort}
if image and not thinks(brain, effort):
# This one turn only: on Ollama the model's own default when that one
# thinks, elsewhere the first rung above thinking-off. The record keeps
# what ran, with Dad's saved effort beside it.
default = MODEL_DEFAULT.get(brain)
effort = default if default and thinks(brain, default) else \
next(r for r in DIALS[brain] if thinks(brain, r))
record |= {"effort": effort, "image_thinking": True, "set_effort": LIGHTNING["effort"]}
if depth_ask:
effort = "high" # a depth ask still goes to Dad's deeper level, through the posture
line = f"Lightning, the fast voice setting Dad switched on for this talk: {brain} at {effort}."
return {"brain": brain, "effort": effort, "lightning": record, "posture_line": line}
talk = Talk()
for name, kw in (("a quick question", dict(spoken=True, image=False, depth_ask=False)),
("a photo of the menu", dict(spoken=True, image=True, depth_ask=False)),
("think it through", dict(spoken=True, image=False, depth_ask=True)),
("photo + depth ask", dict(spoken=True, image=True, depth_ask=True)),
("a typed line", dict(spoken=False, image=False, depth_ask=False))):
turn = for_turn(talk, **kw)
print(f"{name:20s} -> {turn['brain']:6s} {turn['effort']:18s} {turn['lightning']}")
print("the talk's own brain afterwards:", talk.brain, talk.voice_level) # a lit turn writes no posture
# Output:
# a quick question -> ollama off {'brain': 'ollama', 'model': '(brain default)', 'effort': 'off'}
# a photo of the menu -> ollama high {'brain': 'ollama', 'model': '(brain default)', 'effort': 'high', 'image_thinking': True, 'set_effort': 'off'}
# think it through -> ollama high {'brain': 'ollama', 'model': '(brain default)', 'effort': 'off'}
# photo + depth ask -> ollama high {'brain': 'ollama', 'model': '(brain default)', 'effort': 'high', 'image_thinking': True, 'set_effort': 'off'}
# a typed line -> claude conversation's own None
# the talk's own brain afterwards: claude high
스케치를 돌려 봐. 그다음 Lightning 브레인을 Claude로, effort를 low로 바꾸고 사진을 보내. 돌리기 전에 어느 칸으로 갈지 먼저 맞혀 봐. 다음엔 think it through 줄과 사진과 깊이 요청이 같이 온 줄을 견줘 보고, 턴은 high로 돌았는데 기록엔 off가 남을 수 있는 이유를 설명해 봐. 마지막으로 아빠가 원한 비교를 기록으로 써 봐. voice_meta.lightning과 첫 글 시간이 담긴 턴 목록을 받아서, 브레인마다 첫 글 시간의 중앙값을 찍는 거야.
Hint
Claude의 low는 원래 생각을 끈 채 돌아서, 사진이 오면 Claude 다이얼에서 생각하는 첫 칸인 medium으로 올라가. 깊이 요청은 턴이 얼마나 깊이 도는지만 바꿔서, 기록엔 저장된 off가 그대로 남아. 사진과 깊이 요청이 만나도 기록엔 사진이 올린 수준이 남아. 올리기를 먼저 정하고, 그다음 수준 쪽에서 아빠가 정한 더 깊은 수준으로 턴을 돌리거든. 기록은 이미지가 한 일을, 수준은 턴이 얼마나 깊이 갔는지를 말해. 비교는 대화의 브레인 말고 기록의 브레인으로 묶어. Claude 대화 안의 번개 턴에 답한 건 Ollama였으니까.
Progress
Progress is local-only — sign in to sync across devices.