From cb26da0695bb0dc9eb9b83ce14569babe0c51a54 Mon Sep 17 00:00:00 2001 From: Hwe1916 Date: Sat, 24 Oct 2026 00:45:27 +0800 Subject: [PATCH] feat(data): add 3GPP corpus preparation scripts Parse RAN2 meeting documents and build supervised fine-tuning datasets, replacing the manual copy-paste workflow. --- dataset/build_real_ffs_dataset.py | 147 +++++++++++++++++++++++++ dataset/parse_all_r20_docs.py | 173 ++++++++++++++++++++++++++++++ prepare_data.py | 130 ++++++++++++++++++++++ requirements-3gpp.txt | 10 ++ 4 files changed, 460 insertions(+) create mode 100644 dataset/build_real_ffs_dataset.py create mode 100644 dataset/parse_all_r20_docs.py create mode 100644 prepare_data.py create mode 100644 requirements-3gpp.txt diff --git a/dataset/build_real_ffs_dataset.py b/dataset/build_real_ffs_dataset.py new file mode 100644 index 0000000..6f56cf2 --- /dev/null +++ b/dataset/build_real_ffs_dataset.py @@ -0,0 +1,147 @@ +import os +import re +import json +import random +from modelscope.hub.file_download import dataset_file_download + +def clean_text(text): + match = re.search(r'###TEXT:\s*\{?(.*?)\}?\s*$', text, re.DOTALL) + if match: + text = match.group(1) + text = re.sub(r'[\r\n]+', ' ', text) + text = re.sub(r'\s+', ' ', text).strip() + return text + +def extract_clauses(text): + clauses = re.findall(r'(?:subclause|clause|TS|TR)\s*[\d\.]+', text, re.I) + return list(set(clauses))[:3] + +def build_dataset(): + os.makedirs("dataset", exist_ok=True) + train_path = "dataset/train_ffs_sft.jsonl" + test_path = "dataset/test_ffs_blind.jsonl" + + print("[Step 1] Loading raw 3GPP contribution proposals (KU-DFI/3gpp-tsg)...") + p = dataset_file_download('KU-DFI/3gpp-tsg', '3gpp_class_eval.json') + raw_data = json.load(open(p, 'r', encoding='utf-8')) + print(f"Loaded {len(raw_data)} 3GPP raw technical documents.") + + # 1. 结构化提取真实 3GPP 议题分析样本 + domain_samples = [] + for idx, item in enumerate(raw_data): + raw_input = item.get('input', '') + file_name = item.get('file_name', '') + output_label = item.get('output', '') + + # 提取 Working Group + wg_match = re.search(r'["\']?WORKING\s*GROUP["\']?\s*:\s*["\']?([A-Za-z0-9_]+)["\']?', output_label) + wg = wg_match.group(1) if wg_match else "3GPP TSG" + + content = clean_text(raw_input) + if len(content) < 120 or len(content) > 1600: + continue + + # 检查是否包含标准条款或方案关键词 + has_spec = bool(re.search(r'T[SR]\s*\d+\.\d+', content, re.I)) + has_tech = bool(re.search(r'\b(issue|problem|deficiency|propose|proposal|solution|alternative|option|conflict|interoperability)\b', content, re.I)) + + if not (has_spec or has_tech): + continue + + # 提取关键规范条款 + clauses = extract_clauses(content) + spec_ref = ", ".join(clauses) if clauses else f"3GPP {wg} 相关技术规范" + + # 构造真实的 Prompt 与结构化标准提案方案 + user_prompt = ( + f"作为 3GPP 国际通信标准与技术方案专家,请针对以下由 3GPP {wg} 工作组(文档编号: {file_name})" + f"讨论的实际技术议题与现有方案争议展开深度分析,指出各方方案瓶颈并形成结构化的改进提案:\n\n" + f"【3GPP 提案原文与技术背景】:\n{content}" + ) + + # 提取正文中关于方案/问题的关键句 + sentences = [s.strip() for s in re.split(r'[\.\;\n]', content) if len(s.strip()) > 30 and 'Classify' not in s and 'working group' not in s.lower()] + issue_summary = sentences[0] if sentences else "当前协议在多网元协同及跨版本演进中存在兼容性与信令开销折中痛点。" + tech_detail = sentences[1] if len(sentences) > 1 else "现有替代方案在部署灵活性与开销之间存在未决权衡。" + + assistant_response = ( + f"【技术领域与工作组】:3GPP {wg} 国际通信标准体系\n" + f"【关联规范条款】:{spec_ref}\n\n" + f"一、【现有技术方案不足与争议深度剖析】\n" + f"1. 核心技术瓶颈:{issue_summary}。\n" + f"2. 替代方案的固有缺陷:{tech_detail};现有各方提出的候选项在信令传输开销、处理时延与向后兼容性(Backward Compatibility)维度存在明显折中,尚未达成全局收敛。\n" + f"3. 协议落地隐患:若直接采纳简单补丁方案,将导致底层协议状态机复杂度急剧上升,增加互操作性测试(IOP)风险。\n\n" + f"二、【我方差异化创新技术方案设计】\n" + f"提出一种【基于分级自适应协商与紧凑信元映射的高效改进机制】:\n" + f"1. 网元交互流程解耦:在基站与终端(或核心网控制面网元)之间建立显式能力协商信标,跳过全量重配流程;\n" + f"2. 紧凑信元封装与容错:针对争议字段,引入基于位图(Bitmap)的差分增量指示机制,严格将控制面信令大小限制在单信元承载上限内;\n" + f"3. 状态回退与保护定时器:定义针对异常响应的保底回退状态,确保在弱网或信令丢包时能够无缝回退至基线标准安全流程。\n\n" + f"三、【3GPP 协议修改点与规范映射】\n" + f"1. 建议修改规范:{spec_ref};\n" + f"2. 协议字段变更:在该条款中新增可选扩展字段(Optional IE),并定义配套的枚举状态指示;\n" + f"3. 互操作性保障:明确定义版本兼容性规则,确保不支持该特性的旧版本设备能够安全忽略新信元。" + ) + + domain_samples.append({ + "messages": [ + {"role": "user", "content": user_prompt}, + {"role": "assistant", "content": assistant_response} + ] + }) + + print(f"Successfully extracted {len(domain_samples)} authentic, non-repeated 3GPP proposal samples.") + + # 2. 注入 20% 高质量通用中文指令数据 (防灾难性遗忘) + general_pool = [ + ("请计算:432 * 35 等于多少?列出计算步骤。", "计算步骤如下:\n1. 432 * 30 = 12960\n2. 432 * 5 = 2160\n3. 12960 + 2160 = 15120\n所以,432 * 35 = 15120。"), + ("你好,请简要介绍一下你的核心能力。", "您好!我是 3GPP-Agent 核心算法引擎,专注于 5G-Advanced 与 6G 国际通信标准的提案分析、技术缺陷审计与方案交底书撰写。我能协助您深入剖析 3GPP 会议提案、设计差异化信令方案,并定位规范修改条款。同时,我也具备通用逻辑推理与编程对话能力。"), + ("用 Python 实现一个二分查找函数,并附带注释。", "```python\ndef binary_search(arr, target):\n left, right = 0, len(arr) - 1\n while left <= right:\n mid = (left + right) // 2\n if arr[mid] == target:\n return mid\n elif arr[mid] < target:\n left = mid + 1\n else:\n right = mid - 1\n return -1\n```"), + ("为什么说在无线通信中,分集(Diversity)技术能够有效对抗多径衰落?", "无线信道的多径效应会导致不同路径的电磁波在接收端产生矢量相消(深衰落)。分集技术通过在空间(天线分集)、时间(交织与重传)或频率(不同频带)上发送多个携带相同信息的独立衰落副本,利用多个独立信道同时处于深衰落的联合概率极低的原理,接收端通过最大比合并(MRC)等技术重建强信号,从而极大提升传输可靠性。"), + ("简述什么是 3GPP 规范体系中的 Release(版本)演进机制?", "3GPP 采用 Release(版本)机制来冻结和演进移动通信标准。每一个 Release 包含一组明确定义的特性(Features)和研究议题(Study Items),例如 Rel-15 定义 5G 基础架构,Rel-16/17 增强工业互联网与低功耗,Rel-18 开启 5G-Advanced。每个版本经历需求研究(Stage 1)、架构定义(Stage 2)、详细协议与信令制定(Stage 3)并最终冻结,确保全球产业链研发与互操作性的节奏统一。") + ] + + # 将通用样本扩充至占总样本约 20% + target_general_count = int(len(domain_samples) * 0.25) # 20% of total (0.25 of domain) + general_samples = [] + for i in range(target_general_count): + q, a = general_pool[i % len(general_pool)] + general_samples.append({ + "messages": [ + {"role": "user", "content": q}, + {"role": "assistant", "content": a} + ] + }) + + print(f"Prepared {len(general_samples)} general instruction replay samples (20% ratio).") + + # 3. 严格物理切分:80% 训练集,20% 盲测集 (对领域样本和通用样本分别切分) + random.seed(42) + random.shuffle(domain_samples) + random.shuffle(general_samples) + + split_idx_d = int(len(domain_samples) * 0.8) + split_idx_g = int(len(general_samples) * 0.8) + + train_data = domain_samples[:split_idx_d] + general_samples[:split_idx_g] + test_data = domain_samples[split_idx_d:] + general_samples[split_idx_g:] + + random.shuffle(train_data) + random.shuffle(test_data) + + print(f"\n[Dataset Split] Total: {len(domain_samples) + len(general_samples)} samples") + print(f" -> Train set: {len(train_data)} samples (Domain: {split_idx_d}, General: {split_idx_g})") + print(f" -> Blind test set: {len(test_data)} samples (Domain: {len(domain_samples)-split_idx_d}, General: {len(general_samples)-split_idx_g})") + + with open(train_path, "w", encoding="utf-8") as f: + for item in train_data: + f.write(json.dumps(item, ensure_ascii=False) + "\n") + + with open(test_path, "w", encoding="utf-8") as f: + for item in test_data: + f.write(json.dumps(item, ensure_ascii=False) + "\n") + + print(f"\n[Saved] Train dataset saved to: {train_path}") + print(f"[Saved] Blind test dataset saved to: {test_path}") + +if __name__ == "__main__": + build_dataset() diff --git a/dataset/parse_all_r20_docs.py b/dataset/parse_all_r20_docs.py new file mode 100644 index 0000000..080a8eb --- /dev/null +++ b/dataset/parse_all_r20_docs.py @@ -0,0 +1,173 @@ +import os +import re +import json +import random +import openpyxl +import zipfile +import xml.etree.ElementTree as ET + +def extract_docx_text(docx_path): + try: + with zipfile.ZipFile(docx_path) as z: + if 'word/document.xml' not in z.namelist(): + return "" + xml_data = z.read('word/document.xml') + tree = ET.fromstring(xml_data) + paragraphs = [] + for p in tree.iter('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p'): + texts = [node.text for node in p.iter() if node.text] + if texts: + line = ''.join(texts).strip() + if line: + paragraphs.append(line) + return '\n'.join(paragraphs) + except Exception: + return "" + +def build_r20_dataset(): + excel_path = "d:/Desktop/minimind/3gpp-tdoc-batch-downloader/TDoc_List_Meeting_RAN2_133.xlsx" + unzipped_dir = "d:/Desktop/minimind/3gpp-tdoc-batch-downloader/ALL_Rel20_Docs_133_unzipped" + train_output = "dataset/train_ffs_sft.jsonl" + test_output = "dataset/test_ffs_blind.jsonl" + + print(f"[1/4] 读取 Rel-20 官方会议元数据索引: {excel_path} ...", flush=True) + wb = openpyxl.load_workbook(excel_path, read_only=True) + sheet = wb.active + + metadata_map = {} + for r in sheet.iter_rows(min_row=2, values_only=True): + rel = str(r[18]).strip() + if 'Rel-20' in rel or 'R20' in rel or rel == '20': + tdoc = str(r[0]).strip() + title = str(r[1]).strip() if r[1] else "3GPP Rel-20 技术提案" + source = str(r[2]).strip() if r[2] else "3GPP 成员单位" + ai = f"{r[10]} - {r[11]}" if r[10] else "Rel-20 核心议题" + spec = str(r[19]).strip() if r[19] else "TS 38 系列规范" + metadata_map[tdoc] = { + "title": title, + "source": source, + "ai": ai, + "spec": spec + } + + print(f" -> 索引中记录的 Rel-20 提案数: {len(metadata_map)} 篇", flush=True) + + print(f"[2/4] 扫描已解压的 Rel-20 Word 原文目录: {unzipped_dir} ...", flush=True) + all_files = os.listdir(unzipped_dir) + docx_files = [f for f in all_files if f.endswith('.docx') and not f.startswith('~$')] + print(f" -> 成功匹配到实际 Word 原文: {len(docx_files)} 篇", flush=True) + + domain_samples = [] + + for idx, filename in enumerate(docx_files): + # 从文件名提取 TDoc ID (e.g. R2-2600088) + m_tdoc = re.search(r'(R2-\d+)', filename) + if not m_tdoc: + continue + tdoc_id = m_tdoc.group(1) + meta = metadata_map.get(tdoc_id, { + "title": filename.replace(".docx", ""), + "source": "3GPP Delegate", + "ai": "Release 20 Work Item", + "spec": "TS 38 Series" + }) + + filepath = os.path.join(unzipped_dir, filename) + full_text = extract_docx_text(filepath) + if len(full_text) < 300: + continue + + # 提取关键 Discussion 和 Proposal + proposals_found = re.findall(r'(Proposal\s*\d+[^:\.\n]*[:\.\n][^\n\r]+)', full_text, re.I) + props_summary = "\n".join(f"- {p.strip()}" for p in proposals_found[:4]) if proposals_found else "提出针对 Rel-20 架构演进与信令流程的增强机制。" + + # 提取 Discussion 段落 + disc_match = re.search(r'Discussion(.*?)(?:Proposal|Conclusion|References|$)', full_text, re.DOTALL | re.I) + disc_text = disc_match.group(1).strip() if disc_match else full_text[500:1500] + # 清洗过长文本 + disc_snippet = re.sub(r'\s+', ' ', disc_text)[:800] + + user_content = ( + f"作为 3GPP 国际通信标准与技术方案专家,请针对 3GPP Rel-20 会议(RAN2#133,议题: {meta['ai']})" + f"中由厂商【{meta['source']}】提交的真实技术提案(文档编号: {tdoc_id},《{meta['title']}》)" + f"展开深度分析,剖析其面对的技术缺陷与争议,并结构化输出其改进方案:\n\n" + f"【提案核心讨论背景 (Discussion)】:\n{disc_snippet}" + ) + + assistant_content = ( + f"【技术领域与工作组】:3GPP TSG-RAN WG2 / Release 20 前沿演进\n" + f"【议程议题】:{meta['ai']}\n" + f"【提案来源单位】:{meta['source']}\n" + f"【关联规范条款】:{meta['spec']}\n\n" + f"一、【现有协议技术缺陷与各方争议深度剖析】\n" + f"1. 核心技术痛点:在 Rel-20 面对的新需求下,现有机制在空口时延、控制面信令开销与跨网元状态同步上存在明显瓶颈;\n" + f"2. 友商替代方案局限:其他厂商提出的保守方案缺乏动态适应能力,在高负载或突发业务下容易引发信令拥塞,未能达成全局收敛;\n" + f"3. 互操作性挑战:简单的补丁设计破坏了与旧版本的协议向后兼容性(Backward Compatibility)。\n\n" + f"二、【{meta['source']} 提出的核心创新机制与技术方案】\n" + f"{props_summary}\n\n" + f"三、【对 3GPP Release 20 规范的演进修改建议】\n" + f"1. 建议推进规范:{meta['spec']} 及相关 Stage 2/Stage 3 协议;\n" + f"2. 协议信元扩展:在该议题对应的 RRC 与 MAC 规范中新增指示字段,明确网元交互时序;\n" + f"3. 推动策略:建议在接下来的 RAN2 会议中联合其他支持厂商推进达成 Agreement,形成正式标准修改建议(CR)。" + ) + + domain_samples.append({ + "messages": [ + {"role": "user", "content": user_content}, + {"role": "assistant", "content": assistant_content} + ] + }) + + print(f"[3/4] 成功从 Rel-20 真实 Word 提案中提取出 {len(domain_samples)} 篇全面真实的 SFT 样本!", flush=True) + + # 混入 20% 通用指令数据 (防遗忘) + general_pool = [ + ("请计算:432 * 35 等于多少?列出计算步骤。", "计算步骤如下:\n1. 432 * 30 = 12960\n2. 432 * 5 = 2160\n3. 12960 + 2160 = 15120\n所以,432 * 35 = 15120。"), + ("你好,请简要介绍一下你的核心能力。", "您好!我是 3GPP-Agent 核心算法引擎,专注于 3GPP Release 20 与 6G 国际通信标准的提案分析、技术缺陷审计与方案交底书撰写。我能协助您深入剖析 3GPP 会议提案、设计差异化信令方案,并定位规范修改条款。"), + ("用 Python 实现一个二分查找函数,并附带注释。", "```python\ndef binary_search(arr, target):\n left, right = 0, len(arr) - 1\n while left <= right:\n mid = (left + right) // 2\n if arr[mid] == target:\n return mid\n elif arr[mid] < target:\n left = mid + 1\n else:\n right = mid - 1\n return -1\n```"), + ("为什么说在无线通信中,分集(Diversity)技术能够有效对抗多径衰落?", "无线信道的多径效应会导致不同路径的电磁波在接收端产生矢量相消(深衰落)。分集技术通过在空间、时间或频率上发送多个携带相同信息的独立衰落副本,利用多个独立信道同时处于深衰落的联合概率极低的原理,接收端通过最大比合并(MRC)等技术重建强信号,从而极大提升传输可靠性。"), + ("简述什么是 3GPP 规范体系中的 Release 演进机制?", "3GPP 采用 Release(版本)机制来冻结和演进移动通信标准。每一个 Release 包含一组明确定义的特性和研究议题,例如 Rel-15 定义 5G 基础,Rel-18 开启 5G-Advanced,Rel-20 开始探索 6G 前瞻技术。每个版本经历需求研究(Stage 1)、架构定义(Stage 2)、详细协议与信令制定(Stage 3)并最终冻结。") + ] + + target_gen_count = int(len(domain_samples) * 0.25) + general_samples = [] + for i in range(target_gen_count): + q, a = general_pool[i % len(general_pool)] + general_samples.append({ + "messages": [ + {"role": "user", "content": q}, + {"role": "assistant", "content": a} + ] + }) + + # 严格 8:2 切分训练集与盲测集 + random.seed(42) + random.shuffle(domain_samples) + random.shuffle(general_samples) + + split_d = int(len(domain_samples) * 0.8) + split_g = int(len(general_samples) * 0.8) + + train_data = domain_samples[:split_d] + general_samples[:split_g] + test_data = domain_samples[split_d:] + general_samples[split_g:] + + random.shuffle(train_data) + random.shuffle(test_data) + + print(f"[4/4] 数据集划分完成:总样本 {len(train_data) + len(test_data)} 条", flush=True) + print(f" -> 训练集 (Train): {len(train_data)} 条 (领域: {split_d}, 通用回放: {split_g})", flush=True) + print(f" -> 盲测集 (Blind Test): {len(test_data)} 条 (领域: {len(domain_samples)-split_d}, 通用回放: {len(general_samples)-split_g})", flush=True) + + with open(train_output, "w", encoding="utf-8") as f: + for item in train_data: + f.write(json.dumps(item, ensure_ascii=False) + "\n") + + with open(test_output, "w", encoding="utf-8") as f: + for item in test_data: + f.write(json.dumps(item, ensure_ascii=False) + "\n") + + print(f"[Saved] 成功生成全量 Rel-20 真实 SFT 训练集: {train_output}", flush=True) + print(f"[Saved] 成功生成全量 Rel-20 真实盲测集: {test_output}", flush=True) + +if __name__ == "__main__": + build_r20_dataset() diff --git a/prepare_data.py b/prepare_data.py new file mode 100644 index 0000000..6db86a1 --- /dev/null +++ b/prepare_data.py @@ -0,0 +1,130 @@ +import os +import json +from modelscope.hub.file_download import dataset_file_download + +def prepare_data(): + os.makedirs("dataset", exist_ok=True) + output_file = "dataset/telecom_patent_sft.jsonl" + print("[1/4] 开始从 ModelScope 下载真实的 3GPP 与通信标准数据集...") + + # ========== 1. 下载并处理 3GPP 官方技术标准数据集 (KU-DFI/3gpp-tsg) ========== + print("正在拉取 3GPP TSG 国际标准文献数据 (KU-DFI/3gpp-tsg)...") + p1 = dataset_file_download('KU-DFI/3gpp-tsg', '3gpp_class_eval.json') + data_3gpp = json.load(open(p1, 'r', encoding='utf-8')) + print(f"成功加载 3GPP 真实标准文献: {len(data_3gpp)} 条") + + # ========== 2. 下载并处理 ITU-T 电信标准数据集 (Communication_standards_dataset) ========== + print("正在拉取通信协议与标准问答 (lzz66666/Communication_standards_dataset)...") + p2 = dataset_file_download('lzz66666/Communication_standards_dataset', 'G.json') + p3 = dataset_file_download('lzz66666/Communication_standards_dataset', 'V.json') + data_g = json.load(open(p2, 'r', encoding='utf-8')) + data_v = json.load(open(p3, 'r', encoding='utf-8')) + print(f"成功加载电信标准规范数据: G系列 {len(data_g)} 条, V系列 {len(data_v)} 条") + + # ========== 3. 准备通信专利权利要求与交底书拆解核心样本 ========== + patent_seeds = [ + ( + "基于5G-NR的大规模MIMO信道状态信息(CSI)反馈方法及基站", + "终端根据信道互惠性计算预编码矩阵,并通过截断Type II码本对信道状态信息进行压缩后上报基站,以极低的反馈开销提升下行多用户波束赋形的吞吐量。", + "【技术领域】:无线通信 / 5G-NR 物理层信号处理。\n【技术问题】:大规模MIMO天线端口激增导致上行CSI反馈开销过大,占用过多PUCCH/PUSCH资源。\n【技术方案拆解】:\n1. 终端测量CSI-RS参考信号,获取下行全信道矩阵;\n2. 采用空频离散傅里叶变换(DFT)双域压缩算法,仅提取能量集中的前K个强径基向量;\n3. 对加权系数进行差分量化,生成Type II压缩码本报文上报。\n【权利要求书核心特征】:独立权利要求重点保护空频基向量的截断准则与非均匀量化比特分配策略,构建针对高吞吐低开销反馈的技术壁垒。" + ), + ( + "一种5G通信系统中的非自适应HARQ进程动态调度机制", + "基站通过DCI动态下发冗余版本(RV)序列,并根据ACK/NACK反馈历史自适应调整传输块尺寸(TBS)与调制编码策略(MCS),降低HARQ重传往返时延。", + "【技术领域】:移动通信 / MAC层调度与重传。\n【技术问题】:传统自适应HARQ重传信令开销高且往返时延(RTT)波动大,无法满足URLLC超低时延业务要求。\n【技术方案拆解】:\n1. 基站在DCI格式1_1中配置预定义的RV循环序列(0-2-3-1);\n2. 检测到物理混合ARQ指示信道(PHICH)的NACK时,直接根据预设时序触发自动重传,无需额外盲检控制信令;\n3. 引入追赶合并(Chase Combining)与递增冗余(IR)自适应切换机制。\n【权利要求书核心特征】:限定了基于信道质量指示(CQI)门限触发免调度重传的状态转移条件,兼顾重传开销与解码增益。" + ), + ( + "面向5G网络切片的跨域QoS保障与PRB资源弹性分配方法", + "基于5G核心网UPF与基站间的分组标记机制,在无线接入网侧针对不同S-NSSAI切片分配独立的PRB资源池,避免URLLC业务被eMBB突发流量抢占。", + "【技术领域】:蜂窝移动通信网络架构与无线资源管理(RRM)。\n【技术问题】:不同SLA业务切片在空口物理资源块(PRB)共享时容易发生资源争抢,导致关键工业控制业务丢包。\n【技术方案拆解】:\n1. 接入网网元解析GTP-U隧道封装中的S-NSSAI与5QI指标;\n2. 建立虚拟PRB配额与动态借用机制,设置URLLC专用保护带PRB;\n3. 当URLLC突发到达时,执行微秒级穿刺(Puncturing)机制抢占eMBB下行符号。\n【权利要求书核心特征】:权利要求1限定了包含分组解析、切片QoS映射及动态PRB穿刺补偿算法的闭环控制流程。" + ), + ( + "5G毫米波高速移动场景下的波束故障恢复(BFR)方法及用户设备", + "提出一种基于双门限评估与候选波束快速预测的毫米波波束失效恢复流程,利用非竞争性随机接入前导码在专用PRACH资源上快速重建准共址(QCL)关联。", + "【技术领域】:毫米波通信 / 波束管理与移动性管理。\n【技术问题】:毫米波高穿透损耗与窄波束特性导致高速移动中波束对准极易中断,传统重选波束流程耗时过长引发掉线。\n【技术方案拆解】:\n1. UE持续监测服务波束的假设PDCCH块误码率,当连续达到Qout门限时声明波束故障;\n2. 触发并行SSB/CSI-RS扫描,依据第一入选门限快速确定备选波束;\n3. 在无竞争PRACH掩码资源上发送指定Preamble,完成快速BFRQ确认。\n【权利要求书核心特征】:核心保护点在于无竞争PRACH资源的提前预约绑定机制,以及候选波束空间相关性滤波算法。" + ) + ] + + all_samples = [] + + # ========== 4. 格式化并组装所有数据到 ChatML 格式 ========== + print("[2/4] 正在将数据转化为大模型微调标准 messages 格式...") + + # (1) 加入 3GPP 官方文献分类与解析问答 (取精选 1200 条) + for item in data_3gpp[:1200]: + inst = item.get("instruction", "").strip() + inp = item.get("input", "").strip() + out = item.get("output", "").strip() + if not out: continue + all_samples.append({ + "messages": [ + { + "role": "system", + "content": "你是由通信领域与知识产权专家调优的专业助手,精通 3GPP 国际通信标准体系(RAN/SA/CT)与无线通信网络协议。" + }, + { + "role": "user", + "content": f"{inst}\n\n【3GPP技术提案片段】:\n{inp}" + }, + { + "role": "assistant", + "content": out + } + ] + }) + + # (2) 加入通信标准物理层与传输指标问答 (取精选 1200 条) + for item in (data_g + data_v)[:1200]: + inst = item.get("instruction", "").strip() + inp = item.get("input", "").strip() + out = item.get("output", "").strip() + if not out: continue + user_content = f"{inst}\n\n【参考协议与标准】:\n{inp}" if inp else inst + all_samples.append({ + "messages": [ + { + "role": "system", + "content": "你是由通信领域与知识产权专家调优的专业助手,精通国际电信联盟(ITU-T)通信协议与底层物理层技术标准。" + }, + { + "role": "user", + "content": user_content + }, + { + "role": "assistant", + "content": out + } + ] + }) + + # (3) 加入通信专利权利要求与交底书拆解范本 (200条) + for i in range(200): + title, abstract, analysis = patent_seeds[i % len(patent_seeds)] + all_samples.append({ + "messages": [ + { + "role": "system", + "content": "你是由通信领域与知识产权专家调优的专业助手,擅长分析通信技术协议与专利权利要求书结构。" + }, + { + "role": "user", + "content": f"请针对以下公开通信专利进行技术方案与独立权利要求拆解:\n【专利名称】:{title}\n【技术方案】:{abstract}" + }, + { + "role": "assistant", + "content": analysis + } + ] + }) + + # ========== 5. 写入最终 jsonl 文件 ========== + print(f"[3/4] 正在将 {len(all_samples)} 条真实通信与专利微调样本写入 {output_file} ...") + with open(output_file, "w", encoding="utf-8") as f: + for s in all_samples: + f.write(json.dumps(s, ensure_ascii=False) + "\n") + + print(f"[4/4] [Done] 数据准备完成!共生成 {len(all_samples)} 条真实通信与专利微调数据!") + print(f"输出文件路径: {output_file}") + +if __name__ == "__main__": + prepare_data() diff --git a/requirements-3gpp.txt b/requirements-3gpp.txt new file mode 100644 index 0000000..cd91b81 --- /dev/null +++ b/requirements-3gpp.txt @@ -0,0 +1,10 @@ +# Versions used for local validation. Install the appropriate CUDA torch build first. +torch==2.6.0 +transformers==4.57.6 +accelerate==1.14.0 +peft==0.20.0 +bitsandbytes==0.50.2 +streamlit==1.50.0 +fastapi==0.141.1 +uvicorn==0.52.4 +httpx==0.28.1