GuXiaopeng commited on
Commit
bb4ea25
·
verified ·
1 Parent(s): f3d96b6

Update core/rag_engine.py

Browse files
Files changed (1) hide show
  1. core/rag_engine.py +45 -26
core/rag_engine.py CHANGED
@@ -1,43 +1,62 @@
1
  # -*- coding: utf-8 -*-
2
- """轻量级 RAG 引擎 - 解决 20 篇文献的上下文溢出与精准召回"""
3
-
4
  from typing import List
5
  import numpy as np
 
 
 
 
 
 
 
 
6
 
7
  class ResearchRAGEngine:
8
  def __init__(self, raw_texts: List[str]):
9
  self.chunks = []
 
 
 
10
  self._initialize_chunks(raw_texts)
11
 
12
  def _initialize_chunks(self, raw_texts: List[str]):
13
- """将文献全文切割为 800-1000 字左右的语义块"""
14
  for text in raw_texts:
15
- # 简单的按长度切分,实际可按段落 \n\n 切分
16
- size = 3000
17
- for i in range(0, len(text), size):
18
- self.chunks.append(text[i:i + size])
 
 
 
 
 
 
 
19
 
20
- def get_relevant_context(self, query: str, top_k: int = 3) -> str:
21
- """
22
- 根据当前章节主题,通过简单的关键词加权检索相关文本块。
23
- (为了保持低依赖,此处使用词频匹配,如有需要可升级为 Embedding)
24
- """
25
- if not self.chunks: return ""
26
 
27
- scores = []
28
- query_words = set(query.lower().split())
29
-
30
- for chunk in self.chunks:
31
- chunk_lower = chunk.lower()
32
- # 简单评分:计算查询词在块中的覆盖度
33
- score = sum(1 for word in query_words if word in chunk_lower)
34
- scores.append(score)
 
 
 
 
 
 
 
35
 
36
- # 获取评分最高的前 k 个块
37
- top_indices = np.argsort(scores)[-top_k:]
38
- relevant_chunks = [self.chunks[i] for i in top_indices if scores[i] > 0]
39
-
40
- return "\n--- Context Snippet ---\n".join(relevant_chunks)
41
 
42
  def initialize_rag(texts: List[str]):
43
  return ResearchRAGEngine(texts)
 
1
  # -*- coding: utf-8 -*-
 
 
2
  from typing import List
3
  import numpy as np
4
+ from config import APP_CONFIG
5
+
6
+ try:
7
+ from sklearn.feature_extraction.text import TfidfVectorizer
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+ SKLEARN_AVAILABLE = True
10
+ except ImportError:
11
+ SKLEARN_AVAILABLE = False
12
 
13
  class ResearchRAGEngine:
14
  def __init__(self, raw_texts: List[str]):
15
  self.chunks = []
16
+ self.vectorizer = None
17
+ self.tfidf_matrix = None
18
+ self.chunk_size = APP_CONFIG["rag_chunk_size"]
19
  self._initialize_chunks(raw_texts)
20
 
21
  def _initialize_chunks(self, raw_texts: List[str]):
 
22
  for text in raw_texts:
23
+ for i in range(0, len(text), self.chunk_size):
24
+ chunk = text[i:i + self.chunk_size].strip()
25
+ if len(chunk) > 50:
26
+ self.chunks.append(chunk)
27
+
28
+ if SKLEARN_AVAILABLE and self.chunks:
29
+ self.vectorizer = TfidfVectorizer(stop_words='english', max_df=0.85)
30
+ try:
31
+ self.tfidf_matrix = self.vectorizer.fit_transform(self.chunks)
32
+ except ValueError:
33
+ self.vectorizer = None
34
 
35
+ def get_relevant_context(self, query: str, top_k: int = None) -> str:
36
+ if not self.chunks:
37
+ return ""
38
+ if top_k is None:
39
+ top_k = APP_CONFIG["rag_top_k"]
 
40
 
41
+ relevant_chunks = []
42
+ if self.vectorizer and self.tfidf_matrix is not None:
43
+ query_vec = self.vectorizer.transform([query])
44
+ similarities = cosine_similarity(query_vec, self.tfidf_matrix).flatten()
45
+ top_indices = similarities.argsort()[-top_k:][::-1]
46
+ relevant_chunks = [self.chunks[i] for i in top_indices if similarities[i] > 0.05]
47
+ else:
48
+ scores = []
49
+ query_words = set(query.lower().split())
50
+ for chunk in self.chunks:
51
+ chunk_lower = chunk.lower()
52
+ score = sum(1 for word in query_words if word in chunk_lower)
53
+ scores.append(score)
54
+ top_indices = np.argsort(scores)[-top_k:]
55
+ relevant_chunks = [self.chunks[i] for i in top_indices if scores[i] > 0]
56
 
57
+ if not relevant_chunks:
58
+ return ""
59
+ return "\n--- Target Context Snippet ---\n" + "\n\n".join(relevant_chunks)
 
 
60
 
61
  def initialize_rag(texts: List[str]):
62
  return ResearchRAGEngine(texts)