chen666-666 commited on
Commit
fb7b761
·
verified ·
1 Parent(s): c64de64

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +11 -8
  2. app.py +91 -79
  3. requirements.txt +2 -4
Dockerfile CHANGED
@@ -1,10 +1,10 @@
1
- # 使用 python:3.10-slim 作为基础镜像
2
- FROM python:3.10-slim
3
 
4
  # 设置工作目录
5
  WORKDIR /app
6
 
7
- # 安装必要的系统依赖
8
  RUN apt-get update && apt-get install -y \
9
  libglib2.0-0 \
10
  libx11-6 \
@@ -17,17 +17,20 @@ RUN apt-get update && apt-get install -y \
17
  && apt-get clean \
18
  && rm -rf /var/lib/apt/lists/*
19
 
20
- # 复制当前目录到容器内
21
- COPY . /app
22
 
23
  # 安装 Python 依赖
24
  RUN pip install --no-cache-dir -r requirements.txt
25
 
26
- # 暴露端口(假设你的 Gradio 应用在 7860 端口运行)
 
 
 
27
  EXPOSE 7860
28
 
29
- # 设置环境变量
30
  ENV PYTHONUNBUFFERED=1
31
 
32
- # 设置默认命令
33
  CMD ["python", "app.py"]
 
1
+ # 使用更小的基础镜像 python:3.10-slim-buster,减少镜像体积
2
+ FROM python:3.10-slim-buster
3
 
4
  # 设置工作目录
5
  WORKDIR /app
6
 
7
+ # 安装系统依赖,包括图形库和中文字体
8
  RUN apt-get update && apt-get install -y \
9
  libglib2.0-0 \
10
  libx11-6 \
 
17
  && apt-get clean \
18
  && rm -rf /var/lib/apt/lists/*
19
 
20
+ # 复制 requirements.txt 文件先安装 Python 依赖,减少不必要的层
21
+ COPY requirements.txt /app/
22
 
23
  # 安装 Python 依赖
24
  RUN pip install --no-cache-dir -r requirements.txt
25
 
26
+ # 复制剩余应用代码到容器中
27
+ COPY . /app
28
+
29
+ # 暴露端口(假设 Gradio 应用在 7860 端口运行)
30
  EXPOSE 7860
31
 
32
+ # 设置环境变量,确保 Python 输出不缓冲
33
  ENV PYTHONUNBUFFERED=1
34
 
35
+ # 设置默认命令,启动应用
36
  CMD ["python", "app.py"]
app.py CHANGED
@@ -515,103 +515,115 @@ import os
515
  import logging
516
  from matplotlib import font_manager
517
 
518
- # 强制重新加载字体缓存(关键步骤!)
519
- import matplotlib
520
- import os
521
- from matplotlib import font_manager
522
-
523
- # 确保字体缓存重建
524
- font_cache_path = os.path.join(matplotlib.get_cachedir(), 'fontlist-v330.json')
525
- if os.path.exists(font_cache_path):
526
- os.remove(font_cache_path)
527
- matplotlib.font_manager._rebuild()
528
-
529
- # 验证字体是否安装成功
530
- print("=== 可用中文字体 ===")
531
- cjk_fonts = [f.name for f in font_manager.fontManager.ttflist
532
- if 'Noto Sans CJK' in f.name]
533
- print(cjk_fonts if cjk_fonts else "未找到Noto Sans CJK字体!")
534
 
535
  def generate_kg_image(entities, relations):
 
 
 
536
  try:
537
- import matplotlib.pyplot as plt
538
- import networkx as nx
539
- import tempfile
540
- import os
541
- from matplotlib import font_manager
542
-
543
- # === 1. 核弹级字体保障 ===
544
- # 方法1:使用Noto Sans CJK
545
- plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC']
 
546
  plt.rcParams['axes.unicode_minus'] = False
547
-
548
- # 方法2:如果仍然失败,使用最后手段
549
- try:
550
- # 测试字体是否有效
551
- plt.text(0.5, 0.5, "中文测试", fontsize=12)
552
- plt.close()
553
- except:
554
- print("主字体失效,启用备用方案...")
555
- # 使用系统默认字体(至少能显示部分字符)
556
- plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
557
-
558
  # === 2. 创建图谱 ===
559
  G = nx.DiGraph()
560
- entity_colors = {'PER': '#FF6B6B', 'ORG': '#4ECDC4', 'LOC': '#45B7D1'}
561
-
562
- # 添加节点(简化标签,只显示中文)
563
- for entity in entities:
564
- G.add_node(entity["text"],
565
- label=entity["text"], # 只显示中文名,不显示类型
566
- color=entity_colors.get(entity['type'], 'gray'))
567
 
568
- # 添加边
569
- for rel in relations:
570
- if rel["head"] in G.nodes and rel["tail"] in G.nodes:
571
- G.add_edge(rel["head"], rel["tail"], label=rel["relation"])
 
 
 
 
 
 
 
 
 
 
572
 
573
  # === 3. 绘图配置 ===
574
- plt.figure(figsize=(10, 6), dpi=120)
575
- pos = nx.spring_layout(G, k=0.8, seed=42)
576
-
577
- # 绘制节点(不带标签)
578
- nx.draw_networkx_nodes(G, pos,
579
- node_color=[G.nodes[n]['color'] for n in G.nodes],
580
- node_size=700)
581
-
582
- # 绘制边
583
- nx.draw_networkx_edges(G, pos,
584
- arrows=True,
585
- arrowsize=15,
586
- width=1.2)
587
-
588
- # === 4. 手动添加文本标签(绕过字体限制)===
589
- for node, (x, y) in pos.items():
590
- plt.text(x, y,
591
- node,
592
- fontsize=10,
593
- ha='center',
594
- va='center',
595
- bbox=dict(facecolor='white', alpha=0.7, edgecolor='none'))
596
-
597
- # 边标签(英文关系可能能显示)
 
 
598
  edge_labels = nx.get_edge_attributes(G, 'label')
599
- nx.draw_networkx_edge_labels(G, pos,
600
- edge_labels=edge_labels,
601
- font_size=8)
 
 
 
602
 
603
  plt.axis('off')
604
-
605
- # === 5. 保存图片 ===
606
- temp_dir = tempfile.mkdtemp()
 
607
  output_path = os.path.join(temp_dir, "kg.png")
 
 
 
 
608
  plt.savefig(output_path, bbox_inches='tight', pad_inches=0.1)
609
  plt.close()
610
-
611
  return output_path
612
 
613
  except Exception as e:
614
- print(f"[FATAL ERROR] {str(e)}")
615
  return None
616
 
617
 
 
515
  import logging
516
  from matplotlib import font_manager
517
 
518
+ # 这个函数用于查找并验证中文字体路径
519
+ def find_chinese_font():
520
+ # 尝试查找 Noto Sans CJK 字体
521
+ font_paths = [
522
+ "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc", # Noto CJK 字体
523
+ "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc" # 微软雅黑
524
+ ]
525
+
526
+ for font_path in font_paths:
527
+ if os.path.exists(font_path):
528
+ logging.info(f"Found font at {font_path}")
529
+ return font_path
530
+
531
+ logging.error("No Chinese font found!")
532
+ return None
 
533
 
534
  def generate_kg_image(entities, relations):
535
+ """
536
+ 中文知识图谱生成函数,支持自动匹配系统中的中文字体,避免中文显示为方框。
537
+ """
538
  try:
539
+ # === 1. 确保使用合适的中文字体 ===
540
+ chinese_font = find_chinese_font() # 调用查找字体函数
541
+ if chinese_font:
542
+ font_prop = font_manager.FontProperties(fname=chinese_font)
543
+ plt.rcParams['font.family'] = font_prop.get_name()
544
+ else:
545
+ # 如果字体路径未找到,使用默认字体(DejaVu Sans)
546
+ logging.warning("Using default font")
547
+ plt.rcParams['font.family'] = ['DejaVu Sans']
548
+
549
  plt.rcParams['axes.unicode_minus'] = False
550
+
 
 
 
 
 
 
 
 
 
 
551
  # === 2. 创建图谱 ===
552
  G = nx.DiGraph()
553
+ entity_colors = {
554
+ 'PER': '#FF6B6B', # 人物-红色
555
+ 'ORG': '#4ECDC4', # 组织-青色
556
+ 'LOC': '#45B7D1', # 地点-蓝色
557
+ 'TIME': '#96CEB4' # 时间-绿色
558
+ }
 
559
 
560
+ for entity in entities:
561
+ G.add_node(
562
+ entity["text"],
563
+ label=f"{entity['text']} ({entity['type']})",
564
+ color=entity_colors.get(entity['type'], '#D3D3D3')
565
+ )
566
+
567
+ for relation in relations:
568
+ if relation["head"] in G.nodes and relation["tail"] in G.nodes:
569
+ G.add_edge(
570
+ relation["head"],
571
+ relation["tail"],
572
+ label=relation["relation"]
573
+ )
574
 
575
  # === 3. 绘图配置 ===
576
+ plt.figure(figsize=(12, 8), dpi=150)
577
+ pos = nx.spring_layout(G, k=0.7, seed=42)
578
+
579
+ nx.draw_networkx_nodes(
580
+ G, pos,
581
+ node_color=[G.nodes[n]['color'] for n in G.nodes],
582
+ node_size=800,
583
+ alpha=0.9
584
+ )
585
+ nx.draw_networkx_edges(
586
+ G, pos,
587
+ edge_color='#888888',
588
+ width=1.5,
589
+ arrows=True,
590
+ arrowsize=20
591
+ )
592
+
593
+ node_labels = {n: G.nodes[n]['label'] for n in G.nodes}
594
+ nx.draw_networkx_labels(
595
+ G, pos,
596
+ labels=node_labels,
597
+ font_size=10,
598
+ font_family=font_prop.get_name() if chinese_font else 'SimHei',
599
+ font_weight='bold'
600
+ )
601
+
602
  edge_labels = nx.get_edge_attributes(G, 'label')
603
+ nx.draw_networkx_edge_labels(
604
+ G, pos,
605
+ edge_labels=edge_labels,
606
+ font_size=8,
607
+ font_family=font_prop.get_name() if chinese_font else 'SimHei'
608
+ )
609
 
610
  plt.axis('off')
611
+ plt.tight_layout()
612
+
613
+ # === 4. 保存图片 ===
614
+ temp_dir = tempfile.mkdtemp() # 确保在 Docker 容器中有权限写入
615
  output_path = os.path.join(temp_dir, "kg.png")
616
+
617
+ # 打印路径以方便调试
618
+ logging.info(f"Saving graph image to {output_path}")
619
+
620
  plt.savefig(output_path, bbox_inches='tight', pad_inches=0.1)
621
  plt.close()
622
+
623
  return output_path
624
 
625
  except Exception as e:
626
+ logging.error(f"[ERROR] 图谱生成失败: {str(e)}")
627
  return None
628
 
629
 
requirements.txt CHANGED
@@ -22,7 +22,7 @@ python-json-logger>=2.0.0
22
  # 知识图谱可视化
23
  networkx>=3.0
24
  pyvis>=0.3.0
25
- matplotlib>=3.7.0
26
  plotly>=5.10.0
27
 
28
  # 可选依赖(如果使用ChatGLM)
@@ -32,6 +32,4 @@ accelerate>=0.20.0
32
 
33
  # 其他依赖
34
  requests>=2.25.0
35
- beautifulsoup4>=4.10.0
36
-
37
- fonts-noto-cjk
 
22
  # 知识图谱可视化
23
  networkx>=3.0
24
  pyvis>=0.3.0
25
+ matplotlib>=3.5.0
26
  plotly>=5.10.0
27
 
28
  # 可选依赖(如果使用ChatGLM)
 
32
 
33
  # 其他依赖
34
  requests>=2.25.0
35
+ beautifulsoup4>=4.10.0