bichnhan2701 commited on
Commit
a6d62e8
·
1 Parent(s): 2faaa56

Update logic generate mindmap, summary and nlp

Browse files
app/jobs/enrichment_job.py CHANGED
@@ -1,3 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from app.services.storage import get_note, update_note
2
  from app.services.summary_service import generate_summary
3
  from app.services.mindmap_service import generate_mindmap
@@ -5,6 +28,7 @@ from app.services.mindmap_service import generate_mindmap
5
  async def run_enrichment(note_id: str, tasks: list):
6
  note = get_note(note_id)
7
  if not note:
 
8
  return
9
 
10
  text = note.get("normalized_text") or note["raw_text"]
@@ -12,10 +36,18 @@ async def run_enrichment(note_id: str, tasks: list):
12
  update_note(note_id, status="processing")
13
  updates = {}
14
 
15
- if "summary" in tasks:
16
- updates["summary"] = await generate_summary(text)
17
-
18
- if "mindmap" in tasks:
19
- updates["mindmap"] = await generate_mindmap(text)
 
20
 
21
- update_note(note_id, data=updates, status="ready")
 
 
 
 
 
 
 
 
1
+ # from app.services.storage import get_note, update_note
2
+ # from app.services.summary_service import generate_summary
3
+ # from app.services.mindmap_service import generate_mindmap
4
+
5
+ # async def run_enrichment(note_id: str, tasks: list):
6
+ # note = get_note(note_id)
7
+ # if not note:
8
+ # return
9
+
10
+ # text = note.get("normalized_text") or note["raw_text"]
11
+
12
+ # update_note(note_id, status="processing")
13
+ # updates = {}
14
+
15
+ # if "summary" in tasks:
16
+ # updates["summary"] = await generate_summary(text)
17
+
18
+ # if "mindmap" in tasks:
19
+ # updates["mindmap"] = await generate_mindmap(text)
20
+
21
+ # update_note(note_id, data=updates, status="ready")
22
+
23
+ import logging
24
  from app.services.storage import get_note, update_note
25
  from app.services.summary_service import generate_summary
26
  from app.services.mindmap_service import generate_mindmap
 
28
  async def run_enrichment(note_id: str, tasks: list):
29
  note = get_note(note_id)
30
  if not note:
31
+ logging.warning(f"[enrichment] Note not found: {note_id}")
32
  return
33
 
34
  text = note.get("normalized_text") or note["raw_text"]
 
36
  update_note(note_id, status="processing")
37
  updates = {}
38
 
39
+ try:
40
+ if "summary" in tasks:
41
+ try:
42
+ updates["summary"] = await generate_summary(text)
43
+ except Exception as e:
44
+ logging.exception(f"[enrichment] generate_summary failed for note_id={note_id}: {e}")
45
 
46
+ if "mindmap" in tasks:
47
+ try:
48
+ updates["mindmap"] = await generate_mindmap(text)
49
+ except Exception as e:
50
+ logging.exception(f"[enrichment] generate_mindmap failed for note_id={note_id}: {e}")
51
+ finally:
52
+ # Dù thành công hay thất bại, vẫn set status=ready để client ngừng poll
53
+ update_note(note_id, data=updates, status="ready")
app/services/mindmap_service.py CHANGED
@@ -1,56 +1,89 @@
1
- import asyncio, json
 
 
 
 
2
  from app.config import GEMINI_API_KEY
3
- import google.generativeai as genai
 
 
 
 
 
4
 
5
  if GEMINI_API_KEY:
6
- genai.configure(api_key=GEMINI_API_KEY)
7
- _model = genai.GenerativeModel("gemini-pro")
 
 
 
 
8
  else:
9
- _model = None
10
 
11
 
12
  async def generate_mindmap(text: str) -> dict:
13
- if not _model:
 
 
 
 
14
  return {}
15
 
16
  prompt = f"""
17
- Bạn là chuyên gia tạo Sơ đồ tư duy. Hãy phân tích văn bản sau và tạo cấu trúc JSON Mindmap.
 
18
  Yêu cầu:
19
  1. Xác định Ý chính làm Root.
20
  2. Phân tách ý phụ thành nhánh con (tối đa 3 cấp).
21
  3. Nhãn (label) ngắn gọn (< 7 từ).
22
- 4. Màu sắc (colorHex): Root="#6200EE", Con="#F59E2B", "#2ECF9A", "#2F9BFF".
 
 
 
23
 
24
- Cấu trúc JSON bắt buộc (Chỉ trả về JSON):
25
  {{
26
- "root": {{
27
- "label": "Chủ đề",
28
- "colorHex": "#6200EE",
29
- "children": [
30
- {{
31
- "label": "Ý 1",
32
- "colorHex": "#F59E2B",
33
- "children": []
34
- }}
35
- ]
36
- }}
37
  }}
38
 
39
  Văn bản:
40
- {text}
41
  """
42
 
43
  loop = asyncio.get_event_loop()
44
 
45
  def call():
46
- r = _model.generate_content(prompt)
47
- return r.text
48
-
49
- raw = await loop.run_in_executor(None, call)
 
50
 
51
- start = raw.find("{")
52
- end = raw.rfind("}")
53
- if start != -1 and end != -1:
54
- return json.loads(raw[start:end+1])
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  return {}
 
1
+ # app/services/mindmap_service.py
2
+ import asyncio
3
+ import json
4
+ import logging
5
+
6
  from app.config import GEMINI_API_KEY
7
+
8
+ import google.genai as genai
9
+ from google.api_core.exceptions import GoogleAPIError
10
+
11
+ _MINDMAP_MODEL = "gemini-1.5-flash"
12
+ _gemini_client = None
13
 
14
  if GEMINI_API_KEY:
15
+ try:
16
+ _gemini_client = genai.Client(api_key=GEMINI_API_KEY)
17
+ logging.info(f"[mindmap_service] Initialized google.genai client with model={_MINDMAP_MODEL}")
18
+ except Exception as e:
19
+ logging.exception(f"[mindmap_service] Failed to init google.genai client: {e}")
20
+ _gemini_client = None
21
  else:
22
+ logging.warning("[mindmap_service] GEMINI_API_KEY is not set, mindmap generation will be disabled")
23
 
24
 
25
  async def generate_mindmap(text: str) -> dict:
26
+ """
27
+ Sinh cấu trúc mindmap JSON từ văn bản.
28
+ Fallback: trả {} nếu không có model hoặc lỗi.
29
+ """
30
+ if not _gemini_client:
31
  return {}
32
 
33
  prompt = f"""
34
+ Bạn là chuyên gia tạo Sơ đồ tư duy. Hãy phân tích văn bản sau và tạo CẤU TRÚC JSON Mindmap.
35
+
36
  Yêu cầu:
37
  1. Xác định Ý chính làm Root.
38
  2. Phân tách ý phụ thành nhánh con (tối đa 3 cấp).
39
  3. Nhãn (label) ngắn gọn (< 7 từ).
40
+ 4. Màu sắc (colorHex):
41
+ - Root: "#6200EE"
42
+ - Các nhánh con: sử dụng một trong các màu: "#F59E2B", "#2ECF9A", "#2F9BFF"
43
+ 5. CHỈ TRẢ VỀ JSON, không giải thích thêm.
44
 
45
+ Cấu trúc JSON bắt buộc:
46
  {{
47
+ "root": {{
48
+ "label": "Chủ đề",
49
+ "colorHex": "#6200EE",
50
+ "children": [
51
+ {{
52
+ "label": "Ý 1",
53
+ "colorHex": "#F59E2B",
54
+ "children": []
55
+ }}
56
+ ]
57
+ }}
58
  }}
59
 
60
  Văn bản:
61
+ \"\"\"{text}\"\"\"
62
  """
63
 
64
  loop = asyncio.get_event_loop()
65
 
66
  def call():
67
+ resp = _gemini_client.models.generate_content(
68
+ model=_MINDMAP_MODEL,
69
+ contents=prompt,
70
+ )
71
+ return resp.text or ""
72
 
73
+ try:
74
+ raw = await loop.run_in_executor(None, call)
75
+ start = raw.find("{")
76
+ end = raw.rfind("}")
77
+ if start != -1 and end != -1:
78
+ try:
79
+ return json.loads(raw[start:end + 1])
80
+ except Exception as e:
81
+ logging.warning(f"[mindmap_service] Failed to parse mindmap JSON: {e}")
82
+ else:
83
+ logging.warning("[mindmap_service] Mindmap response has no JSON block")
84
+ except GoogleAPIError as e:
85
+ logging.error(f"[mindmap_service] Gemini API error: {e}")
86
+ except Exception as e:
87
+ logging.exception(f"[mindmap_service] generate_mindmap failed: {e}")
88
 
89
  return {}
app/services/summary_service.py CHANGED
@@ -1,35 +1,62 @@
1
  import asyncio
 
 
2
  from app.config import GEMINI_API_KEY
3
- import google.generativeai as genai
 
 
 
 
 
4
 
5
  if GEMINI_API_KEY:
6
- genai.configure(api_key=GEMINI_API_KEY)
7
- _model = genai.GenerativeModel("gemini-pro")
 
 
 
 
8
  else:
9
- _model = None
10
 
11
 
12
  async def generate_summary(text: str) -> str:
13
- if not _model:
 
 
 
 
14
  return ""
15
 
16
  prompt = f"""
17
- Bạn là chuyên gia tóm tắt. Hãy tóm tắt văn bản sau thành **một đoạn văn duy nhất**.
18
- Yêu cầu:
19
- 1. Viết khoảng 3-5 câu, tổng hợp đầy đủ chủ đề và các ý chính.
20
- 2. Viết liền mạch, KHÔNG xuống dòng, KHÔNG dùng gạch đầu dòng hay đánh số.
21
- 3. Chỉ dựa trên thông tin được cung cấp, tuyệt đối KHÔNG tự thêm thông tin bên ngoài.
22
- 4. Trả về văn bản thuần (plain text).
23
-
24
- Văn bản:
25
- \"\"\"{text}\"\"\"
26
- """
 
27
 
28
  loop = asyncio.get_event_loop()
29
 
30
  def call():
31
- r = _model.generate_content(prompt)
32
- return r.text.strip()
33
-
34
- result = await loop.run_in_executor(None, call)
35
- return result.replace("```", "").strip()
 
 
 
 
 
 
 
 
 
 
 
 
1
  import asyncio
2
+ import logging
3
+
4
  from app.config import GEMINI_API_KEY
5
+
6
+ import google.genai as genai
7
+ from google.api_core.exceptions import GoogleAPIError
8
+
9
+ _SUMMARY_MODEL = "gemini-1.5-flash"
10
+ _gemini_client = None
11
 
12
  if GEMINI_API_KEY:
13
+ try:
14
+ _gemini_client = genai.Client(api_key=GEMINI_API_KEY)
15
+ logging.info(f"[summary_service] Initialized google.genai client with model={_SUMMARY_MODEL}")
16
+ except Exception as e:
17
+ logging.exception(f"[summary_service] Failed to init google.genai client: {e}")
18
+ _gemini_client = None
19
  else:
20
+ logging.warning("[summary_service] GEMINI_API_KEY is not set, summary will be empty")
21
 
22
 
23
  async def generate_summary(text: str) -> str:
24
+ """
25
+ Tạo tóm tắt ngắn gọn 3-5 câu, một đoạn văn duy nhất.
26
+ Fallback: trả "" nếu không có model hoặc lỗi.
27
+ """
28
+ if not _gemini_client:
29
  return ""
30
 
31
  prompt = f"""
32
+ Bạn là chuyên gia tóm tắt. Hãy tóm tắt văn bản sau thành một đoạn văn duy nhất.
33
+
34
+ Yêu cầu:
35
+ 1. Viết khoảng 3-5 câu, tổng hợp đầy đủ chủ đề các ý chính.
36
+ 2. Viết liền mạch, KHÔNG xuống dòng, KHÔNG dùng gạch đầu dòng hay đánh số.
37
+ 3. Chỉ dựa trên thông tin được cung cấp, tuyệt đối KHÔNG tự thêm thông tin bên ngoài.
38
+ 4. Trả về VĂN BẢN THUẦN (plain text), không bọc trong ``` hoặc JSON.
39
+
40
+ Văn bản:
41
+ \"\"\"{text}\"\"\"
42
+ """
43
 
44
  loop = asyncio.get_event_loop()
45
 
46
  def call():
47
+ resp = _gemini_client.models.generate_content(
48
+ model=_SUMMARY_MODEL,
49
+ contents=prompt,
50
+ )
51
+ return (resp.text or "").strip()
52
+
53
+ try:
54
+ result = await loop.run_in_executor(None, call)
55
+ # clean backticks nếu model có lỡ bọc
56
+ return result.replace("```", "").strip()
57
+ except GoogleAPIError as e:
58
+ logging.error(f"[summary_service] Gemini API error: {e}")
59
+ except Exception as e:
60
+ logging.exception(f"[summary_service] generate_summary failed: {e}")
61
+
62
+ return ""