项ç®å·²åŒæºïŒæ¬¢è¿ Star æ¯æïŒ
- å端ïŒgithub.com/ankeji/rag-âŠ
- å端ïŒgithub.com/ankeji/knowâŠ
åèš
æè¿ RAGïŒæ£çŽ¢å¢åŒºçæïŒææ¯éåžžç«çïŒåŸå€ååŠéœåšåŠä¹ åŠäœæå»ºèªå·±çç¥è¯åºé®çç³»ç»ãæè±äºäž€äžªææ¶éŽïŒä»é¶æå»ºäºäžäžªäŒäžçº§ RAG ç¥è¯åºå©æïŒéæäºåœåææµè¡çææ¯æ ïŒç°åšå·²ç»åŒæºïŒåžæèœåž®å©å€§å®¶åŠä¹ ååèã
项ç®ç®ä»
è¿æ¯äžäžªåºäº LangChain + LangGraph + Vue 3 æå»ºçäŒäžç¥è¯åºé®çç³»ç»ïŒæ¯æïŒ
- â åšæå€ææ¡£å¯Œå ¥ - æŸå ¥ PDF å³å¯èªåšæå»ºç¥è¯åº
- â æ··åæ£çŽ¢ - åéæ£çŽ¢ + BM25 å ³é®è¯æ£çŽ¢
- â Rerank 粟æåº - æåæ£çŽ¢çžå ³æ§
- â æµåŒèŸåº - 宿¶å±ç€ºæèè¿çš
- â Agent å·¥å ·è°çš - æ¯æè¡šç®¡çãPDF å¯Œå ¥çæäœ
- â Redis äŒè¯ååš - æ¯æåå²å¯¹è¯ãååžåŒéšçœ²
ææ¯æ¶æ
åç«¯ææ¯æ
| ææ¯ | 诎æ |
|---|---|
| LangChain + LangGraph | å·¥äœæµçŒæãAgent æå»º |
| ChromaDB | åéæ°æ®åº |
| éä¹åé® qwen-turbo | LLM æš¡å |
| gte-rerank-v2 | 粟æåºæš¡å |
| rank_bm25 | BM25 å ³é®è¯æ£çŽ¢ |
| FastAPI | Web æ¡æ¶ïŒæ¯ææµåŒèŸåº |
| Redis | äŒè¯ååš |
åç«¯ææ¯æ
| ææ¯ | 诎æ |
|---|---|
| Vue 3 | æžè¿åŒæ¡æ¶ |
| Element Plus | UI ç»ä»¶åº |
| Vite | æå»ºå·¥å · |
| Axios | HTTP è¯·æ± |
æ¶æåŸ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â å端 (Vue 3) â
â âââââââââââ âââââââââââ âââââââââââ âââââââââââ â
â â 对è¯çé¢ â â æèè¿çš â â é
çœ®é¢æ¿ â â ç»è®¡å±ç€º â â
â âââââââââââ âââââââââââ âââââââââââ âââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
⌠SSE æµåŒèŸåº
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â å端 (FastAPI + LangGraph) â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â LangGraph å·¥äœæµ â â
â â çšæ·èŸå
¥ â å€é®å¥çæ â æ··åæ£çŽ¢ â Rerank â äžäžæå猩 â â
â â â LLM åç â æµåŒèŸåº â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â
â âââââââââââ âââââââââââ âââââââââââ âââââââââââ â
â â ChromaDBâ â BM25 â â Rerank â â Redis â â
â âââââââââââ âââââââââââ âââââââââââ âââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
æ žå¿åèœè¯Šè§£
1. RAG æ£çŽ¢æµçš
è¿æ¯é¡¹ç®çæ žå¿ïŒå®æŽç RAG æ£çŽ¢æµçšåŠäžïŒ
PDF富å
¥ â æºèœåå â åéåååš
â
çšæ·é®é¢ â Redisè·ååå² â å€é®å¥çæ â åéæ£çŽ¢ + BM25æ£çŽ¢
â
åå¹¶å»é â Rerank粟æåº â äžäžæå猩 â LLMåç â Redisä¿ååå²
2. å€é®å¥çæ
çšæ·çé®é¢å¯èœè¡šè¿°äžç²Ÿç¡®ïŒæä»¬äœ¿çš LLM çæå€äžªæ£çŽ¢é®å¥ïŒæé«å¬åçïŒ
# èŸå
¥ïŒå¹Žåæå€å°å€©ïŒ
# èŸåºïŒ["幎åæå€å°å€©ïŒ", "幎å倩æ°è§å®", "åå·¥å¹Žåæ¿ç"]
3. æ··åæ£çŽ¢
ç»ååéæ£çŽ¢å BM25 å ³é®è¯æ£çŽ¢çäŒå¿ïŒ
def hybrid_search(db, bm25, question, top_k=5):
# 1. åéæ£çŽ¢ - è¯ä¹çžäŒŒ
vector_candidates = db.search(question, top_k=top_k)
# 2. BM25æ£çŽ¢ - å
³é®è¯ç²Ÿç¡®å¹é
bm25_candidates = bm25.search(question, top_k=top_k)
# 3. åæ°åœäžå + å æèå
all_candidates = normalize_and_merge(
vector_candidates, bm25_candidates,
vector_weight=0.6, bm25_weight=0.4
)
return all_candidates
4. Rerank 粟æåº
äœ¿çš Cross-Encoder æš¡å对åéç»æè¿è¡ç²ŸæåºïŒ
def rerank(question, candidates):
# è°çš gte-rerank-v2 æš¡å
results = rerank_api(question, [c["chunk"] for c in candidates])
# æçžå
³æ§åæ°æåº + éåŒè¿æ»€
filtered = [r for r in results if r["score"] >= threshold]
return filtered[:top_k]
5. æµåŒèŸåº + æèè¿çšå±ç€º
åç«¯å®æ¶å±ç€º RAG æ£çŽ¢çæ¯äžæ¥ïŒ
// SSE æµåŒæ¥æ¶
const eventSource = new EventSource('/api/chat/stream')
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.type === 'log') {
// 宿¶æŸç€ºæèè¿çš
thinkingLogs.value.push(data.log)
} else if (data.type === 'answer') {
// æµåŒèŸåºçæ¡
currentAnswer.value += data.content
}
}
6. åšæå€ææ¡£å¯Œå ¥
è¿æ¯æè§åŸæå®çšçåèœïŒçšæ·åªéèŠæ PDF æä»¶æŸå
¥ docs ç®åœïŒæ§è¡å¯Œå
¥èæ¬å³å¯ïŒ
# 1. æŸå
¥ PDF æä»¶
cp åå·¥æå.pdf docs/
cp è§ç« å¶åºŠ.pdf docs/
# 2. æ§è¡å¯Œå
¥
python pdf_import_script.py
# èŸåºïŒ
# ð æ«æPDFæä»¶ â åç° 2 䞪 PDF æä»¶
# ð 读åPDFæä»¶: ./docs/åå·¥æå.pdf
# âïž ææ¬åå â ååæ°éïŒ150
# ð¢ çæåé â çæ150䞪åé
# ð¥ 富å
¥ChromaDB â 衚åïŒyuan_gong_shou_ce
# â
æå富å
¥è¡šãyuan_gong_shou_ceã
å¿«éåŒå§
1. å é项ç®
# å
éå端
git clone https://github.com/ankeji/rag-pro.git
cd rag-pro
# å
éå端
git clone https://github.com/ankeji/knowledge-assistant.git
cd knowledge-assistant
2. å端é 眮
# å®è£
äŸèµ
pip install -r requirements.txt
# é
眮 API Key
echo "API_KEY=your_dashscope_api_key" > .env
# 富å
¥ææ¡£
mkdir docs
cp your_document.pdf docs/
python pdf_import_script.py
# å¯åšæå¡
python api.py
3. å端é 眮
# å®è£
äŸèµ
npm install
# å¯åšåŒåæå¡åš
npm run dev
è®¿é® http://localhost:3000 å³å¯äœ¿çšïŒ
ææå±ç€º
åœä»€è¡é®ç
ð¬ 请èŸå
¥é®é¢ïŒå¹Žåæå€å°å€©ïŒ
ð åŒå§å€ç: 幎åæå€å°å€©ïŒ
ââââââââââââââââââââââââââââââââââââââââ
â
æ£æ¥å èœœæ°æ®åºè¡š: yuan_gong_shou_ce(150æ¡) + gui_zhang_zhi_du(80æ¡)
â
è·åå岿¶æ¯: å·²è·å0æ¡å岿¶æ¯
â
çæå€æ£çŽ¢é®å¥: çæ3䞪æ£çŽ¢é®å¥
â
åéæ£çŽ¢: æ£çŽ¢å°12䞪åé
â
Rerank粟æåº: æåºå®æïŒä¿çå5äžªç»æ
â
æš¡åçæåç: åçé¿åºŠ:156å笊
ð€ åçïŒ
æ ¹æ®ãåå·¥æåãè§å®ïŒå工幎å倩æ°åŠäžïŒ
- å·¥éŸæ»¡1å¹Žäžæ»¡10幎ïŒ5倩
- å·¥éŸæ»¡10å¹Žäžæ»¡20幎ïŒ10倩
- å·¥éŸæ»¡20幎å以äžïŒ15倩
å端çé¢
å端ç颿¯æïŒ
- ð åšæç¥è¯åºç»è®¡
- ð 宿¶æèè¿çšå±ç€º
- âïž å¯è§åé çœ®é¢æ¿
- ð è§è²æé管ç
ææ¯äº®ç¹
1. LangGraph å·¥äœæµçŒæ
äœ¿çš LangGraph æå»ºæž æ°çå·¥äœæµïŒ
from langgraph.graph import StateGraph
workflow = StateGraph(WorkflowState)
workflow.add_node("init_database", node_init_database)
workflow.add_node("generate_queries", node_generate_queries)
workflow.add_node("vector_search", node_vector_search)
workflow.add_node("rerank", node_rerank)
workflow.add_node("generate_answer", node_generate_answer)
workflow.set_entry_point("init_database")
workflow.add_edge("init_database", "generate_queries")
workflow.add_edge("generate_queries", "vector_search")
# ...
2. Redis äŒè¯ååš + å岿èŠ
é¿å¯¹è¯åºæ¯äžïŒäœ¿çš LLM 对åå²è¿è¡æèŠïŒèçäžäžæç©ºéŽïŒ
def summarize_history(messages):
# ä¿çææ° N èœ®å®æŽå¯¹è¯
old_messages = messages[:-KEEP_ROUNDS]
recent_messages = messages[-KEEP_ROUNDS:]
# LLM çææèŠ
summary = llm.invoke(f"请æ»ç»ä»¥äžå¯¹è¯ïŒ{old_messages}")
return [HumanMessage(f"[å岿èŠ] {summary}")] + recent_messages
3. æµè§åšæçº¹çæ Session ID
åç«¯äœ¿çšæµè§åšæçº¹çæå¯äžæ è¯ïŒæ éç»åœå³å¯åºåçšæ·ïŒ
const generateFingerprint = () => {
const components = [
navigator.userAgent,
navigator.language,
screen.width + 'x' + screen.height,
canvas.toDataURL(),
// ...
]
return 'fp_' + hash(components)
}
项ç®ç»æ
åç«¯ç»æ
rag-pro/
âââ docs/ # ææ¡£ç®åœ
âââ main.py # LangGraph å·¥äœæµ
âââ api.py # FastAPI æå¡
âââ config.py # é
眮管ç
âââ tools.py # Agent å·¥å
·
âââ retriever.py # æ£çŽ¢æš¡å
âââ llm_utils.py # LLM å·¥å
·
âââ embedding_utils.py # åéçæ
âââ chroma_store.py # ChromaDB
âââ pdf_utils.py # PDF è§£æ
âââ pdf_import_script.py # 富å
¥èæ¬
âââ session_store.py # Redis ååš
âââ requirements.txt # äŸèµ
åç«¯ç»æ
knowledge-assistant/
âââ src/
â âââ components/
â â âââ KnowledgeAssistant.vue # äž»ç»ä»¶
â âââ App.vue
â âââ main.js
âââ vite.config.js
âââ package.json
æ»ç»
è¿äžªé¡¹ç®æ¶µçäº RAG ç³»ç»çå®æŽææ¯æ ïŒå æ¬ïŒ
- ææ¡£å€çïŒPDF è§£æãæºèœååãåéå
- æ£çŽ¢äŒåïŒæ··åæ£çŽ¢ãRerank 粟æåºãéåŒè¿æ»€
- LLM åºçšïŒå€é®å¥çæãäžäžæå猩ãå岿èŠ
- å·¥çšå®è·µïŒæµåŒèŸåºãäŒè¯ç®¡çãé çœ®åšææŽæ°
- å端亀äºïŒå®æ¶æèè¿çšãå¯è§åé 眮ãè§è²æé
åžæè¿äžªé¡¹ç®èœåž®å©å€§å®¶åŠä¹ RAG ææ¯ïŒæ¬¢è¿ Star æ¯æïŒ
ð 项ç®éŸæ¥
- å端项ç®ïŒgithub.com/ankeji/rag-âŠ
- å端项ç®ïŒgithub.com/ankeji/knowâŠ
â Star æ¯æ
åŠæè¿äžªé¡¹ç®å¯¹äœ æåž®å©ïŒæ¬¢è¿ç»äžª Star âïŒè¿æ¯å¯¹ææå€§çéŒå±ïŒ
乿¬¢è¿æ Issue å PRïŒäžèµ·å®åè¿äžªé¡¹ç®ïŒ