Commit beef466f7e635bdaf5aa561b8812abb776608fc9

Authored by tangwang
1 parent d54b0467

商品索引的nchors 与语义属性

Showing 1 changed file with 141 additions and 16 deletions   Show diff stats
indexer/process_products.py
... ... @@ -61,13 +61,141 @@ LANG_LABELS: Dict[str, str] = {
61 61  
62 62 SUPPORTED_LANGS = set(LANG_LABELS.keys())
63 63  
  64 +SYSTEM_MESSAGES: Dict[str, str] = {
  65 + "zh": (
  66 + "你是一名电商平台的商品标注员,你的工作是对输入的每个商品进行理解、分析和标注,"
  67 + "并按要求格式返回 Markdown 表格。所有输出内容必须为中文。"
  68 + ),
  69 + "en": (
  70 + "You are a product annotator for an e-commerce platform. "
  71 + "For each input product, you must understand, analyze and label it, "
  72 + "and return a Markdown table strictly following the requested format. "
  73 + "All output must be in English."
  74 + ),
  75 + "de": (
  76 + "Du bist ein Produktannotator für eine E‑Commerce‑Plattform. "
  77 + "Du sollst jedes Eingabeprodukt verstehen, analysieren und beschriften "
  78 + "und eine Markdown-Tabelle im geforderten Format zurückgeben. "
  79 + "Alle Ausgaben müssen auf Deutsch sein."
  80 + ),
  81 + "ru": (
  82 + "Вы — разметчик товаров для платформы электронной коммерции. "
  83 + "Ваша задача — понимать, анализировать и размечать каждый товар "
  84 + "и возвращать таблицу Markdown в требуемом формате. "
  85 + "Весь вывод должен быть на русском языке."
  86 + ),
  87 + "fr": (
  88 + "Vous êtes annotateur de produits pour une plateforme e‑commerce. "
  89 + "Pour chaque produit en entrée, vous devez le comprendre, l’analyser et l’annoter, "
  90 + "puis renvoyer un tableau Markdown au format demandé. "
  91 + "Toute la sortie doit être en français."
  92 + ),
  93 +}
  94 +
64 95  
65 96 def create_prompt(products: List[Dict[str, str]], target_lang: str = "zh") -> str:
66   - """创建LLM提示词(根据目标语言输出)"""
67   - lang_label = LANG_LABELS.get(target_lang, "对应语言")
68   - prompt = f"""请对输入的每条商品标题,分析并提取以下信息,所有输出内容请使用{lang_label}:
  97 + """根据目标语言创建 LLM 提示词和表头说明。"""
  98 + if target_lang == "en":
  99 + prompt = """Please analyze each input product title and extract the following information:
  100 +
  101 +1. Product title: a natural English product name derived from the input title
  102 +2. Category path: from broad to fine-grained category, separated by ">" (e.g. Clothing>Women>Dresses>Work Dress)
  103 +3. Fine-grained tags: style / features / attributes (e.g. floral, waist-cinching, French style)
  104 +4. Target audience: gender / age group, etc. (e.g. young women)
  105 +5. Usage scene
  106 +6. Applicable season
  107 +7. Key attributes
  108 +8. Material description
  109 +9. Functional features
  110 +10. Selling point: one concise key selling sentence for recommendation
  111 +11. Anchor text: a set of words or phrases that could be used by users as search queries for this product, covering category, fine-grained tags, functional attributes, usage scenes, etc.
  112 +
  113 +Input product list:
  114 +
  115 +"""
  116 + prompt_tail = """
  117 +Please strictly return a Markdown table in the following format. For any column that can contain multiple values, separate values with commas. Do not add any other explanations:
  118 +
  119 +| No. | Product title | Category path | Fine-grained tags | Target audience | Usage scene | Season | Key attributes | Material | Features | Selling point | Anchor text |
  120 +|----|----|----|----|----|----|----|----|----|----|----|----|
  121 +"""
  122 + elif target_lang == "de":
  123 + prompt = """Bitte analysiere jeden eingegebenen Produkttitel und extrahiere die folgenden Informationen:
  124 +
  125 +1. Produkttitel: ein natürlicher deutscher Produkttitel basierend auf dem Eingangstitel
  126 +2. Kategoriepfad: von Oberkategorie bis Feinkategorie, getrennt durch ">" (z. B. Kleidung>Damen>Kleider>Businesskleid)
  127 +3. Feinkörnige Tags: Stil / Merkmale / Eigenschaften (z. B. Blumenmuster, tailliert, französischer Stil)
  128 +4. Zielgruppe: Geschlecht / Altersgruppe usw. (z. B. junge Frauen)
  129 +5. Einsatzszenario
  130 +6. Geeignete Saison
  131 +7. Wichtige Attribute
  132 +8. Materialbeschreibung
  133 +9. Funktionale Merkmale
  134 +10. Verkaufsargument: ein prägnanter, einzeiliger Haupt-Selling-Point für Empfehlungen
  135 +11. Ankertexte: eine Menge von Wörtern oder Phrasen, die Nutzer als Suchanfragen für dieses Produkt verwenden könnten und die Kategorie, feine Tags, Funktion und Nutzungsszenarien abdecken.
  136 +
  137 +Eingabeliste der Produkte:
  138 +
  139 +"""
  140 + prompt_tail = """
  141 +Gib bitte strikt eine Markdown-Tabelle im folgenden Format zurück. Mehrere Werte in einer Spalte werden durch Kommas getrennt. Füge keine weiteren Erklärungen hinzu:
  142 +
  143 +| Nr. | Produkttitel | Kategoriepfad | Feintags | Zielgruppe | Einsatzszenario | Saison | Wichtige Attribute | Material | Merkmale | Verkaufsargument | Ankertexte |
  144 +|----|----|----|----|----|----|----|----|----|----|----|----|
  145 +"""
  146 + elif target_lang == "ru":
  147 + prompt = """Пожалуйста, проанализируйте каждый входной заголовок товара и извлеките следующую информацию:
  148 +
  149 +1. Заголовок товара: естественное русскоязычное название товара на основе исходного заголовка
  150 +2. Путь категории: от широкой до узкой категории, разделённый символом ">" (например: Одежда>Женская одежда>Платья>Деловое платье)
  151 +3. Детализированные теги: стиль / особенности / характеристики (например: цветочный принт, приталенный, французский стиль)
  152 +4. Целевая аудитория: пол / возрастная группа и т. п. (например: молодые женщины)
  153 +5. Сценарий использования
  154 +6. Подходящий сезон
  155 +7. Ключевые характеристики
  156 +8. Описание материала
  157 +9. Функциональные особенности
  158 +10. Торговое преимущество: одно краткое ключевое предложение для рекомендаций
  159 +11. Якорные запросы: набор слов или фраз, которые пользователи могут использовать в качестве поисковых запросов для этого товара, покрывающих категорию, детализированные теги, функциональные характеристики, сценарии использования и т. д.
  160 +
  161 +Список входных товаров:
69 162  
70   -1. 商品标题:将输入商品名称翻译为{lang_label}
  163 +"""
  164 + prompt_tail = """
  165 +Пожалуйста, строго верните Markdown‑таблицу в следующем формате. Для колонок с несколькими значениями разделяйте значения запятыми. Не добавляйте никаких дополнительных пояснений:
  166 +
  167 +| № | Заголовок товара | Путь категории | Детализированные теги | Целевая аудитория | Сценарий использования | Сезон | Ключевые характеристики | Материал | Особенности | Торговое преимущество | Якорные запросы |
  168 +|----|----|----|----|----|----|----|----|----|----|----|----|
  169 +"""
  170 + elif target_lang == "fr":
  171 + prompt = """Veuillez analyser chaque titre de produit en entrée et extraire les informations suivantes :
  172 +
  173 +1. Titre du produit : un titre de produit naturel en français basé sur le titre d’origine
  174 +2. Chemin de catégorie : de la catégorie la plus large à la plus fine, séparées par ">" (par ex. Vêtements>Femme>Robes>Robe de travail)
  175 +3. Tags détaillés : style / caractéristiques / attributs (par ex. fleuri, cintré, style français)
  176 +4. Public cible : sexe / tranche d’âge, etc. (par ex. jeunes femmes)
  177 +5. Scénario d’utilisation
  178 +6. Saison adaptée
  179 +7. Attributs clés
  180 +8. Description du matériau
  181 +9. Caractéristiques fonctionnelles
  182 +10. Argument de vente : une phrase concise résumant le principal atout pour la recommandation
  183 +11. Texte d’ancrage : un ensemble de mots ou d’expressions que les utilisateurs pourraient saisir comme requêtes de recherche pour ce produit, couvrant la catégorie, les tags détaillés, les fonctions, les scénarios d’usage, etc.
  184 +
  185 +Liste des produits en entrée :
  186 +
  187 +"""
  188 + prompt_tail = """
  189 +Veuillez strictement renvoyer un tableau Markdown au format suivant. Pour toute colonne pouvant contenir plusieurs valeurs, séparez‑les par des virgules. N’ajoutez aucune autre explication :
  190 +
  191 +| N° | Titre du produit | Chemin de catégorie | Tags détaillés | Public cible | Scénario d’utilisation | Saison | Attributs clés | Matériau | Caractéristiques | Argument de vente | Texte d’ancrage |
  192 +|----|----|----|----|----|----|----|----|----|----|----|----|
  193 +"""
  194 + else:
  195 + # 默认中文版本
  196 + prompt = """请对输入的每条商品标题,分析并提取以下信息:
  197 +
  198 +1. 商品标题:将输入商品名称翻译为自然、完整的中文商品标题
71 199 2. 品类路径:从大类到细分品类,用">"分隔(例如:服装>女装>裤子>工装裤)
72 200 3. 细分标签:商品的风格、特点、功能等(例如:碎花,收腰,法式)
73 201 4. 适用人群:性别/年龄段等(例如:年轻女性)
... ... @@ -82,8 +210,7 @@ def create_prompt(products: List[Dict[str, str]], target_lang: str = "zh") -> st
82 210 输入商品列表:
83 211  
84 212 """
85   -
86   - prompt_tail = """
  213 + prompt_tail = """
87 214 请严格按照以下markdown表格格式返回,每列内部的多值内容都用逗号分隔,不要添加任何其他说明:
88 215  
89 216 | 序号 | 商品标题 | 品类路径 | 细分标签 | 适用人群 | 使用场景 | 适用季节 | 关键属性 | 材质说明 | 功能特点 | 商品卖点 | 锚文本 |
... ... @@ -97,8 +224,8 @@ def create_prompt(products: List[Dict[str, str]], target_lang: str = "zh") -> st
97 224 return prompt
98 225  
99 226  
100   -def call_llm(prompt: str) -> Tuple[str, str]:
101   - """调用大模型API(带重试机制)"""
  227 +def call_llm(prompt: str, target_lang: str = "zh") -> Tuple[str, str]:
  228 + """调用大模型API(带重试机制),按目标语言选择系统提示词。"""
102 229 headers = {
103 230 "Authorization": f"Bearer {API_KEY}",
104 231 "Content-Type": "application/json"
... ... @@ -109,7 +236,7 @@ def call_llm(prompt: str) -> Tuple[str, str]:
109 236 "messages": [
110 237 {
111 238 "role": "system",
112   - "content": "你是一名电商平台的商品标注员,你的工作是对输入的每个商品进行理解、分析和标注,按要求格式返回Markdown表格。"
  239 + "content": SYSTEM_MESSAGES.get(target_lang, SYSTEM_MESSAGES["zh"])
113 240 },
114 241 {
115 242 "role": "user",
... ... @@ -196,18 +323,16 @@ def parse_markdown_table(markdown_content: str) -> List[Dict[str, str]]:
196 323 if not line:
197 324 continue
198 325  
199   - # 跳过表头
  326 + # 表格行处理
200 327 if line.startswith('|'):
201   - # 跳过分隔行
  328 + # 分隔行(----)
202 329 if set(line.replace('|', '').strip()) <= {'-', ':'}:
203 330 data_started = True
204 331 continue
205 332  
206   - # 跳过表头行
  333 + # 首个表头行:无论语言如何,统一跳过
207 334 if not data_started:
208   - if '序号' in line or '商品中文标题' in line:
209   - continue
210   - data_started = True
  335 + # 等待下一行数据行
211 336 continue
212 337  
213 338 # 解析数据行
... ... @@ -248,7 +373,7 @@ def process_batch(
248 373  
249 374 # 调用LLM
250 375 try:
251   - raw_response, full_response_json = call_llm(prompt)
  376 + raw_response, full_response_json = call_llm(prompt, target_lang=target_lang)
252 377  
253 378 # 解析结果
254 379 parsed_results = parse_markdown_table(raw_response)
... ...