尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Dynamic Filtering:解决大语言模型代码生成中的“脑补”现象

Dynamic Filtering:解决大语言模型代码生成中的“脑补”现象 1. 当模型开始“脑补”一个令人头疼的代码生成现象最近在折腾大语言模型生成代码时我遇到了一个特别典型又让人哭笑不得的问题。场景是这样的我需要模型帮我写一个Python函数功能是解析一个网页表格提取其中的数字列并计算总和。按理说这是个非常明确的任务。我给了模型一个示例网页的HTML结构甚至标明了目标数据在哪个td标签里。模型信心满满地回复“好的我理解了。我将使用BeautifulSoup解析HTML定位到id为>table idfinancial-data theadtrth日期/thth收入/thth支出/th/tr/thead tbody trtd2023-10-01/tdtd1,200.50/tdtd850.00/td/tr trtd2023-10-02/tdtd950.00/tdtd1,100.00/td/tr trtd2023-10-03/tdtdN/A/tdtd700.50/td/tr /tbody /table模糊指令“写Python代码提取上面表格中‘收入’列的总和。”模型可能“脑算”出的问题代码from bs4 import BeautifulSoup import re html “”” ... (上面的HTML) ... “”” soup BeautifulSoup(html, ‘html.parser’) table soup.find(‘table’, {‘id’: ‘financial-data’}) rows table.find_all(‘tr’)[1:] # 跳过表头 total_income 0 for row in rows: cols row.find_all(‘td’) income_text cols[1].text # 脑补第二列是收入 # 可能错误地处理了‘N/A’或千分位逗号 if income_text ! ‘N/A’: income float(income_text.replace(‘,’, ‘’)) total_income income print(total_income)问题cols[1]可能因为thead和tbody的标签结构而不准确没有稳健地处理“N/A”和千分位格式代码脆弱。应用Dynamic Filtering的重构提示“你是一个稳健的数据提取助手。请严格按照以下步骤处理提供的HTML表格数据并生成最终代码。步骤1 结构探查与分析请分析提供的HTML字符串专注于id为financial-data的表格。请输出 a. 该表格的完整CSS选择器路径。 b. 表头(th)的所有文本内容列表。 c. 第一个数据行(tbody下的第一个tr)的所有td单元格的文本内容列表。 d. 指出‘收入’这一列在表头列表中的索引位置从0开始。步骤2 设计健壮的提取逻辑基于步骤1的分析设计提取逻辑。请考虑 a. 如何准确定位到所有数据行避免包含表头行 b. 如何根据表头索引稳定地获取每一行的‘收入’单元格 c. ‘收入’单元格文本可能包含‘N/A’、千分位逗号‘,’、货币符号等。设计一个函数parse_income(text: str) - float | None来处理这些情况无法解析时返回None。 d. 如何安全地求和忽略None值步骤3 生成最终代码根据步骤2的设计编写一个完整的Python函数calculate_total_income(html_string: str) - float。要求函数必须包含必要的导入BeautifulSoup。必须包含你设计的parse_income辅助函数。在主要函数中先打印出表头列表和找到的数据行数进行验证。遍历时如果parse_income返回None则打印一条警告信息如“Warning: Could not parse income value: {text}”。最终返回总和。请按顺序输出步骤1的探查结果然后输出步骤3的完整代码。”模型基于此提示生成的代码示意将会更健壮from bs4 import BeautifulSoup def parse_income(text: str): “”“尝试将文本解析为收入浮点数处理N/A和逗号。”“” text text.strip() if text.upper() ‘N/A’ or text ‘’: return None # 移除千分位逗号和可能的货币符号简单示例 cleaned text.replace(‘,’, ‘’).replace(‘$’, ‘’).replace(‘¥’, ‘’) try: return float(cleaned) except ValueError: return None def calculate_total_income(html_string: str) - float: soup BeautifulSoup(html_string, ‘html.parser’) table soup.select_one(‘table#financial-data’) if not table: raise ValueError(“Table with id ‘financial-data’ not found”) # 1. 定位表头确定‘收入’索引 header_row table.find(‘thead’).find(‘tr’) if table.find(‘thead’) else table.find(‘tr’) headers [th.get_text(stripTrue) for th in header_row.find_all([‘th’, ‘td’])] # 兼容写法 print(f“Table headers: {headers}”) try: income_col_idx headers.index(‘收入’) except ValueError: # 如果表头不是‘收入’尝试其他常见名称 for idx, h in enumerate(headers): if ‘收入’ in h or ‘income’ in h.lower(): income_col_idx idx break else: raise ValueError(“‘收入’ column not found in table headers”) # 2. 定位所有数据行 data_rows table.find(‘tbody’).find_all(‘tr’) if table.find(‘tbody’) else table.find_all(‘tr’)[1:] print(f“Number of data rows found: {len(data_rows)}”) # 3. 遍历提取和求和 total 0.0 for row in data_rows: cells row.find_all(‘td’) if len(cells) income_col_idx: cell_text cells[income_col_idx].get_text(stripTrue) income_val parse_income(cell_text) if income_val is None: print(f“Warning: Could not parse income value: ‘{cell_text}’“) else: total income_val else: print(f“Warning: Row does not have enough columns for income index {income_col_idx}”) return total # 探查结果模型会先输出这个 # 步骤1 # a. 选择器table#financial-data # b. 表头: [‘日期’ ‘收入’ ‘支出’] # c. 第一行数据: [‘2023-10-01’ ‘1,200.50’ ‘850.00’] # d. ‘收入’索引: 1通过这样的Dynamic Filtering提示我们得到的不再是一个脆弱的脚本而是一个包含错误处理、数据验证、灵活解析的健壮函数。模型被强制进行了“探查-设计-实现”的完整思考链输出结果的质量和可靠性得到了质的提升。5. 高级技巧与集成框架将Dynamic Filtering融入工作流掌握了基本战术后我们可以将其系统化融入到更大的AI编码工作流中这里涉及到一些高级思路和工具链的配合。5.1 思维链Chain-of-Thought与自我反思的结合最强大的Dynamic Filtering往往要求模型进行多步推理并自我检查。我们可以设计一个多轮对话的提示模板第一轮分析与计划“给定任务X和输入数据Y请列出完成此任务所需的关键步骤、潜在难点以及你将如何验证每一步的正确性。请以清单形式输出。”第二轮草稿与风险点“根据你的计划现在生成实现第一个关键步骤的代码草稿。明确指出这段草稿代码基于哪些假设以及哪些地方最容易出错。”第三轮基于假设的验证“现在请编写一个小的测试代码块用于验证你上述代码草稿中的核心假设例如数据格式是否如预期。如果验证失败代码应如何降级处理”第四轮合成与最终输出“综合前三轮的思考现在输出完整的、健壮的最终代码并附上简单的使用示例。”这种多轮交互模拟了人类的“设计-评审-测试-重构”流程极大地压缩了模型“脑算”的空间。5.2 与代码解释器Code Interpreter或工具使用Tool Use结合如果环境允许例如OpenAI的GPT-4 with Code Interpreter或Claude的Tool Use功能Dynamic Filtering的威力能发挥到极致。你可以直接要求模型“我将给你一份数据CSV/JSON。请你先编写Python代码来加载和探索这份数据输出数据形状、列名、前几行样本以及基本的统计信息。根据探索结果我们再讨论下一步的分析任务。”模型生成的探索代码会被实际执行执行结果真实的数据信息会反馈给它。这样它后续生成的所有分析、清洗、可视化代码都基于真实数据彻底杜绝了“脑算”。这本质上是将Dynamic Filtering中的“验证”环节自动化、实时化了。5.3 构建可复用的提示模板库针对常见的任务类型可以提前构建好Dynamic Filtering提示模板。例如API调用生成模板要求模型先输出拟调用的API端点、所需参数结构然后基于此生成代码并包含参数验证和错误处理。数据清洗模板要求模型先识别数据中的具体问题如缺失值格式、异常值模式再针对每个问题编写特定的处理函数。正则表达式生成模板不直接让模型写正则而是让它先输出几个正面和反面匹配示例然后基于示例生成正则表达式并附带测试用例。将这些模板保存下来遇到类似任务时稍作修改即可使用能极大提升效率和输出质量。6. 避坑指南Dynamic Filtering实践中常见的陷阱尽管Dynamic Filtering很强大但使用不当也会事倍功半。下面是一些我踩过坑后总结的注意事项。6.1 提示词过于复杂导致模型迷失Dynamic Filtering提示词往往较长。如果一次性提出太多步骤和约束模型可能会忽略其中一些或者产生混乱的输出。对策是“循序渐进”。对于复杂任务先进行一轮高层次的规划对话“这个任务可以分解为哪几个模块”再针对每个模块应用Dynamic Filtering。或者使用分隔符如---清晰地划分指令的不同部分。6.2 模型“绕过”约束依然输出脑补内容有时即使你要求分步输出模型还是会急于给出最终答案把中间步骤一笔带过。对策是强化输出格式指令。使用非常明确的格式要求例如“你的输出必须严格遵循以下格式不要有任何偏离 【步骤1分析开始】 ...你的分析内容... 【步骤1分析结束】 【步骤2代码开始】 ...你的代码... 【步骤2代码结束】” 甚至可以要求模型在每一步开始时重复你的指令关键词如“现在我开始步骤1结构探查...”。6.3 对“未知未知”的无力Dynamic Filtering能很好地处理你能预见的问题格式混乱、索引偏差但如果数据中出现完全出乎意料的模式比如嵌套了五层的奇怪div结构代替了table模型基于你提示生成的逻辑可能依然会失败。对策是强调“防御性编程”和“探索性代码”。在提示中要求模型“如果首选定位方法失败请尝试备用方案如使用更通用的选择器或基于文本内容匹配。” 或者要求它生成一段先进行“数据探测模式识别”的代码。6.4 成本与时间的增加分步思考、多轮对话意味着更多的token消耗和更长的交互时间。对于简单、明确的任务过度使用Dynamic Filtering可能是一种浪费。关键在于权衡。对于核心业务逻辑、数据处理管道等关键代码投入时间做Dynamic Filtering是值得的。对于一次性的、简单的脚本或许直接生成并人工快速检查更高效。7. 总结与个人心得让模型成为可靠的代码协作者经过大量项目实践我的体会是Dynamic Filtering不仅仅是一组提示技巧更是一种与AI协作的思维模式转变。我们不再把模型看作一个“问答机”输入问题期待它吐出完美答案。而是把它看作一个需要严格需求和清晰上下文才能出色工作的初级程序员。我们的角色从“提问者”变成了“技术负责人”或“产品经理”需要需求分析把模糊的自然语言需求分解成清晰、无歧义的具体任务。架构设计为任务设计实现步骤和约束框架Dynamic Filtering提示词就是这个框架。代码评审审查模型生成的代码重点关注其是否严格遵循了框架逻辑是否健壮。集成测试将生成的代码放入真实环境运行完成最后一道验证。这个过程初期会觉得比直接问要麻烦但一旦形成习惯你会发现它带来的代码质量提升是巨大的。它显著减少了后续调试的时间生成的代码更易于理解和维护。更重要的是它让AI的产出变得可预测、可控制。最后分享一个小技巧在编写复杂的Dynamic Filtering提示时我自己会先像写测试用例一样在脑子里过一遍各种正常和异常的输入场景。把这些场景的应对期望也写进提示词里比如“如果数据为空怎么办”“如果网络请求超时代码应该如何重试或报错”。这样训练出来的模型代码才会真正具备工业级的鲁棒性。让模型“老老实实写代码”的秘诀就在于我们用提示词为它搭建一个“老老实实思考”的轨道。Dynamic Filtering就是那根最关键的轨道。
返回列表