트렌딩 딥다이브 · 2026-07-18 · OSSInsight 24h #6

FB208/OpenBidKit_Yibiao 딥다이브
— AI가 10만~100만 자 입찰서(標書)를 써 내려가는 오픈소스 데스크톱 에이전트

OpenBidKit(易标, 이뱌오)"공고문(招標문서)만 던지면, 목차를 뽑고 → 장(章)별로 본문을 쓰고 → 표·다이어그램·그림까지 배치해 → 완성된 Word 입찰서를 만들어 주는" Electron 데스크톱 앱이다. 핵심 목표는 하나다 — "한 부에 수십 위안씩 하는 유료 AI 입찰서 도구를, 완전 오픈소스·로컬·저비용으로 대체한다"(개발자 표현: "투standing 영역의 OpenClaw"). 실제로 DeepSeek V4 Flash로 10만 자 입찰서를 뽑는 데 약 1위안이 든다고 주장한다. 다만 이 문서가 파고드는 진짜 가치는 "입찰서"가 아니다. 이 저장소는 "약한 모델로도 복잡한 JSON을 안정적으로 뽑는 법", "프롬프트 순서를 바꿔 입력 비용을 10배 줄이는 법", "수십만~백만 자 장문을 일관성 있게 생성하는 법", "RAG 없이 지식베이스를 쓰는 법"이라는, LLM 애플리케이션 엔지니어링의 실전 노하우가 코드와 연재 글(문장 7편)로 함께 담긴 드문 표본이다. (저장소: FB208/OpenBidKit_Yibiao · Electron+React+TypeScript · AGPL-3.0 · 클라이언트 v0.1.0 · 최신 커밋 47aba16(2026-07-16, PR#154) · 공식 사이트 yibiao.pro · 이번 회차는 TrendShift Daily·Weekly·Monthly가 모두 기분석 소진되어 OSSInsight 순위로 폴백)
목차
  1. 프로젝트 한 줄 요약
  2. 왜 지금 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 — LLM 엔지니어링 4대 노하우
  7. 시스템 요구사항 · 설치
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한 줄 요약

"입찰서를 써 주는 AI 에이전트" — 공고문 파싱 → 목차 생성 → 장별 본문 → 도표·삽화 → Word 내보내기까지 전 과정을 로컬에서

FB208/OpenBidKit_Yibiao(중국어명 易标投标工具箱, "이뱌오 입찰 도구상자")는 기업이 입찰(招投標)에 낼 기술제안서·상용제안서 같은 "표준 입찰서(標書)"를 AI로 자동 작성해 주는 오픈소스 데스크톱 애플리케이션이다. 저장소가 내건 한 줄은 이것 — "开箱即用-开源免费AI标书编写工具"(개봉 즉시 쓰는, 오픈소스·무료 AI 입찰서 작성 도구).

동작의 큰 그림은 "공고문 한 부 → 완성된 입찰서 한 부"다. 사용자가 초대·공고 문서(招標文件)를 넣으면, 앱이 ① 프로젝트 개요와 기술 평가(배점) 요구를 뽑아내고 → ② 그 배점에 맞춘 입찰서 목차(3단 트리)를 만들고 → ③ 목차의 말단(잎) 노드마다 본문을 병렬로 채우고 → ④ 적절한 곳에 표·Mermaid 도표·AI 삽화를 배치하고 → ⑤ 전부 이어 붙여 Word(.docx)로 내보낸다. 이 과정에서 회사 자료를 담아 둔 지식베이스를 재료로 쓰고, 다 쓴 뒤엔 표절 검사(査重)폐찰(廢標) 위험 항목 검사까지 돌려 준다.

핵심 용어 · 이게 뭐냐
標書(표서, 입찰서) = "이 사업 저희에게 맡겨 주세요"라는 공식 제안 문서
공공·기업 입찰에서 발주처가 공고문(招標文件)으로 "이런 일을 할 업체를 찾는다, 이런 기준으로 채점한다"를 내면, 참여 업체는 입찰서(投標文件/標書)로 "우리가 이렇게 하겠다"를 제출한다. 특히 기술제안서(技術標)는 수십~수백 페이지에 달해, 작성에 며칠씩 걸리는 노동집약 문서다. OpenBidKit은 바로 이 장문 문서 생성을 AI로 자동화하는 것이 목표다.
핵심 용어 · 정체성
"데스크톱 앱 + 로컬 우선" — 브라우저 SaaS가 아니라 내 컴퓨터에서 도는 프로그램
OpenBidKit은 웹 서비스가 아니라 Electron으로 만든 설치형 데스크톱 앱이다. 설정·캐시·생성 결과·지식베이스가 전부 내 PC의 로컬 SQLite와 파일에 저장된다. AI 호출만 외부 모델 API(또는 로컬 Ollama)로 나간다. 입찰서는 대외비 성격이 강해 "클라우드에 올리기 싫다"는 수요가 크기 때문에, 이 로컬 우선 설계가 셀링 포인트다.
한 문장 비유

"혼자 3일 밤새우던 제안서를, 목차부터 삽화까지 대신 채워 주는 AI 대필 작가 + 편집 데스크"

입찰서 작성은 공고문을 읽고 → 목차를 잡고 → 각 장을 쓰고 → 표와 그림을 넣고 → 형식을 맞추는, 지루하고 반복적인 장문 노동이다. 사람이 하면 며칠, 유료 AI 툴에 맡기면 한 부에 수십 위안이 든다.

OpenBidKit은 이 전 과정을 하나의 작업 파이프라인으로 자동화한 "대필 데스크"다. 당신은 공고문을 올리고 몇 가지 선호(그림 몇 장·표 성향 등)만 정하면, AI가 목차를 짜고 본문을 병렬로 쓰며 도표·삽화까지 배치한다. 게다가 이 모든 걸 당신이 고른 모델(비싼 GPT든 값싼 DeepSeek이든 로컬 Ollama든)로, 당신 PC 안에서 돌린다.

2왜 지금 주목받는가

"장문 생성 + 저비용 + 로컬"이라는 실수요 조합 — 그리고 코드보다 값진 "연재 노하우"

OpenBidKit이 트렌딩에 오른 힘은 두 겹이다. 표층은 "유료 입찰서 AI가 비싸다"는 명확한 페인포인트를 오픈소스로 정면 공략했다는 점이고, 심층은 개발자가 제작 과정을 7편의 기술 연재로 공개해 "어떻게 만들었나"가 통째로 드러난다는 점이다. 후자가 이 저장소를 단순 앱이 아니라 LLM 엔지니어링 교재로 만든다.

포인트내용
정체AI 입찰서 작성 데스크톱 앱. Electron 41 + React 19 + TypeScript 5.9 + Vite 7. 렌더러(UI) + 메인(비즈니스 로직·SQLite·AI·작업) 구조. TS/TSX 약 23,000줄, Electron 메인 로직 .cjs 85개.
차별점 ①"장문 일관성" 정면 돌파. 목차 잎 노드 단위 병렬 생성 + 전역 사실(globalFacts) 주입으로 10만~100만 자 문서의 앞뒤 모순을 억제.
차별점 ②약한/값싼 모델도 안정 출력. 프롬프트에만 기대지 않고 "생성→검증→수리→재시도→분할→AI 심사→재생성" 워크플로로 복잡한 목차 JSON을 안정화(OpenCode의 자기반성 기법 차용).
차별점 ③비용 설계가 1급 관심사. 프롬프트 순서를 재배열해 서비스사 Prompt Cache를 명중시켜 입력 비용을 최대 10배 절감. "10만 자에 약 1위안"이라는 수치의 근거.
차별점 ④모델 선택 자유 + 로컬. GPT·DeepSeek·火山方舟(Volcano Ark)를 심층 적응, OpenAI 호환이면 무엇이든, Ollama·LM Studio로 로컬 모델까지. 데이터는 로컬 SQLite에.
주의할 맥락범용 도구가 아니다. 중국 입찰(招投標) 실무에 최적화됐고, 라이선스는 AGPL-3.0(강한 카피레프트)이며, 문서·UI가 대부분 중국어다. (§10 함정 참조)

주목 포인트 1 — "장문 생성"이라는, 챗봇과 다른 전장

일반 챗봇은 몇 백~몇 천 자 답을 낸다. 입찰서는 수십만 자다. 이 스케일에선 완전히 다른 문제가 튀어나온다 — 앞 장과 뒤 장이 서로 모순되고("우리 팀은 5명" vs 뒤에서 "8명"), 목차 JSON이 한 번만 깨져도 전체 파이프라인이 멈추며, 같은 공고문을 매 장마다 다시 넣느라 입력 토큰 비용이 폭발한다. OpenBidKit의 설계 대부분은 바로 이 "장문 3대 난제(일관성·안정성·비용)"를 푸는 데 바쳐져 있다.

주목 포인트 2 — 코드 + 연재 글이라는 "이중 교재"

저장소 안 文章/ 폴더에는 "标书智能体(입찰서 에이전트)" 연재 1~7편이 마크다운으로 들어 있다. 각 편이 실전 주제를 정면으로 다룬다 — 공고문 파싱, 목차 생성, 본문 생성, 프롬프트 순서·캐시(비용 10배↓), 약한 모델 복잡 JSON 안정화, 초장문+도표 제어, RAG 없는 지식베이스. 개발자 스스로 "vibe coding 시대엔 코드보다 문제를 푸는 사고(프롬프트·워크플로·에이전트 설계)가 중요하다"고 못박는다. 즉 이 저장소는 "무엇을 만들었나"보다 "어떻게 사고했나"를 배우기에 좋다.

경쟁 구도 · OpenBidKit은 어디에 서 있나

vs 유료 입찰서 SaaS — 페인포인트를 정확히 겨냥한 대상. 한 부에 수십 위안 vs "10만 자에 약 1위안". 대신 품질·안정성은 당신이 고른 모델과 설정에 달렸다.

vs 범용 문서 AI(ChatGPT에 복붙) — 챗봇은 장문 일관성·목차 구조·도표 배치·Word 서식을 손수 관리해야 한다. OpenBidKit은 그 전 과정을 파이프라인으로 묶었다.

vs 자체 스크립트 — 직접 짜려면 이 문서의 §6에 나오는 4대 난제를 전부 재발명해야 한다. OpenBidKit은 그 해법이 이미 코드로 들어 있는 참조 구현이다.

vs OpenCode(코딩 에이전트) — 경쟁이 아니라 내부 부품. OpenBidKit은 OpenCode 런타임을 벤더링해 에이전트 엔진으로 품고, 그 위에 "입찰서"라는 도메인을 얹었다.

3기술 스택 전체 지도

Electron "메인 ↔ 렌더러" 두 세계 — 렌더러는 React 19 기능 슬라이스, 메인은 SQLite·AI·작업 엔진(.cjs)

OpenBidKit은 전형적인 Electron 이중 구조다. 렌더러(renderer)는 사용자가 보는 화면으로 React 19 + TypeScript + Vite 7이 담당하고, 메인(main) 프로세스는 화면 뒤의 무거운 일 — 파일 파싱, AI 호출, SQLite 저장, 장시간 작업 관리 — 을 Node.js(.cjs 모듈)로 처리한다. 둘은 IPC 브리지(window.yibiao)로만 대화한다. 이 분리를 이해하면 코드 전체가 한눈에 잡힌다.

핵심 용어 · Electron 이중 구조
렌더러(화면) ↔ IPC 브리지 ↔ 메인(엔진)
렌더러는 브라우저 같은 샌드박스라 파일·네트워크를 직접 못 만진다. 그래서 "AI를 불러 줘", "파일을 열어 줘" 같은 요청을 IPC(프로세스 간 통신)메인에 넘기고, 메인이 실제 일을 한 뒤 결과를 돌려준다. OpenBidKit에선 preload.cjswindow.yibiao.ai.chat(...) 같은 안전한 창구만 노출하고, 진짜 로직은 전부 electron/services/에 있다. "UI와 엔진의 물리적 분리"가 이 앱의 뼈대다.

렌더러 — React 19 기능 슬라이스(feature-sliced)

UI는 client/src/ 아래 기능(feature) 단위로 잘려 있다. 입찰 워크플로의 각 단계가 곧 하나의 폴더다. 공통 부품(AI 클라이언트·프롬프트·마크다운·UI·타입)은 shared/에 모여 있다.

영역 · 버전역할
react ^19.1.1 · react-dom ^19.1.1UI 프레임워크(최신 React 19)
vite ^7.1.7 · @vitejs/plugin-react ^5개발 서버·번들러(HMR)
typescript ^5.9.2전면 타입스크립트
@radix-ui/react-* (dialog·popover·toast·tooltip 등)접근성 갖춘 헤드리스 UI 프리미티브
mermaid ^11.14.0본문 다이어그램 — 텍스트로 순서도·구조도를 그려 삽화로
markdown-it (+cjk-friendly·task-lists)생성 결과 마크다운 렌더링(중일 문자 친화)

메인 — 파싱·AI·저장·작업의 엔진실

메인 프로세스(client/electron/)가 진짜 무게중심이다. 문서를 마크다운으로 바꾸고, AI를 부르고, SQLite에 쓰고, 오래 걸리는 작업을 관리한다.

영역 · 버전역할
better-sqlite3 ^12.10.0로컬 워크스페이스 DBworkspace/yibiao.sqlite. 동기식 고속 SQLite
mammoth ^1.12 · pdf-parse ^2.4 · pdfjs-dist ^5.7공고문 파싱 — Word(.docx)·PDF에서 텍스트 추출
xlsx ^0.18 · cfb ^1.2엑셀·복합 문서(구형 .doc/OLE) 파싱
chardet ^2.1 · iconv-lite ^0.7인코딩 감지·변환(중국어 GBK 등 깨짐 방지)
cheerio ^1.2 · turndown ^7.2 (+gfm)HTML → 마크다운 정규화(웹/서식 문서 처리)
docx ^9.6.1Word 내보내기 — 완성 입찰서를 .docx로. 표·이미지·목차 포함
undici ^7.25고성능 HTTP 클라이언트(AI API 호출)
image-size ^2.0 · adm-zip ^0.5이미지 치수 계산 · 압축(리소스·삽화 처리)

패키징 · 벤더링된 OpenCode

배포는 electron-builder로 Windows(NSIS·zip)·macOS(dmg, x64+arm64) 설치본을 굽는다(appId: com.yibiao.openbidkit). 특이점은 extraResourcesOpenCode 런타임을 통째로 벤더링(vendor/opencode)한다는 것 — 즉 이 앱은 내부에 코딩 에이전트 엔진을 하나 품고 있다(§4에서 상술).

핵심 용어 · 火山方舟(Volcano Ark)
바이트댄스(ByteDance)의 모델 서비스 플랫폼
OpenBidKit이 GPT·DeepSeek과 함께 "심층 적응"했다고 밝힌 세 번째 플랫폼. 삽화 생성에 이 플랫폼의 doubao-seedream-5.0(이미지 모델)을 쓴다. 그 외 OpenAI 호환 API면 무엇이든 연결되고, Ollama·LM Studio로 로컬 모델도 붙는다 — "모델 종속 없음"이 설계 원칙이다.

4아키텍처 심화 분석

"공고문 → 목차 → 본문 → 삽화 → Word" 파이프라인, 그리고 그 밑을 받치는 작업(Task) 엔진과 OpenCode 런타임

OpenBidKit의 심장은 단계별 작업(Task) 파이프라인이다. 각 단계가 electron/services/의 독립 서비스이고, 결과는 로컬 SQLite와 파일에 낙점(落點)돼 페이지를 옮겨도 진행이 복구된다. 아래가 전체 흐름이다.

┌─────────────── 렌더러 (React 19, client/src) ───────────────┐ │ features/ technical-plan · knowledge-base · duplicate-check │ │ rejection-check · business-bid · export-format ... │ │ shared/ ai(aiClient) · prompts · markdown · ui · types │ └───────────────────────────┬───────────────────────────────────┘ window.yibiao (IPC 브리지, preload.cjs) ┌───────────────────────────▼───────────────────────────────────┐ │ 메인 프로세스 (Electron, client/electron) │ │ │ │ [1] 공고문 파싱 fileService → doc2markdown/convert.mjs │ │ (mammoth/pdf-parse/xlsx/cheerio, 선택: MinerU) │ │ [2] 공고 분석 bidAnalysisTask → 개요·기술배점 추출 │ │ [3] 목차 생성 outlineGenerationTask (3단 트리 JSON) │ │ └ 검증·수리·재시도·분할·AI 심사 워크플로 (§6-②) │ │ [4] 전역 사실 globalFactsTask → 전체 일관성 앵커 │ │ [5] 본문 편성 contentGenerationTask (잎 노드 병렬 생성) │ │ [6] 삽화 편성 contentIllustrationPlanning → ...Generation │ │ (mermaid · doubao-seedream · nano banana pro) │ │ [7] 검사/내보내기 duplicateCheck · rejectionCheck · export(docx)│ │ │ │ 저장: sqliteDatabase(better-sqlite3, user_version=17) │ │ AI : aiService / agentService → OpenCode 런타임(벤더링) │ └────────────────────────────────────────────────────────────────┘

이 파이프라인을 떠받치는 세 가지 핵심 설계를 뜯어보자.

설계 ① 낙점 가능한 작업(Task) 엔진 — "끊겨도 이어서"

입찰서 생성은 수십 분씩 걸리는 장시간 작업이다. 그래서 각 단계(*Task.cjs)는 진행 상태를 SQLite에 계속 낙점한다. taskService가 이들을 관리하고, SQLite 스키마의 PRAGMA user_version = 17이 말해 주듯 17차례의 마이그레이션을 거치며 "다중 표단(標段)", "다중 공고문", "전문 삽화 편성" 같은 기능이 점진적으로 쌓여 왔다. 원문(공고문 마크다운)은 SQLite에 넣지 않고 userData/workspace/ 파일로 두고, DB엔 경로·해시·글자수만 저장하는 "큰 텍스트는 파일, 메타는 DB" 분리가 인상적이다.

설계 ② 장문 일관성 — 목차 잎 노드 병렬 + 전역 사실 앵커

본문은 목차 트리의 말단(잎) 노드 단위로 병렬 생성된다(contentGenerationTask). 병렬로 쓰면 빠르지만 장끼리 모순이 생기기 쉽다. 그래서 먼저 globalFactsTask전역 사실(회사 규모·프로젝트명·핵심 수치 등)을 뽑아 앵커로 삼고, 각 노드 생성 시 이 앵커를 함께 주입해 앞뒤 일관성을 붙든다. 삽화도 "본문 다 쓰고 나서"가 아니라 본문 생성 전에 미리 편성(预编排)한다 — 어느 노드에 표/Mermaid/AI그림을 넣을지 점수를 매겨 상위 몇 개만 고르는 식이라, 비용이 예측 가능하고 그림이 앞 장에만 몰리지 않는다.

설계 ③ 벤더링된 OpenCode 런타임 — 앱 속의 에이전트 엔진

electron/services/opencode/OpenCode(코딩 에이전트)를 로컬 런타임으로 감싼 층이다. opencodeServerRunner가 프로세스를 띄우고, aiServiceOpenAiProxyOpenAI 호환 프록시로 붙으며, opencodeIsolationService가 격리, opencodeSelfCheckService가 자기 점검(自检)을 담당한다. 즉 OpenBidKit은 "입찰서"라는 도메인 로직을, 검증된 에이전트 런타임 위에 얹은 셈이다. §6-②의 "약한 모델 JSON 안정화"가 OpenCode의 자기반성·교정(self-reflection) 기법을 차용한 것도 이 통합 덕이다.

읽는 재미 · IPC의 얇은 창구
렌더러의 aiClient는 딱 두 줄이다
shared/ai/aiClient.tschat()requestJson() 두 메서드가 전부고, 실제 구현은 window.yibiao.ai.*(IPC 브리지)로 넘긴다. "복잡한 AI 로직은 전부 메인에, 렌더러는 얇은 호출만" — 이 규율이 코드를 깔끔하게 유지한다. requestJson이 별도로 있는 이유는, 입찰서 파이프라인에서 "신뢰 가능한 JSON"이 그만큼 중요하기 때문이다(§6-②).

5디렉토리 구조 해부

앱 코드는 client/ 한 곳 — 그리고 지식의 보고 文章/(연재 7편)

저장소는 앱 코드(client/)와 문서·자료가 명확히 갈린다. 특히 文章/(문장) 폴더는 이 저장소를 교재로 만드는 핵심이니 꼭 열어 보자.

OpenBidKit_Yibiao/ ├── README.md / README.en.md (중/영), LICENSE(AGPL-3.0), NOTICE ├── 文章/ ★ "标书智能体" 연재 1~7편 (LLM 노하우) │ ├── (一) AI로 공고문 파싱 (二) 목차 생성 코드+프롬프트 │ ├── (三) 본문 생성 (四) 프롬프트 순서→캐시, 비용 10배↓ │ ├── (五) 약한 모델의 복잡 JSON 안정화 (六) 초장문 생성 + 도표 제어 │ └── (七) 지식베이스: 당신에겐 RAG가 필요 없다 ├── 使用说明/ 사용 설명(설정·사용·업데이트 로그·이미지) ├── sql/workspace_schema.sql SQLite 목표 스키마(user_version=17, 읽기용) ├── analytics/ 방문/사용 분석(worker·dashboard·scripts) ├── screenshots/ 데모 스크린샷·배너 └── client/ ← 실제 앱 (Electron + React) ├── package.json (yibiao-client v0.1.0) vite.config.ts tsconfig ├── electron/ ← 메인 프로세스 (Node, .cjs 85개) │ ├── main.cjs · preload.cjs 앱 진입 · IPC 브리지 │ ├── ipc/ aiIpc · knowledgeBaseIpc · taskIpc · exportIpc ... │ ├── services/ ★ 엔진실 │ │ ├── bidAnalysisTask · outlineGenerationTask · contentGenerationTask │ │ ├── contentIllustrationPlanning/Generation · globalFactsTask │ │ ├── knowledgeBaseService · duplicateCheckService · rejectionCheckTask │ │ ├── exportService(docx) · fileService · doc2markdown/convert.mjs │ │ ├── sqliteDatabase · configStore · taskService · licenseService │ │ └── opencode/ OpenCode 런타임 래퍼(runner·proxy·isolation·selfCheck) │ ├── resources/ · utils/ │ └── vendor/opencode ← 벤더링된 OpenCode 바이너리/자산 └── src/ ← 렌더러 (React 19) ├── app/providers/ 전역 프로바이더 ├── features/ technical-plan(12) · export-format(3) · │ knowledge-base · duplicate-check · rejection-check · │ business-bid · bid-opportunity · settings · developer └── shared/ ai(aiClient) · prompts(analysis·outline·jsonRepair·rejection) · markdown · ui · types · utils · analytics

이 저장소를 읽을 때 지적 핵심은 세 곳이다 — 文章/(왜·어떻게 사고했나), client/electron/services/(그 사고가 코드로 어떻게 구현됐나), client/src/shared/prompts/(실제 프롬프트 본문).

읽는 순서 · 어디부터 파나
README → 文章/(四)(五)(六)(七) → services/outlineGenerationTask → prompts/
README로 전체 그림과 파이프라인을 잡고 → ② 文章/의 4·5·6·7편을 읽어 "비용·JSON·장문·지식베이스"의 사고를 흡수한 뒤 → ③ services/outlineGenerationTask.cjs·contentGenerationTask.cjs·globalFactsTask.cjs에서 그 사고가 코드로 어떻게 옮겨졌는지 확인 → ④ shared/prompts/(outlinePrompts·jsonRepairPrompts·analysisPrompts)로 실제 프롬프트 문구를 본다. 글과 코드를 번갈아 보면 이해가 배가된다.

6학습 포인트 — LLM 엔지니어링 4대 노하우

이 저장소의 진짜 보물 — 입찰서가 아니라, 장문 LLM 앱을 만들 때 누구나 부딪히는 4대 난제의 실전 해법

OpenBidKit이 학습 표본으로 값진 이유는, "챗봇을 넘어 진짜 장문 LLM 애플리케이션을 만들 때 반드시 만나는 문제들"을 정면으로 풀고 그 과정을 글로 남겼기 때문이다. 아래 4개는 입찰서와 무관하게 모든 LLM 앱 개발자에게 전이되는 노하우다.

① 프롬프트 "순서"로 입력 비용을 10배 줄인다 (Prompt Cache)

가장 반직관적이면서 강력한 교훈이다. 대부분의 모델 서비스사는 Prompt Cache(프롬프트 캐시)를 지원하는데, "내용이 같으면" 캐시되는 게 아니라 "요청의 앞부분(prefix)이 같으면" 캐시된다. 그래서 매번 바뀌는 지시문을 앞에, 안 바뀌는 긴 원문(공고문)을 뒤에 두면, 같은 공고문이어도 캐시를 못 타 돈이 새어 나간다.

OpenBidKit은 같은 공고문을 두 번 분석한다(개요 추출 + 배점 추출). 그래서 긴 공고문을 프롬프트 에 고정하고, 분석 종류 같은 가변 지시는 뒤로 밀어 캐시 프리픽스를 안정화했다. 결과 — 입력 비용 최대 10배 절감.

# 나쁜 예 — 가변 지시가 앞, 긴 원문이 뒤 → 프리픽스가 매번 달라 캐시 미스
[system] "개요를 추출하는 지시..."          # 분석마다 다름
[user]   "다음 공고문을 분석: {아주 긴 원문}"   # 뒤에 있어 캐시 못 탐

# 좋은 예 — 안 바뀌는 긴 원문을 프리픽스로 고정, 가변 지시는 뒤로
[system] "당신은 공고문 분석가다. 원문은 아래와 같다:\n{긴 원문}"  ← 안정 프리픽스(캐시 명중)
[user]   "이번엔 '기술 배점 요구'만 추출하라"    # 짧은 가변 지시
코드에 실제로 있다 · 캐시 워밍업
waitForPromptCacheWarmup() — fan-out 전에 5초 기다린다
knowledgeBaseService.cjs에는 PROMPT_CACHE_WARMUP_DELAY_MS = 5000이 있다. 여러 요청을 동시에 뿌리기(fan-out) 전에, 서비스사가 프리픽스 캐시를 먼저 쓰도록 5초 기다린다. 안 그러면 병렬 요청들이 모두 "캐시 없음" 상태로 출발해 프리픽스가 중복 과금된다. "캐시를 한 번 데운 뒤 병렬화"라는 디테일이 코드에 박혀 있다.

② 약한 모델도 복잡한 JSON을 안정 출력하게 — "프롬프트가 아니라 워크플로"

입찰서 목차는 3단 중첩 JSON이고, 이 JSON이 한 번 깨지면 뒤의 모든 단계(본문·캐시·편집·Word)가 멈춘다. 값싼/약한 모델에 맡기면 쉼표 누락, markdown 코드블록으로 감싸기, 설명문 섞기, 필드명 오타(childrenchild), 2단만 생성 등 실패가 "운(運) 뽑기"처럼 터진다.

핵심 통찰 — "프롬프트는 첫 성공률만 올릴 뿐, 진짜 안정성은 워크플로가 만든다." OpenBidKit은 목차 생성을 단일 호출이 아니라 다단계 방어 루프로 짰다(OpenCode의 자기반성·교정 차용).

목차 생성 워크플로 (약한 모델도 안정화) 1. 목차 JSON 생성 2. JSON 문법 검증 ─┐ 3. 스키마(Pydantic류) 검증 ├─ 하나라도 실패하면 4. 업무 규칙 검증 ─┘ ↓ 5. JSON 자동 수리 (buildJsonRepairMessages: 불법 이스케이프 등 교정) 6. 그래도 실패 → 재시도 7. 통짜 생성 실패 → "1단→2·3단" 분할 생성으로 전환 8. 생성 후 → AI에게 목차 품질 자체를 심사시킴 9. 심사 불통과 → 개선 제안을 붙여 다시 생성

shared/prompts/jsonRepairPrompts.ts의 수리 프롬프트는 아주 구체적이다 — "너는 엄격한 JSON 수리 도우미다. 1\. 같은 불법 역슬래시 이스케이프를 1.로 고치고, 보존해야 할 역슬래시는 \\로 써라. 설명 없이 수리된 완전한 JSON만 반환하라." 이 "생성-검증-수리-재시도-분할-심사-재생성" 패턴은 어떤 구조화 출력 LLM 앱에도 그대로 쓸 수 있는 골든 템플릿이다.

③ 초장문(10만~100만 자)을 일관성 있게 — 잎 노드 병렬 + 전역 사실 + 삽화 선편성

수십만 자를 한 번에 생성할 순 없다. OpenBidKit은 목차 잎 노드마다 나눠 병렬 생성하되, 병렬이 부르는 모순을 두 장치로 막는다 — ① globalFactsTask가 뽑은 전역 사실을 모든 노드에 앵커로 주입해 앞뒤가 어긋나지 않게 하고, ② 지식베이스 소재도 어느 노드에 쓸지 미리 배정한다.

삽화는 더 영리하다. "본문 다 쓰고 어디에 그림 넣지?"라고 나중에 정하면 (a) 100만 자를 AI가 다시 읽어야 하고(토큰 낭비) (b) 그림 수가 통제 불능이 된다. 그래서 OpenBidKit은 본문 생성 전에 전체 목차를 훑어 "이 소절에 표/Mermaid/AI그림이 적합한가 + 우선순위 점수"를 미리 편성(预编排)하고, 점수 상위 노드만 골라 그림을 생성한다. 덕분에 비용이 예측 가능하고, 그림이 앞 장에만 몰리지 않으며, 본문이 "여기 뒤에 그림이 온다"를 미리 알아 표현이 자연스러워진다.

④ "당신에겐 RAG가 필요 없다" — 롱컨텍스트 + 캐시로 지식베이스

연재 7편의 도발적 제목이다. 전통적 지식베이스는 RAG(문서를 벡터로 쪼개 검색해 일부만 주입)를 쓴다. OpenBidKit의 접근은 다르다 — 모델의 거대한 컨텍스트 창(코드 기본값 DEFAULT_CONTEXT_LENGTH_LIMIT = 400000 자, 그 80%까지 사용)에 지식베이스를 통째로 넣고, ②에서 본 프롬프트 캐시로 그 비용을 죽인다.

벡터 검색의 "관련 조각을 잘 못 찾는" 문제도, 청킹 경계에서 문맥이 잘리는 문제도 없다. 대신 문서가 컨텍스트 한계를 넘으면 splitUserTextByContextLimit로 나누고, 과대 블록(8000자)·의미 병합 목표(500자) 같은 파라미터로 조율한다. "컨텍스트가 충분히 크고 캐시가 싸다면, 검색(RAG)보다 통째로 넣기가 낫다"는 이 관점은 롱컨텍스트 시대의 실전 설계 선택지로서 배울 가치가 크다.

한 줄로 남길 교훈
"코드가 아니라 사고를 훔쳐라"

개발자 스스로 "vibe coding 시대엔 코드 자체는 거의 막힘이 없었고, 어려운 건 문제를 푸는 사고(프롬프트·워크플로·에이전트 설계)였다"고 말한다. 이 4대 노하우(캐시로 비용↓, 워크플로로 JSON 안정, 앵커+선편성으로 장문 일관, 롱컨텍스트로 RAG 대체)는 입찰서가 아닌 어떤 LLM 앱에도 그대로 이식된다.

7시스템 요구사항 · 설치

Windows/macOS 데스크톱 앱 · GPU 불필요(로컬 모델 쓸 때만 필요) · 모델 API 키(또는 로컬 Ollama)

OpenBidKit 자체는 무겁지 않다 — 문서를 파싱하고 AI를 호출하는 앱이라 특별한 하드웨어가 필요 없다. 무거운 연산(모델 추론)은 외부 API나 로컬 Ollama가 담당한다. 두 가지 사용 경로가 있다.

# 경로 A) 그냥 쓰기 — Releases에서 설치본 다운로드
#   GitHub Releases의 Windows(.exe/NSIS) 또는 macOS(.dmg) 설치
#   앱 설정에서 모델 공급자(GPT/DeepSeek/火山方舟/OpenAI호환/Ollama) + API 키 입력

# 경로 B) 소스로 개발·빌드 (client/ 안에서)
git clone https://github.com/FB208/OpenBidKit_Yibiao && cd OpenBidKit_Yibiao/client
npm install
npm run dev          # Vite(5173) + Electron 동시 실행(핫리로드)
npm run dist:win     # Windows 설치본 빌드 (또는 dist:mac)
항목요구 / 설명
OSWindows / macOS(x64 + arm64) 데스크톱. Electron 41 기반. (Linux 타깃은 빌드 설정에 미포함)
가속기(GPU)앱 자체엔 불필요. 단, 로컬 모델(Ollama/LM Studio)로 돌릴 땐 그 모델이 요구하는 만큼 필요
모델GPT · DeepSeek · 火山方舟(doubao) 심층 적응 · OpenAI 호환 API면 무엇이든 · 로컬 Ollama/LM Studio
API 키클라우드 모델은 키 필요(암호화해 로컬 저장). 로컬 모델만 쓰면 키 불필요·완전 오프라인 추론
문서 파싱로컬 파서 기본 내장(Word/PDF/Excel). 복잡한 문서는 MinerU 파서 연동 가능(선택)
삽화(선택)Mermaid(내장) · 火山方舟 doubao-seedream-5.0 · Google AI Studio nano banana pro
저장전부 로컬 — userData/workspace/의 SQLite + 파일. 클라우드 업로드 없음
비용 감각 · 개발자 주장
10만 자 입찰서 ≈ 1위안 (DeepSeek V4 Flash 기준)
§6-①의 프롬프트 캐시 최적화가 이 숫자의 근거다. 다만 모델·설정·문서 길이에 따라 실제 비용과 품질은 크게 달라진다 — "값싼 모델로도 돌아가게" 하는 것이 목표이지, "값싼 모델이 GPT급 품질을 낸다"는 보장은 아니다.

8직접 해볼 수 있는 실습 과제

난이도별 5개 — 입찰서를 만들 필요는 없다. "장문 LLM 앱 기법"을 내 프로젝트로 훔쳐 오는 실습
난이도 ★☆☆ · 초급

과제 1 — 앱을 돌려 파이프라인을 눈으로 보기

소스를 클론해 cd client && npm install && npm run dev로 띄우고, 설정에서 로컬 Ollama(또는 DeepSeek 키)를 붙인 뒤 짧은 공고문 하나로 "공고 분석 → 목차 → 본문 → Word"를 끝까지 돌려 본다. 목표: 단계별 작업(Task)이 SQLite에 낙점되며 진행되는 파이프라인을 체감.

난이도 ★☆☆ · 초급

과제 2 — 프롬프트 캐시 실험(비용 10배 재현)

아무 모델 API로, 같은 긴 문서를 두 번 분석하되 (a) 긴 문서를 에, (b) 긴 문서를 앞(프리픽스)에 두는 두 버전을 만들어 입력 토큰 청구액을 비교한다. 文章/(四)편과 나란히 읽으며. 목표: "내용이 아니라 프리픽스가 캐시된다"를 지갑으로 확인.

난이도 ★★☆ · 중급

과제 3 — "생성→검증→수리→재시도" JSON 워크플로 이식

shared/prompts/jsonRepairPrompts.tsoutlineGenerationTask.cjs의 방어 루프를 참고해, 내 프로젝트의 아무 "구조화 출력"(예: 상품 정보 JSON)에 "JSON 검증 → 스키마 검증 → 자동 수리 → 재시도 → AI 심사" 루프를 붙여 본다. 목표: 약한 모델로도 깨지지 않는 구조화 출력 패턴 습득.

난이도 ★★☆ · 중급

과제 4 — "전역 사실 앵커"로 장문 일관성 잡기

여러 조각으로 나눠 생성하는 긴 글(예: 여러 절로 된 보고서)에서, 먼저 핵심 사실(이름·수치·용어) 목록을 뽑아 모든 조각 프롬프트에 함께 주입해 본다. globalFactsTask의 발상 그대로. 주입 전/후의 앞뒤 모순 빈도를 비교. 목표: 병렬 장문 생성의 일관성 앵커 기법 체득.

난이도 ★★★ · 고급

과제 5 — "삽화 선편성(预编排)" 미니 구현

목차(또는 문단 리스트)를 입력받아, 본문 생성 전에 "이 노드에 표/도표/그림이 적합한가 + 우선순위 점수"를 AI로 매기고 상위 N개만 고르는 편성기를 만든다. contentIllustrationPlanning.cjs의 설계를 참고. 목표: "리소스(비용) 예산을 선(先)배분"하는 편성-실행 분리 패턴 이해.

9관련 기술 심화 학습 로드맵

4주 코스 — Electron 이중 구조 → 장문 생성·일관성 → 구조화 출력·비용 → 롱컨텍스트 vs RAG
주차주제 · 학습 목표
1주차
Electron 앱 구조
메인 ↔ 렌더러 ↔ IPC. Electron의 프로세스 분리, preload로 안전한 브리지 노출, 렌더러(React 19)와 메인(Node) 역할 분담. OpenBidKit의 preload.cjs·ipc/·services/를 지도 삼아 "왜 로직이 전부 메인에 있나"를 이해.
2주차
장문 생성 · 일관성
수십만 자를 나눠 쓰고 다시 합치기. 목차 트리 잎 노드 병렬 생성, 전역 사실 앵커로 모순 억제, 삽화 선편성(预编排). 文章/(六) + contentGenerationTask·globalFactsTask·contentIllustrationPlanning을 정독.
3주차
구조화 출력 · 비용
깨지지 않는 JSON과 싼 입력. "생성-검증-수리-재시도-분할-심사" 워크플로(§6-②)와 Prompt Cache 프리픽스 설계(§6-①). 文章/(四)(五) + jsonRepairPrompts·outlineGenerationTask. 자기 프로젝트에 이식해 볼 것.
4주차
롱컨텍스트 vs RAG
"검색이냐 통째로냐"의 선택. RAG(벡터 검색)의 장단점과, 롱컨텍스트+캐시로 지식베이스를 대체하는 관점(§6-④). 文章/(七) + knowledgeBaseService(splitUserTextByContextLimit·컨텍스트 40만 자·캐시 워밍업). 언제 RAG가 여전히 유리한지도 함께 판단.

10핵심 키워드 사전

이 문서에서 반드시 챙길 용어 14개
용어 01
標書(입찰서) · 招標문서(공고문)
발주처가 낸 공고문(요구·배점)에 맞춰 업체가 제출하는 장문 제안 문서. OpenBidKit의 생성 대상.
용어 02
Electron 이중 구조(메인/렌더러)
화면(렌더러, React)과 엔진(메인, Node)이 분리돼 IPC로만 통신. 무거운 로직은 전부 메인 services/에.
용어 03
IPC 브리지 (window.yibiao)
preload.cjs가 노출하는 안전한 창구. 렌더러의 aiClient.chat/requestJson이 이걸 통해 메인의 실제 AI 로직을 호출.
용어 04
Prompt Cache(프롬프트 캐시) · 프리픽스
"내용이 같으면"이 아니라 "요청 앞부분이 같으면" 캐시. 긴 원문을 앞에 고정하면 입력 비용 최대 10배↓(§6-①).
용어 05
캐시 워밍업(warmup)
병렬 요청(fan-out) 전에 잠깐(5초) 기다려 서비스사가 프리픽스 캐시를 먼저 쓰게 하는 기법. knowledgeBaseService에 실장.
용어 06
구조화 출력 방어 워크플로
생성→JSON검증→스키마검증→업무규칙→자동수리→재시도→분할→AI심사→재생성. 약한 모델도 복잡 JSON을 안정 출력(§6-②).
용어 07
JSON 자동 수리(jsonRepair)
깨진 JSON(불법 이스케이프 등)을 AI에게 "설명 없이 고친 JSON만 반환"시켜 되살리는 단계. jsonRepairPrompts.ts.
용어 08
잎 노드 병렬 생성
목차 트리의 말단(잎)마다 본문을 나눠 병렬로 쓰는 방식. 빠르지만 일관성 장치(전역 사실)가 필요.
용어 09
전역 사실(globalFacts) 앵커
회사 규모·프로젝트명·핵심 수치 등을 먼저 뽑아 모든 노드에 주입 → 장문 앞뒤 모순 억제(§6-③).
용어 10
삽화 선편성(预编排, pre-arrangement)
본문 생성 전에 어느 노드에 표/Mermaid/AI그림을 넣을지 점수로 미리 배정. 비용 예측·분포 균등·표현 자연스러움.
용어 11
롱컨텍스트 지식베이스(비RAG)
문서를 벡터로 쪼개 검색(RAG)하는 대신, 큰 컨텍스트(기본 40만 자)에 통째로 넣고 캐시로 비용을 죽이는 접근(§6-④).
용어 12
벤더링된 OpenCode 런타임
앱이 품은 코딩 에이전트 엔진. OpenAI 호환 프록시·격리·자기점검 래퍼로 감쌈. 자기반성·교정 기법의 출처.
용어 13
better-sqlite3 · user_version
로컬 워크스페이스 DB. 동기식 고속. PRAGMA user_version=17로 17차례 마이그레이션한 이력을 관리(큰 원문은 파일, 메타만 DB).
용어 14
MinerU · 火山方舟(Volcano Ark)
MinerU=복잡 문서용 외부 파서(선택). 火山方舟=바이트댄스 모델 플랫폼(삽화 doubao-seedream-5.0 등 심층 적응).

11참고 링크

저장소 · 공식 사이트 · 저장소 내 핵심 자료 · 상위 개념

저장소 & 배포
· GitHub: github.com/FB208/OpenBidKit_Yibiao (AGPL-3.0, 클라이언트 v0.1.0)
· 미러(Gitee): gitee.com/yibiao-ai/OpenBidKit_Yibiao · 설치본은 GitHub Releases에서
· DeepWiki(자동 문서): deepwiki.com/FB208/OpenBidKit_Yibiao

공식 사이트
· 온라인 체험·제품 정보·기술 지원: yibiao.pro

저장소 내 핵심 코드/문서
· 文章/(연재 1~7편, LLM 노하우) · client/electron/services/(outlineGenerationTask·contentGenerationTask·globalFactsTask·knowledgeBaseService·opencode/) · client/src/shared/prompts/(outlinePrompts·jsonRepairPrompts·analysisPrompts) · sql/workspace_schema.sql

상위 개념 · 함께 볼 것
· Electron(electronjs.org) · Prompt Caching(각 모델사 문서) · MinerU(문서 파싱) · Mermaid(mermaid.js.org) · OpenCode(코딩 에이전트 런타임)

반드시 알아 둘 함정 · "범용 도구가 아니다"
쓰기 전에 체크할 6가지

① 도메인·언어 종속. 중국 입찰(招投標) 실무에 최적화됐고, UI·문서·연재 글이 대부분 중국어다. 다른 나라·다른 문서 유형엔 프롬프트·업무 규칙을 손봐야 한다.

② AGPL-3.0. 강한 카피레프트다 — 이 코드를 가져다 네트워크 서비스로 제공하면 소스 공개 의무가 따라온다. 사내 폐쇄 제품에 그대로 이식할 계획이면 라이선스를 반드시 확인.

③ 품질은 "당신의 모델·설정"에 달렸다. "약한 모델로도 돌아가게" 하는 워크플로가 강점이지, "값싼 모델이 GPT급 품질을 낸다"는 보장은 아니다. "10만 자 ≈ 1위안"은 조건부 수치.

④ 연재 글과 코드의 세대차. 초기 연재(1~4편)는 Python+React 시절(yibiao-simple) 예제라 코드가 지금의 Electron+TS 앱과 다르다. 사고(프롬프트·워크플로)는 유효하지만, 코드는 현재 저장소 기준으로 대조할 것. 연재 7편(비RAG)은 저장소 안 파일이 비어 있어 개념은 README·코드로 보충해야 한다.

⑤ 외부 의존·과금 표면. 클라우드 모델·삽화 모델(doubao/nano banana)·MinerU는 각각 키·과금이 붙는다. 완전 무료·오프라인을 원하면 로컬 Ollama + Mermaid 조합으로 범위가 좁아진다.

⑥ 결과물은 "초안". 실제 입찰 제출 전 사람의 검토·수정이 필수다. AI 생성 입찰서를 무검수로 제출하는 것은 폐찰·신뢰 위험을 부른다(앱에 폐찰 검사 기능이 있는 이유이기도 하다).