forum_parser.py
4.54 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
Forum 日志解析器
解析 forum.log 文件,提取结构化的讨论记录用于构建知识图谱。
"""
from dataclasses import dataclass
from typing import List, Optional
import re
@dataclass
class ForumEntry:
"""论坛讨论条目"""
timestamp: str
speaker: str
content: str
@property
def is_host(self) -> bool:
"""是否为主持人发言"""
return self.speaker.upper() == 'HOST'
@property
def is_system(self) -> bool:
"""是否为系统消息"""
return self.speaker.upper() == 'SYSTEM'
@property
def engine_name(self) -> Optional[str]:
"""获取对应的引擎名称(小写)"""
speaker_upper = self.speaker.upper()
if speaker_upper in ['INSIGHT', 'MEDIA', 'QUERY', 'HOST']:
return speaker_upper.lower()
return None
class ForumParser:
"""
Forum 日志解析器
解析 forum.log,提取结构化的讨论记录。
日志格式: [HH:MM:SS] [SPEAKER] content
"""
# 匹配日志行的正则表达式
PATTERN = re.compile(r'\[(\d{2}:\d{2}:\d{2})\]\s*\[(\w+)\]\s*(.+)')
# 有效的发言者
VALID_SPEAKERS = {'INSIGHT', 'MEDIA', 'QUERY', 'HOST', 'SYSTEM'}
def parse(self, forum_logs: str) -> List[ForumEntry]:
"""
解析 forum.log 内容
Args:
forum_logs: forum.log 文件内容
Returns:
ForumEntry 列表
"""
if not forum_logs:
return []
entries = []
for line in forum_logs.strip().split('\n'):
if not line.strip():
continue
match = self.PATTERN.match(line)
if match:
timestamp, speaker, content = match.groups()
speaker_upper = speaker.upper()
if speaker_upper in self.VALID_SPEAKERS:
# 处理转义的换行符
content = content.replace('\\n', '\n')
entries.append(ForumEntry(
timestamp=timestamp,
speaker=speaker_upper,
content=content
))
return entries
def get_host_insights(self, entries: List[ForumEntry]) -> List[str]:
"""
提取 Host(主持人)的发言内容
Args:
entries: ForumEntry 列表
Returns:
Host 发言内容列表
"""
return [e.content for e in entries if e.is_host]
def get_engine_entries(self, entries: List[ForumEntry],
engine: str) -> List[ForumEntry]:
"""
获取指定引擎的发言
Args:
entries: ForumEntry 列表
engine: 引擎名称 (insight/media/query/host)
Returns:
该引擎的 ForumEntry 列表
"""
engine_upper = engine.upper()
return [e for e in entries if e.speaker == engine_upper]
def get_summary_by_engine(self, entries: List[ForumEntry]) -> dict:
"""
按引擎分组统计发言
Args:
entries: ForumEntry 列表
Returns:
{engine: [contents]} 字典
"""
result = {
'insight': [],
'media': [],
'query': [],
'host': []
}
for entry in entries:
engine = entry.engine_name
if engine and engine in result:
result[engine].append(entry.content)
return result
def extract_key_points(self, entries: List[ForumEntry],
max_points: int = 10) -> List[str]:
"""
提取关键观点(优先 Host 发言)
Args:
entries: ForumEntry 列表
max_points: 最大提取数量
Returns:
关键观点列表
"""
key_points = []
# 优先提取 Host 的发言
for entry in entries:
if entry.is_host and not entry.is_system:
# 提取前 200 字作为摘要
summary = entry.content[:200]
if len(entry.content) > 200:
summary += '...'
key_points.append(f"[{entry.speaker}] {summary}")
if len(key_points) >= max_points:
break
return key_points