File size: 4,013 Bytes
515f392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
---
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`λ₯Ό μ°Έκ³ ν•˜μ„Έμš”.