Skip to content

feat: LLM 요청 타임아웃을 외부에서 설정 가능하도록 추가#26

Merged
serithemage merged 2 commits into
mainfrom
fix/24-configurable-llm-timeout
Apr 27, 2026
Merged

feat: LLM 요청 타임아웃을 외부에서 설정 가능하도록 추가#26
serithemage merged 2 commits into
mainfrom
fix/24-configurable-llm-timeout

Conversation

@serithemage
Copy link
Copy Markdown
Contributor

Summary

  • 원격 Ollama 서버 등 응답이 느린 환경에서 고정 타임아웃 때문에 요청이 실패하던 문제(timeout을 외부에서 설정할 수 있었으면 합니다. #24) 해결
  • 모든 LLM 프로바이더(openai/anthropic/gemini/upstage/ollama)에 동일하게 적용되는 --timeout 플래그와 HWP2MD_TIMEOUT 환경변수 추가
  • 미지정 시 기존 프로바이더별 기본값(180s/120s/60s) 그대로 유지 — 동작 변화 없음

Behavior

값 형식: Go duration 문자열 (5m, 300s, 10m30s)
우선순위: --timeout 플래그 > HWP2MD_TIMEOUT 환경변수 > 프로바이더 기본값

# 환경변수
export HWP2MD_TIMEOUT=10m
hwp2md convert document.hwpx --llm --base-url http://my.host.com:11434

# 플래그
hwp2md convert document.hwpx --llm --timeout 5m

잘못된 입력(파싱 불가, 0 이하)은 명시적 에러로 거절합니다.

Changes

File Change
internal/cli/convert.go --timeout 플래그 추가, parseLLMTimeout 헬퍼, 5개 프로바이더에 Timeout 전달
internal/cli/config.go config show 환경변수 목록에 HWP2MD_TIMEOUT 추가
internal/cli/cli_test.go parseLLMTimeout 단위 테스트 (10 케이스)
CLAUDE.md 환경변수 표 업데이트

각 프로바이더(internal/llm/*/)는 이미 Config.Timeout 필드를 받고 있어 별도 수정 불필요.

Test plan

  • go test ./... — 전체 통과 (cli, llm, parser, e2e 포함)
  • make lint — 통과
  • make fmt — 변경 없음
  • --help에서 --timeout / HWP2MD_TIMEOUT 노출 확인
  • HWP2MD_TIMEOUT=invalid → 명확한 에러 메시지 출력 확인

Closes #24

🤖 Generated with Claude Code

원격 호스트의 Ollama 서버 등 응답이 느린 환경에서 고정 타임아웃 때문에
요청이 실패하던 문제를 해결한다. `--timeout` 플래그와 `HWP2MD_TIMEOUT`
환경변수로 모든 LLM 프로바이더(openai, anthropic, gemini, upstage, ollama)에
일관되게 적용되며, 미지정 시 기존 프로바이더 기본값을 그대로 사용한다.

값은 Go 기간 형식(예: `5m`, `300s`, `10m30s`)으로 받고, 양수가 아니거나
파싱 불가능한 입력은 명시적 에러로 거절한다.

Closes #24

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex 셀프 리뷰 지적 사항을 반영한다.

- `formatWithLLM`의 unused `cmd *cobra.Command` 파라미터를 제거하고
  호출자도 `formatWithLLM(doc)`로 갱신해 dead API 표면을 정리한다.
- `parseLLMTimeout` 에러 메시지를 "Go 기간 형식이어야 합니다"에서
  "`5m`, `300s`, `10m30s` 같은 시간 형식이어야 합니다"로 자연스럽게 다듬는다.
- `config show`의 `HWP2MD_TIMEOUT` 설명을 `convert --help`/CLAUDE.md와
  같은 디테일(예시 + provider 기본값 폴백 안내)로 통일한다.
- `TestParseLLMTimeout`에 source-specific 메시지와 공백 fallback 케이스 3종을
  추가해 우선순위/메시지 품질을 함께 검증한다 (총 13 케이스).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@serithemage serithemage merged commit 0f81f20 into main Apr 27, 2026
5 checks passed
@serithemage serithemage deleted the fix/24-configurable-llm-timeout branch April 27, 2026 09:10
serithemage added a commit that referenced this pull request Apr 27, 2026
`hwp2md config set`이 이슈 #19에서 명세한 키들을 모두 처리하도록 확장하고,
`convert` 커맨드가 설정 파일을 실제로 읽어 동작에 반영하도록 wire-up 한다.
우선순위는 CLI 플래그 > 환경 변수 > 설정 파일 > 코드 기본값으로 통일한다.

추가된 설정 키:
- parser            (native, upstage)
- llm.enabled       (true/false)
- llm.provider      (openai, anthropic, gemini, upstage, ollama)
- llm.model
- llm.base_url      (URL 형식 검증)
- llm.timeout       (Go 기간 문자열, 양수)

Config 구조체에 `Parser`와 `LLM` 그룹을 추가하되, 기존 `default_provider`,
`providers.*`, `format.*` 키는 호환성 유지를 위해 그대로 남겨둔다.
실패 시 동작 차단을 피하려고 `loadAppConfig`는 파일 부재/파싱 오류 모두
DefaultConfig로 폴백한다(플래그/환경변수가 우선이므로 안전).

`llm.timeout` 키는 추가하지만, `convert.go`의 timeout 처리 wire-up은
PR #26에 의존하므로 본 PR에는 포함하지 않는다(#26 머지 후 follow-up).

Closes #19

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
serithemage added a commit that referenced this pull request Apr 27, 2026
PR #19 description에서 PR #26 머지 후 follow-up으로 약속한 마지막 결합.
`parseLLMTimeout` 시그니처에 `configVal` 파라미터를 추가해 우선순위
flag > env > config > provider default를 단일 resolver로 처리한다.
잘못된 값 입력 시 source-specific 에러("--timeout"/"HWP2MD_TIMEOUT"/
"config llm.timeout")로 어디서 들어왔는지 명확히 알린다.

테스트는 13 → 18 케이스로 확장: config 정상 fallback, env/flag와의
우선순위 교차, whitespace 폴백, source-specific 에러 검증을 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
serithemage added a commit that referenced this pull request Apr 27, 2026
* feat: config 파일을 CLI 설정 소스로 활용 (#19)

`hwp2md config set`이 이슈 #19에서 명세한 키들을 모두 처리하도록 확장하고,
`convert` 커맨드가 설정 파일을 실제로 읽어 동작에 반영하도록 wire-up 한다.
우선순위는 CLI 플래그 > 환경 변수 > 설정 파일 > 코드 기본값으로 통일한다.

추가된 설정 키:
- parser            (native, upstage)
- llm.enabled       (true/false)
- llm.provider      (openai, anthropic, gemini, upstage, ollama)
- llm.model
- llm.base_url      (URL 형식 검증)
- llm.timeout       (Go 기간 문자열, 양수)

Config 구조체에 `Parser`와 `LLM` 그룹을 추가하되, 기존 `default_provider`,
`providers.*`, `format.*` 키는 호환성 유지를 위해 그대로 남겨둔다.
실패 시 동작 차단을 피하려고 `loadAppConfig`는 파일 부재/파싱 오류 모두
DefaultConfig로 폴백한다(플래그/환경변수가 우선이므로 안전).

`llm.timeout` 키는 추가하지만, `convert.go`의 timeout 처리 wire-up은
PR #26에 의존하므로 본 PR에는 포함하지 않는다(#26 머지 후 follow-up).

Closes #19

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: parseLLMTimeout에 config llm.timeout fallback 추가

PR #19 description에서 PR #26 머지 후 follow-up으로 약속한 마지막 결합.
`parseLLMTimeout` 시그니처에 `configVal` 파라미터를 추가해 우선순위
flag > env > config > provider default를 단일 resolver로 처리한다.
잘못된 값 입력 시 source-specific 에러("--timeout"/"HWP2MD_TIMEOUT"/
"config llm.timeout")로 어디서 들어왔는지 명확히 알린다.

테스트는 13 → 18 케이스로 확장: config 정상 fallback, env/flag와의
우선순위 교차, whitespace 폴백, source-specific 에러 검증을 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: TestRunConfigSet_NewKeys에 USERPROFILE 격리 추가

Windows의 os.UserHomeDir()은 HOME이 아닌 USERPROFILE을 보므로
t.Setenv(\"HOME\", tmpHome)만으로는 격리되지 않아 진짜 user home에
config 파일을 만들고, 같은 runner의 e2e 테스트가 그 파일을 읽어
LLM Stage 2(upstage)를 켜면서 UPSTAGE_API_KEY 부재로 실패했다.

HOME과 USERPROFILE을 모두 tmpDir로 redirect해 OS와 무관하게
격리되도록 한다.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

timeout을 외부에서 설정할 수 있었으면 합니다.

1 participant