2026/9/6 10:07:33

用LLM给巴黎面包店巧克力面包排名:AI评价工作流全解析

用LLM给巴黎面包店巧克力面包排名:AI评价工作流全解析 一个用 LLM 给巴黎面包店巧克力面包排名的项目背后是完整的 AI 评价工作流这个项目的标题很有意思Show HN: I ranked every Paris bakerys pain au chocolat using an LLM。本质上作者做了一件事让 LLM 去评价巴黎几乎所有面包店的巧克力面包然后给出一个完整排名。听上去像是一篇美食博客但它其实是一个典型的LLM 真实场景应用案例数据采集、文本评分、结果排序、人工复核全链路用大模型驱动。这里没有简单地问“哪家面包店好吃”而是把评价标准、采样流程、数据格式、批量调用、结果稳定性和偏差控制都做了一遍。这类项目对技术读者的价值在于不是教你怎么烤面包而是教你怎么把 LLM 接入到带主观评价、多维度打分和排序的真实业务流程中。不管你是做本地评测、内容审核、商品评分还是任何需要结构化输出的文本分析这套思路都能直接套用。我从技术实现角度拆解这个项目分析了它在 LLM 使用上的关键环节、容易踩的坑、工程化改造方式以及如果你自己想做类似“LLM 全链路打分排序”项目应该从哪一步开始。1. 核心能力速览能力项说明项目类型LLM 驱动的真实世界数据采集、评价与排名核心任务对多个候选对象面包店做结构化评分并按维度排序关键模型能力文本理解、多维度评分、结构化 JSON 输出、稳定性控制数据采集复杂度中高涉及店铺名单、评分维度设计、抽样式采样硬件需求取决于所选模型云端 API 或本地部署均可启动方式非一键集成包需按数据流程编写脚本或工作流接口能力依赖所选 LLM 的 API可跑批量任务批量任务需要自行设计队列、重试与日志结果可靠性受模型偏差、样本量、评分维度设计影响需抽样复核适合读者对 LLM 实际落地、评价体系设计、批量文本分析感兴趣的技术人这个项目的门槛不在“显存”或“显卡”而在任务设计和工程流程。它能跑但跑得稳不稳取决于你怎么定义问题。2. 适用场景与使用边界这个项目把所有面包店的巧克力面包做排名看似小众但它代表的是一类通用需求用 LLM 对一组需要主观判断的对象做标准化、可复现的评价。典型适用场景包括商品评价与比价多个同类产品的参数、口碑、价格评分汇总。内容质量评测图文、视频脚本、音频转写文本的打分排序。本地生活服务点评餐厅、咖啡店、健身房的横向对比。内部数据质检客服对话、工单、报告文本的多维度评分。学术或行业榜单期刊、课程、开源项目的横向评测。这些场景的共同点是评价对象多、维度多、人工打分成本高、结果需要可解释。使用边界也很明确不要拿 LLM 的单一评分当最终结论。LLM 有偏好和幻觉它可能因为某个店铺名字带有“经典”“老字号”字样就给更高分。不要忽视采样偏差。项目的采样方式、时间段、面包新鲜程度都会影响评分。不涉及图像识别。除非额外接入视觉模型否则只看文本信息。版权和隐私边界店铺名称、地址、点评内容可能涉及第三方版权和隐私采集和使用要避免违反平台规则。若采集用户点评做训练或公开排名需确认授权范围。简单说这类项目适合做辅助评价和初筛不适合作为唯一决策依据。3. 这个项目的技术拆解LLM 怎么完成一次面包店评分我们先把这个巴黎面包店项目拆开看它到底经历了哪些技术环节。理解了这个你就能迁移到自己的任务上。3.1 问题定义先确定“什么是好吃的巧克力面包”LLM 不是直接回答“哪家最好吃”而是要按一套可量化的标准来评分。通常一个巧克力面包的评价维度可以包括酥皮层次是否酥脆、起酥是否均匀。巧克力品质可可含量、苦甜平衡。内部结构气孔分布、是否扎实或过硬。新鲜度出炉时间、保存状态。整体口感黄油香、回味、是否油腻。这些维度就是“提示词里的评分卡”。评分卡越清晰模型的输出越稳定。对应到技术语言就是定义evaluation_criteria结构在调用 LLM 时作为上下文传入。这一步决定了后面所有结果的质量。3.2 数据采集巴黎有多少家面包店怎么获得名单项目名里写了“every Paris bakery”实际执行时不可能真的遍历每一家通常是通过地图服务、点评平台或公开榜单拿到面包店清单再按分区、知名度、类型做抽样。这里数据采集要注意名单来源是否合法。是否有重复项和关店店铺。是否需要人工确认。如果使用爬虫采集还需要遵守目标网站的服务条款如果是公开数据集要确认授权和时效性。3.3 提示词设计让 LLM 做“裁判员”而不是“聊天者”这是整个项目最核心的技术点。同样的面包店描述提示词写得好不好得分完全是两回事。常见的低质量提示词是这家店的面包好吃吗打1到10分。它会得到一个没有标准、没有依据的数字。高质量提示词要包含角色设定。评分维度。每个维度的分值权重。评分标准说明。输出 JSON 格式要求。禁止或注意事项。例如你是一名专业的烘焙评测员。请根据以下描述对这家面包店的巧克力面包进行评分。 评分维度 - 酥皮层次0-10酥皮是否酥脆、层次是否分明。 - 巧克力品质0-10巧克力风味是否浓郁、是否过甜。 - 内部结构0-10气孔是否均匀、口感是否适中。 - 新鲜度0-10是否新鲜出炉状态是否良好。 最终输出 JSON 格式包含每个维度的分数和一句总评。模板里只是示例实际评分标准要以项目自己的评估体系为准。这里的关键是先确定评分标准的颗粒度再设计提示词而不是反过来。3.4 批量调用与结构化输出有了评分标准下一步就是批量调用 LLM。对每家面包店构造一条提示词拿到一个 JSON 结果。这一步的工程要点是批量任务要有队列和失败重试。每一次调用要记录原始输入和模型输出。JSON 输出要做 schema 校验避免模型返回非法格式。如果调用的是云端 API还要注意请求频率限制和超时设置。一个典型的批量调用流程是加载面包店名单 - 构造提示词 - 批量调用 LLM - 解析 JSON - 写入结果表 - 抽样复核3.5 结果汇总与排名最后一步是把所有评分汇总按维度加权得到总排名。这里常见的坑是不同批次调用的分数尺度不一致。有些模型对评分的偏好偏向中位数。单个维度异常值影响总排名。解决办法是多做几轮评测取平均值。用归一化或分位数处理分数。人工抽样复核排名靠前和靠后的店铺。4. 本地部署环境准备与前置条件这个项目的核心是“调用 LLM 完成任务”所以环境准备包括两部分基础 Python 环境和模型访问方式。4.1 操作系统与 Python开发环境建议Windows 10/11、macOS、Linux 都可以。Python 3.10 或 3.11。需要能够安装 pip 依赖包。4.2 模型访问方式有两种路线路线优点缺点云端 LLM API无需本地显卡效果稳定代码简单有费用受网络和服务可用性影响本地部署开源模型数据不出内网无单次调用费用需要显卡资源效果可能弱于云端旗舰模型选择哪种取决于你要处理的文本量级和隐私要求。4.3 Python 依赖常规的依赖包包括# 用于 HTTP 请求和 API 调用 pip install requests openai # 用于 JSON 解析和数据校验 pip install pydantic # 用于数据处理 pip install pandas # 用于并发批量调用 pip install tqdm这里openai只是示例你需要根据自己实际使用的模型服务商替换为对应的 SDK。对于本地模型例如通过 Ollama 或 vLLM 起的 OpenAI 兼容接口通常也可以直接用openaiSDK只改base_url。4.4 目录结构建议建议把项目按以下结构管理bakery_rank/ ├── data/ │ ├── bakeries.json # 面包店名单 │ └── evaluation_results.json # 评分结果 ├── prompts/ │ └── scoring_prompt.txt # 评分提示词模板 ├── scripts/ │ ├── collect_data.py # 数据采集 │ ├── run_evaluation.py # 批量评分 │ └── validate_output.py # 结果校验 └── outputs/ ├── scores_raw.json # 原始评分 └── ranking_final.json # 最终排名这样做的好处是模型文件、输入素材、输出结果分开管理后续调试和复用都方便。5. 安装部署与启动方式由于这不是一个现成的一键启动项目而是需要按流程搭建自己的 LLM 评价工作流下面给出一套可复制的标准化部署流程。5.1 创建项目虚拟环境# 创建虚拟环境 python -m venv .venv # 激活虚拟环境Windows .venv\Scripts\activate # 激活虚拟环境macOS / Linux source .venv/bin/activate # 升级 pip pip install --upgrade pip5.2 安装依赖pip install requests openai pydantic pandas tqdm如果你的本地模型是通过 Ollama 提供的 OpenAI 兼容接口可以这样配置客户端from openai import OpenAI client OpenAI( base_urlhttp://localhost:11434/v1, api_keyollama # 本地服务不校验但要按实际服务说明填写 )注意api_key只做占位具体要看你使用的本地推理服务的鉴权方式。5.3 准备模型访问配置建议把模型配置写入环境变量或.env文件不要把密钥硬编码进代码。# .env 示例实际值需要替换为你自己的 LLM_API_BASEhttps://your-api-endpoint.example.com/v1 LLM_API_KEYyour-api-key LLM_MODELyour-model-name这里只是模板你需要按实际使用的模型服务商和模型名填充。5.4 启动测试先跑一个最小测试确认模型接口能通# 最小测试脚本 test_llm.py import os from openai import OpenAI client OpenAI( base_urlos.getenv(LLM_API_BASE), api_keyos.getenv(LLM_API_KEY), ) response client.chat.completions.create( modelos.getenv(LLM_MODEL), messages[ {role: system, content: 你是一个评测助手。}, {role: user, content: 请用一句话评价这个描述。} ], temperature0.2, ) print(response.choices[0].message.content)注意这里的模型名、API 地址、消息格式都需要以实际服务提供方为准。先跑通这一步再进入批量流程。6. 功能测试与效果验证项目不是跑通一次就结束了关键是验证 LLM 的评分是否稳定、是否有偏差、结果是否可复现。6.1 测试多维度评分能力测试目的确认模型能按设定的评分维度输出结构化的 JSON。测试输入这家店位于巴黎玛黑区是一家传统法式面包店。 巧克力面包售价 1.5 欧元外观呈深棕色酥皮有 7 层 内部巧克力采用 70% 黑巧克力口感偏苦酥皮酥脆。预期输出{ 酥皮层次: 9, 巧克力品质: 8, 内部结构: 7, 新鲜度: 8, 总评: 酥皮层次优秀巧克力风味浓郁偏苦整体品质较高。 }判断标准返回内容是否为合法 JSON。分数是否在 1 到 10 之间。总评是否和分数一致。常见失败模型输出带解释文字无法直接解析 JSON。模型给出 11 分或 0 分超出范围。解决方式在提示词中强调“只输出 JSON不要解释”。解析时做两级容错先尝试直接解析失败后用正则提取第一个{到最后一个}。6.2 测试同一对象两次评分是否一致测试目的检查模型评分稳定性。操作方式对同一条面包店描述连续调用 3 次比较分数差异。判断标准如果每次评分差异超过 2 分说明评分卡不够清晰或模型随机性太强。此时要降低temperature或修改提示词让维度定义更明确。这是一个非常重要的质量控制手段很多做 LLM 评分项目的团队都会忽略。6.3 测试极端样本测试目的确认模型不会因为名称或地理位置产生无依据的偏差。设计两个样本一家“网红店”评分维度描述很差。一家“无名小店”评分维度描述很好。判断标准模型应该按描述评分而不是按店的知名度评分。如果模型给网红店打了高分而没有给评分依据说明提示词里缺少“不要受店铺知名度影响”的限制。6.4 批量测试批量测试要关注两个指标成功率批量调用中成功返回并解析成 JSON 的比例。有效率通过 JSON schema 校验的比例。如果有效率低于 80%优先检查提示词和模型选择而不是扩大样本量。7. 接口 API 与批量任务设计这个项目天然适合设计成 API 服务或批量任务。如果只写一个脚本每次都要手动跑改进后就是一个标准的评测服务。7.1 本地 API 服务可以用 FastAPI 把评分功能封装成接口# app.py 示例需要按实际项目调整 from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List app FastAPI() class EvaluationRequest(BaseModel): description: str dimensions: List[str] [酥皮层次, 巧克力品质, 内部结构, 新鲜度] class EvaluationResponse(BaseModel): scores: dict summary: str app.post(/evaluate, response_modelEvaluationResponse) async def evaluate(req: EvaluationRequest): # 这里实际调用你的 LLM 评分函数返回值需要做校验 result dummy_evaluate(req.description, req.dimensions) return result def dummy_evaluate(description: str, dimensions: List[str]): # 这里替换为真实的 LLM 调用逻辑 return { scores: {d: 8 for d in dimensions}, summary: 示例返回请替换为模型真实输出, } # 启动方式uvicorn app:app --host 127.0.0.1 --port 8000这段代码里dummy_evaluate是占位函数实际使用时必须替换为真实的模型调用和 JSON 解析逻辑不要直接用于生产。7.2 Python 调用示例import requests url http://127.0.0.1:8000/evaluate payload { description: 这家店位于巴黎蒙马特高地店龄超过30年。巧克力面包酥皮酥脆巧克力品质中等偏上。, dimensions: [酥皮层次, 巧克力品质, 内部结构, 新鲜度] } response requests.post(url, jsonpayload, timeout60) print(response.json())7.3 批量任务设计真实项目中店铺数量可能上百甚至上千一次性提交不可取。建议按以下流程读取全量名单。分批次构造任务每批 10 到 20 条。每批次之间加短暂延迟避免触发频率限制。每一条结果写入结果表记录状态成功/失败。失败任务进入重试队列重试最多 3 次。全部完成后统一生成排名。# 批量任务伪代码路径和模型名需要替换 import json import time from pathlib import Path results [] for idx, bakery in enumerate(bakery_list): try: score call_llm_scoring(bakery[description]) # 替换为实际调用函数 results.append({ id: bakery[id], name: bakery[name], scores: score[scores], summary: score[summary], status: success }) except Exception as e: results.append({ id: bakery[id], name: bakery[name], status: failed, error: str(e) }) # 控制请求频率 time.sleep(0.5) # 写入结果 Path(outputs/scores_raw.json).write_text( json.dumps(results, ensure_asciiFalse, indent2), encodingutf-8 )批量任务最容易出问题的不是模型本身而是超时、频率限制、JSON 解析失败。所以日志和重试机制一定要有。8. 资源占用与性能观察和图像、视频类项目不同这个项目的资源占用主要集中在API 调用成本或本地模型推理的显存/内存。8.1 API 调用场景如果用云端 API资源占用不是显卡而是Token 消耗额度。每千次调用的费用。网络延迟。要重点观察的是指标观察方式控制手段单次调用 Token 消耗查看模型 API 返回的 usage 字段精简描述文本、缩短提示词模板单次调用耗时接口响应时间选用更快的模型减少重试频率限制API 是否返回 429增加 sleep 间隔、使用指数退避重试费用服务商控制台先小批量测试再全量发起如果模型返回的usage里有prompt_tokens和completion_tokens建议每次调用都记录到日志方便事后算成本。8.2 本地模型部署场景如果你用本地模型比如通过 Ollama 或 vLLM 部署 7B 到 14B 级别的开源模型需要观察显存占用。单次推理耗时。并发请求时的显存峰值。本地部署的观察方式# Linux 下观察显存 nvidia-smi -l 1显存占用会随模型大小、上下文长度、并发数变化。降低显存和内存占用的通用手段使用量化版本模型如 Q4_K_M、Q8_0。减少单次送入的文本长度。降低并发数。避免无限保留历史对话评分任务只传需要的文本。注意不同模型和推理框架的实际占用差异很大不要参考网上某个固定数字要以本机测试为准。8.3 性能瓶颈判断一个小技巧如果批量任务跑得慢先区分瓶颈在哪里。如果耗时集中在模型接口响应说明是模型推理慢和本地数据解析无关。如果耗时集中在数据分批和解析说明是流程代码有问题。如果批量任务经常失败优先检查频率限制和超时时间。给批量任务加一行日志print(fBatch {idx}: success{status}, elapsed{elapsed:.2f}s)这个日志能帮你快速定位是哪一段变慢。9. LLM 评分的常见问题与排查方法这类“LLM 做评价排名”的项目问题和图像类项目完全不同。下面是实际操作里最常见的几个坑。问题现象可能原因排查方式解决方案模型输出的 JSON 无法解析提示词未限制输出格式查看原始返回内容在提示词中强制 JSON 输出并加解析容错同一对象两次评分差异很大模型随机性太高或评分标准不清晰对同一输入跑 3 次降低 temperature细化评分维度描述某些店铺被明显高估店铺名称携带“老店”“米其林”等字眼模型被影响检查提示词是否要求只看描述在提示词中加入“请忽略店铺名称和地理位置的额外语义”批量任务大量失败请求频率超限或超时检查日志中的错误状态码增加 sleep 间隔配置重试队列分数普遍偏高模型倾向输出中高分数统计评分分布设计评分锚点例如“5 分代表平均水平”排名结果不稳定单次评分噪声大对比两次排名多做几轮取平均分或改用归一化排序调用成本超出预期单次调用 Token 太多检查 usage 字段精简输入描述缩短评分维度描述模板一个关键点是不要只用一轮评分就直接出排名。更稳妥的做法是第一轮全量评分。第二轮重跑同一样本。取平均值作为最终分。对排名前 10 名和后 10 名做人工抽样复核。10. 最佳实践与使用建议把这个巴黎面包店项目的思路转换成一个通用工程方法核心建议如下。10.1 先把评分标准写清楚再写代码LLM 打分项目里 80% 的问题出在评分标准不清晰。不要在代码里纠结“要不要加一个维度”先花一天时间把维度、分值区间、每档描述写出来。评分标准颗粒度越高模型输出越稳定。建议评分卡用 Markdown 表格维护例如得分酥皮层次巧克力品质9-10层次分明入口酥脆有明显黄油香气可可风味浓郁苦甜平衡融化顺滑7-8层次较清晰口感较酥脆巧克力风味较好甜度稍高5-6层次一般略绵软巧克力味较淡偏甜0-4酥皮软塌无层次巧克力口感差过甜或代可可脂味这段评分卡可以直接作为系统提示词传入模型。10.2 每次调用都记录原始数据批量任务不能只存最终分数。建议每一条记录至少保存三样东西原始输入文本。模型原始返回。解析后的结构化数据。这样出了问题可以直接回溯不需要重新调用模型。10.3 用“锚点样本”校准模型在批量任务中加入几个你已经知道“应该得多少分”的样本作为校准锚点。例如你人工判定 A 店巧克力面包口感很好应得 9 分。如果模型给 A 店打了 6 分说明模型整体评分偏严。这时可以把所有分数做平移修正或者调整提示词的表达。10.4 涉及真实商家和用户数据时注意合规真实世界的评价项目必须注意采集店铺信息、用户点评时遵守平台服务条款和知识产权约定。公开排名结果时对排名最后几名或个别负面评价保持克制避免引发争议。如果涉及人脸、声音、私人数据更是要提前获得授权。最终榜单建议展示“样本有限、基于某时间节点采样”避免被读者误解为绝对定论。10.5 发布结果前做好免责说明任何由 LLM 生成的评价都不能替代真实体验。建议在最终输出中说明本排名由 LLM 基于公开文本信息和设定的评分标准自动生成仅用于技术演示和参考不构成实际消费建议。11. 总结这个项目给你的启发这个巴黎面包店排名项目最值得参考的地方不是那个榜单本身而是它演示了一条完整链路把现实问题变成可量化的评分任务用 LLM 完成批量评价最后输出排名结果。如果你也准备做一个类似的项目先从这里开始找 10 个测试样本先手工写好评分卡。写一个最简单的调用脚本确认模型能稳定输出 JSON。跑通 10 条批量任务检查成功率和分数稳定性。最后再扩大到全量数据和最终排名。最容易踩的坑是样本量还没跑完就急着出排名结果评分不稳定整个榜单不可信。更稳妥的方法是先小批量测试再设计重试和校验最后再做全量运行。后续可以扩展的方向包括接入多模态模型直接分析图片加入人工复核界面或把评分结果做成实时可视化榜单。用 LLM 做真实世界评测才刚刚开始这套“评分卡 批量调用 结果校验”的方法在内容评价、商品横向对比、数据质检等场景都可以复用。