--- title: CodeWeaver emoji: πŸ€– colorFrom: blue colorTo: purple sdk: gradio sdk_version: "4.44.1" app_file: ui/app.py pinned: false license: mit --- # CodeWeaver LangGraph 기반의 **개발자 Q&A μ—μ΄μ „νŠΈ**μž…λ‹ˆλ‹€. μ§ˆλ¬Έμ„ λΆ„μ„ν•˜κ³ (후속/독립), **μΊμ‹œ(Qdrant)**λ₯Ό μš°μ„  ν™•μΈν•œ λ’€ μΊμ‹œ 미슀일 λ•Œ **3개 μ†ŒμŠ€(Stack Overflow / GitHub / 곡식 λ¬Έμ„œ(Tavily))λ₯Ό 병렬 검색**ν•΄ 닡변을 μƒμ„±ν•©λ‹ˆλ‹€. μ„œλ‘œ 독립적인 질문이 2개 λ“€μ–΄μ˜€λ©΄ **λ™μ μœΌλ‘œ 2개 νŒŒμ΄ν”„λΌμΈμ„ 병렬 μ‹€ν–‰**ν•΄ 톡합 닡변을 μ œκ³΅ν•©λ‹ˆλ‹€. ## 핡심 κΈ°λŠ₯(ν˜„μž¬ μ½”λ“œ κΈ°μ€€) - **질문 개수 감지**: 1개(단일 주제) / 2개(독립 질문 2개) / 3개 이상(거절 μ•ˆλ‚΄) - **질문 νƒ€μž… 뢄석**: `clarification`이면 검색/μΊμ‹œ 없이 **λŒ€ν™” νžˆμŠ€ν† λ¦¬ 기반 λ‹΅λ³€** - **의미적 캐싱**: Qdrant에 질문-닡변을 μ €μž₯ν•˜κ³  μœ μ‚¬ μ§ˆλ¬Έμ„ λΉ λ₯΄κ²Œ μž¬μ‚¬μš©(μž„κ³„κ°’ 0.85) - **병렬 검색**: Stack Overflow / GitHub / Tavily(곡식 λ¬Έμ„œ 도메인 μ œν•œ) λ™μ‹œ 검색 - **검색 ν’ˆμ§ˆ 보정**: κ²°κ³Όκ°€ λΆ€μ‘±ν•˜λ©΄ **쿼리 κ°œμ„ μ„ μ΅œλŒ€ 1회** μˆ˜ν–‰ - **μ„œλΈŒκ·Έλž˜ν”„ 처리**: 검색 κ²°κ³Όλ₯Ό 필터링/μ μˆ˜ν™” ν›„ μš”μ•½ β†’ μ΅œμ’… λ‹΅λ³€ 생성 ## λ¬Έμ„œ - μ•„ν‚€ν…μ²˜/λ™μž‘ 원리: `../ARCHITECTURE.md` - 닀쀑 질문 병렬 처리 섀계(λ°°κ²½ μ„€λͺ…): `../DYNAMIC_PARALLEL_SEARCH.md` ## λΉ λ₯Έ μ‹œμž‘ ### 1) μ„€μΉ˜ μ•„λž˜λŠ” μ €μž₯μ†Œ λ£¨νŠΈκ°€ μ•„λ‹ˆλΌ **`CodeWeaver/` 디렉터리 κΈ°μ€€** μ˜ˆμ‹œμž…λ‹ˆλ‹€. ```bash cd CodeWeaver # uv μ‚¬μš©(ꢌμž₯) uv sync # λ˜λŠ” pip μ‚¬μš© pip install -r requirements.txt ``` > `sentence-transformers`κ°€ 졜초 μ‹€ν–‰ μ‹œ `BAAI/bge-m3` λͺ¨λΈμ„ λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€(λ„€νŠΈμ›Œν¬ ν•„μš”). ### 2) ν™˜κ²½ λ³€μˆ˜ μ„€μ •(.env) `CodeWeaver/.env` νŒŒμΌμ„ λ§Œλ“€κ³  μ•„λž˜λ₯Ό μ„€μ •ν•˜μ„Έμš”(ν•„μˆ˜/선택 ꡬ뢄). ```bash # ν•„μˆ˜: Gemini (LLM) GOOGLE_API_KEY=your_google_api_key # ν•„μˆ˜: Tavily (곡식 λ¬Έμ„œ 검색) TAVILY_API_KEY=your_tavily_api_key # ν•„μˆ˜: Qdrant Cloud (μΊμ‹œ) QDRANT_URL=https://xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.us-east-1-0.aws.cloud.qdrant.io QDRANT_API_KEY=your_qdrant_api_key # 선택: GitHub API rate limit μ™„ν™” GITHUB_TOKEN=your_github_token # 선택: LangSmith νŠΈλ ˆμ΄μ‹± LANGCHAIN_TRACING_V2=true LANGCHAIN_API_KEY=your_langsmith_api_key ``` ### 3) μ‹€ν–‰(Gradio UI) ```bash cd CodeWeaver python ui/app.py ``` κΈ°λ³Έ μ£Όμ†Œ: `http://localhost:7860` ## ν˜„μž¬ 폴더 ꡬ쑰 ``` CodeWeaver/ β”œβ”€β”€ main.py β”œβ”€β”€ pyproject.toml β”œβ”€β”€ requirements.txt β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ agent/ β”‚ β”‚ β”œβ”€β”€ graph.py # LangGraph 메인 κ·Έλž˜ν”„(λΌμš°νŒ…/병렬화) β”‚ β”‚ β”œβ”€β”€ nodes.py # 각 λ…Έλ“œ κ΅¬ν˜„ β”‚ β”‚ └── state.py # AgentState + reducer μ •μ˜ β”‚ β”œβ”€β”€ tools/ β”‚ β”‚ └── search_tools.py # StackOverflow/GitHub/Tavily 검색 β”‚ β”œβ”€β”€ utils/ β”‚ β”‚ └── tracing.py # trace_node λ°μ½”λ ˆμ΄ν„°(LangSmith 연동) β”‚ └── vector_db/ β”‚ β”œβ”€β”€ qdrant_client.py # Qdrant μΊμ‹œ 관리 β”‚ └── local_embeddings.py # bge-m3 둜컬 μž„λ² λ”© └── ui/ └── app.py # Gradio UI (μ‹€μ œ μ—”νŠΈλ¦¬) ``` ## λ™μž‘ 흐름(μš”μ•½) - `START β†’ create_plan` - **3개 이상**이면 μ•ˆλ‚΄ λ©”μ‹œμ§€ λ°˜ν™˜ - **2개**λ©΄ 각 μ§ˆλ¬Έμ„ workerμ—μ„œ 단일 νŒŒμ΄ν”„λΌμΈμœΌλ‘œ μ‹€ν–‰ ν›„ κ²°ν•© - **1개**λ©΄ μ•„λž˜ 단일 νŒŒμ΄ν”„λΌμΈ μˆ˜ν–‰ - 단일 νŒŒμ΄ν”„λΌμΈ: - `analyze_question` - `clarification`이면 `generate_with_history`둜 μ¦‰μ‹œ λ‹΅λ³€ - κ·Έ μ™Έ: `check_cache` β†’ hitλ©΄ λ°˜ν™˜, missλ©΄ `classify_intent` - `classify_intent` β†’ 3μ†ŒμŠ€ 병렬 검색 β†’ `collect_results` β†’ `evaluate_results` - ν•„μš” μ‹œ `refine_search` 1회 β†’ μž¬κ²€μƒ‰ - `filter_and_score β†’ summarize_results β†’ generate_answer`(+쑰건뢀 μΊμ‹œ μ €μž₯) μžμ„Έν•œ μ›λ¦¬λŠ” `../ARCHITECTURE.md`λ₯Ό μ°Έκ³ ν•˜μ„Έμš”.