一日一技:如何正確使用正則表達式的字符串替換
在日常工作中,可能需要一次性給大模型發送N篇文章,讓其幫忙提取并返回Markdown格式的產品信息。假設這N篇文章的json格式如下:
[
{"id": 1, "title": "xxx", "content": "yyyy", "url": "https://..."},
{"id": 2, "title": "xxx", "content": "yyyy", "url": "https://..."}
{"id": 3, "title": "xxx", "content": "yyyy", "url": "https://..."}
]
然后,讓大模型從這N篇文章中提取出產品信息,標明對應產品的出處URL,并以Markdown表格返回。返回的Markdown格式如下:
| 產品名稱 | 產品價格 | 出處 |
| --- | --- | --- |
| xx | 100 | https://xxxx |
| yy | 200 | https://yyyyy |
但上述這種直接處理方法有兩個弊端。一是有些網站的URL很長,讓大模型原樣將URL返回出來,會浪費輸出token,且輸出token一般都比較貴。二是大模型容易出錯,可能會生成假的URL。
因此,一種常見的做法是讓大模型用文章ID來代替出處URL這一列。上述示例如下:
| 產品名稱 | 產品價格 | 出處 |
| --- | --- | --- |
| xx | 100 | article_1 |
| yy | 200 | article_2 |
這里提醒大家一下,如果文章ID是1、2、3這種簡單的數字,建議拼接一個前綴,否則在進行替換時容易將其他字段正常的數字給替換掉。例如,這里我使用article_1來表示文章ID。
這樣我們在拿到返回的文本以后,還需要寫很長的replace語句將文章ID全部替換成Markdown格式的網址,如下:
answer = ask_llm(參數)
answer = (answer.replace('article_1', f'[{article["title"]}]({article["url"]})')
.replace('article_2', f'[第二個標題](第二個連接)')
.replace('article_3', f'[第3個標題](第3個連接)')
。。。
)
上述replace
寫法的代碼長得太丑了。另一方面,每次replace都會完整掃描一次文本,如果返回的Markdown很長的話,非常浪費時間。
最近發現一個非常簡單的辦法,只需要掃描一次Markdown就可以完成全部替換。就是使用re.sub
并且把第二個參數改寫成函數。
一般使用re.sub
的時候,第二個參數都是字符串,例如:
re.sub('目標正則表達式', '新的字符串', '原始字符串')
下面例子是使用re.sub
將一段話中的具體郵箱地址替換為[EMAIL],手機號替換為[PHONE]。
圖片
但是re.sub
的第二個參數實際上也可以是函數。下面用一個例子來展示。
首先定義一個字典:
article_id_url_map = {
"article_1": '[文章標題1](https://example.com/article1)',
"article_2": '[文章標題2](https://example.com/article2)',
"article_3": '[文章標題3](https://example.com/article3)',
}
然后使用如下代碼:
answer = re.sub('(article_\d+)', lambda x: article_id_url_map[x.group(1)], answer)
就搞定了。
運行效果如下:
圖片
這樣可以在處理返回包含 URL 的 Markdown 時,僅掃描一次就完成全部替換,提高效率。