tim1900's picture
Update README.md
3de7ef9 verified
---
license: mit
language:
- en
- zh
pipeline_tag: token-classification
---
# bert-chunker-Chinese-2
[GitHub](https://github.com/jackfsuia/bert-chunker/tree/main/bcc2)
bert-chunker-Chinese-2 (中文分段器) is a text chunker based on BertForTokenClassification to predict the start token of chunks (for use in RAG, etc), and using a sliding window it cuts documents of any size into chunks. We see it as an alternative of [semantic chunker](https://github.com/FullStackRetrieval-com/RetrievalTutorials/blob/main/tutorials/LevelsOfTextSplitting/5_Levels_Of_Text_Splitting.ipynb), but specially, it not only works for the structured texts, but also the **unstructured and messy texts**. It is a new version of [bc-chinese](https://huggingface.co/tim1900/bert-chunker-chinese), for which we change our data labeling and train pipeline to make it more stable and useful.
Updates :
- 2025.5.12: an experimental script that **supports specifying the maximum tokens per chunk** is available now [below](#experimental).
## Usage
Run the following:
```python
# -*- coding: utf-8 -*-
import torch
from transformers import AutoTokenizer, BertForTokenClassification
import math
model_path = "tim1900/bert-chunker-Chinese-2"
tokenizer = AutoTokenizer.from_pretrained(
model_path,
padding_side="right",
model_max_length=512,
trust_remote_code=True,
)
device = "cpu" # or 'cuda'
model = BertForTokenClassification.from_pretrained(
model_path,
).to(device)
def chunk_text(model, text, tokenizer, prob_threshold=0.5):
# slide context window chunking
MAX_TOKENS = 512
tokens = tokenizer(text, return_tensors="pt", truncation=False)
input_ids = tokens["input_ids"]
attention_mask = tokens["attention_mask"][:, 0:MAX_TOKENS]
attention_mask = attention_mask.to(model.device)
CLS = input_ids[:, 0].unsqueeze(0)
SEP = input_ids[:, -1].unsqueeze(0)
input_ids = input_ids[:, 1:-1]
model.eval()
split_str_poses = []
token_pos = []
windows_start = 0
windows_end = 0
logits_threshold = math.log(1 / prob_threshold - 1)
print(f"Processing {input_ids.shape[1]} tokens...")
while windows_end <= input_ids.shape[1]:
windows_end = windows_start + MAX_TOKENS - 2
ids = torch.cat((CLS, input_ids[:, windows_start:windows_end], SEP), 1)
ids = ids.to(model.device)
output = model(
input_ids=ids,
attention_mask=torch.ones(1, ids.shape[1], device=model.device),
)
logits = output["logits"][:, 1:-1, :]
chunk_decision = logits[:, :, 1] > (logits[:, :, 0] - logits_threshold)
greater_rows_indices = torch.where(chunk_decision)[1].tolist()
# null or not
if len(greater_rows_indices) > 0 and (
not (greater_rows_indices[0] == 0 and len(greater_rows_indices) == 1)
):
split_str_pos = [
tokens.token_to_chars(sp + windows_start + 1).start
for sp in greater_rows_indices
if sp > 0
]
token_pos += [
sp + windows_start + 1 for sp in greater_rows_indices if sp > 0
]
split_str_poses += split_str_pos
windows_start = greater_rows_indices[-1] + windows_start
else:
windows_start = windows_end
substrings = [
text[i:j] for i, j in zip([0] + split_str_poses, split_str_poses + [len(text)])
]
token_pos = [0] + token_pos
return substrings, token_pos
# chunking
print("\n>>>>>>>>> Chunking...")
doc = r'''经典中式家常菜:红烧肉 详尽版食谱
红烧肉,作为中华美食殿堂中一颗璀璨的明珠,以其色泽红亮、肥而不腻、入口即化的独特风味,征服了无数食客的味蕾。它不仅仅是一道菜,更是一种情怀,是记忆中妈妈厨房里飘出的诱人香气,是团圆饭桌上最温暖的慰藉。要烹制出一盘完美的红烧肉,需要耐心、技巧以及对细节的专注。以下将为您详尽分解从选材到成品的每一个步骤,力求让您在家也能复刻出餐厅级别的美味。本食谱旨在深入剖析,故篇幅较长,以确保每个环节都清晰透彻。
一、 精选主料:奠定美味的基石
• 猪肉选择。
◦ 首选带皮的五花肉。
◦ 层次分明为佳。
◦ 肥瘦相间是关键。
◦ 厚度约三指左右。
◦ 重量约一斤半为宜。
◦ 确保猪皮完整无缺。
◦ 新鲜肉品呈鲜红色。
◦ 脂肪部分应洁白细腻。
• 预处理工作。
◦ 用镊子拔除残留猪毛。
◦ 将肉块置于冷水中浸泡。
◦ 浸泡时间约三十分钟。
◦ 中途可换水一至两次。
◦ 目的是泡出部分血水。
◦ 然后用刀刮洗猪皮表面。
◦ 彻底清除污物和杂质。
◦ 最后用流动水冲洗干净。
二、 准备辅料:调配灵魂之味
• 主要调味品。
◦ 老抽:负责上色。
◦ 用量需谨慎控制。
◦ 过多会导致发黑发苦。
◦ 生抽:提供咸鲜底味。
◦ 与老抽比例约二比一。
◦ 优质花雕酒是精髓。
◦ 去腥增香效果显著。
◦ 冰糖:首选黄冰糖。
◦ 炒出的糖色更红亮。
◦ 风味也比白糖醇和。
• 香辛料组合。
◦ 生姜一大块,切片。
◦ 大葱一根,切成长段。
◦ 蒜头数瓣,轻轻拍松。
◦ 八角两至三颗,增香。
◦ 桂皮一小段,勿过多。
◦ 香叶两片,增添风味。
◦ 草果一颗,可拍裂开。
◦ 干辣椒依个人口味添加。
• 其他基础材料。
◦ 食用油适量,需耐高温。
◦ 最好使用菜籽油或花生油。
◦ 食盐少许,用于最后调味。
◦ 因为酱油已有咸度。
◦ 准备足量的开水备用。
◦ 切记不可使用冷水。
◦ 冷水会使肉质收缩变柴。
三、 精细加工:关键步骤解析
• 肉块改刀。
◦ 将洗净的五花肉捞出。
◦ 用厨房纸彻底吸干水分。
◦ 这一步非常重要。
◦ 能有效防止后续溅油。
◦ 将肉切成三厘米见方块。
◦ 大小尽量保持均匀一致。
◦ 以确保受热和入味均匀。
◦ 切面应能看到完美层次。
• 焯水去腥。
◦ 冷水下锅,放入切好的肉。
◦ 同时加入几片生姜。
◦ 倒入一汤匙花雕酒。
◦ 开大火煮沸,撇净浮沫。
◦ 浮沫是血水和杂质所致。
◦ 务必撇除干净直至汤清。
◦ 焯水时间约五到八分钟。
◦ 煮至肉块变色定型即可。
• 捞出与冲洗。
◦ 用漏勺将肉块捞出。
◦ 立即放入温水中冲洗。
◦ 洗去表面残留的浮沫。
◦ 注意水温不宜过低。
◦ 再次用厨房纸吸干水分。
◦ 防止入锅时油花四溅。
◦ 此时肉块呈灰白色。
◦ 经过焯水已无肉腥味。
四、 核心工艺:炒糖色与煸炒
• 炒制糖色。
◦ 锅烧热,倒入少量底油。
◦ 放入准备好的冰糖。
◦ 开中小火慢慢搅动。
◦ 观察冰糖融化的过程。
◦ 先从固体变为液态。
◦ 再从小泡转为密集大泡。
◦ 当大泡逐渐回落消失时。
◦ 糖液颜色开始加深。
• 观察颜色变化。
◦ 从浅黄色变为枣红色。
◦ 这个瞬间非常关键。
◦ 枣红色时立即下入肉块。
◦ 过早则甜腻,过晚则发苦。
◦ 动作务必迅速而准确。
◦ 糖色是红亮色泽的来源。
◦ 也是风味层次的基础。
• 煸炒肉块。
◦ 快速颠锅,使每块肉均匀裹上糖色。
◦ 持续翻炒约三到五分钟。
◦ 直到肉块表面微微焦黄。
◦ 部分油脂被煸炒出来。
◦ 这样吃起来肥而不腻。
◦ 同时香味物质充分释放。
◦ 煸出的猪油可倒出部分。
◦ 留作炒青菜风味极佳。
五、 炖煮入味:时间与火候的艺术
• 加入调料。
◦ 沿着锅边烹入花雕酒。
◦ 瞬间激发出浓郁酒香。
◦ 接着倒入适量生抽。
◦ 再加入少许老抽上色。
◦ 放入所有香料:姜、葱、蒜等。
◦ 与肉块一起翻炒均匀。
◦ 让酱香与肉香充分融合。
◦ 翻炒约两分钟至香气扑鼻。
• 注入开水。
◦ 务必一次性加足开水。
◦ 水量要完全没过肉块。
◦ 甚至可以略多一些。
◦ 避免中途再次加水。
◦ 大火烧开后转小火。
◦ 盖上锅盖,慢火焖炖。
◦ 这是“入口即化”的关键。
◦ 时间至少需要一小时。
• 慢炖过程。
◦ 保持汤面微沸即可。
◦ 火候切忌过大过急。
◦ 否则容易烧干且肉不烂。
◦ 期间可偶尔开盖查看。
◦ 用勺子轻轻推动一下。
◦ 防止粘锅底的情况发生。
◦ 但尽量不要频繁翻动。
◦ 以免影响肉块的完整。
六、 收汁与装盘:成就最终美味
• 大火收汁。
◦ 炖煮一小时后。
◦ 用筷子戳一下瘦肉部分。
◦ 若能轻松戳透即表示已软烂。
◦ 此时根据汤汁咸度加盐。
◦ 开大火,将汤汁收浓。
◦ 用锅铲不停搅动。
◦ 防止糊底,并让汤汁变稠。
◦ 均匀包裹在每一块肉上。
• 收汁技巧。
◦ 收到汤汁浓稠如蜜。
◦ 油亮红润的汤汁紧裹肉块。
◦ 锅中泛起密集的大泡。
◦ 即可准备关火出锅。
◦ 收汁程度依个人喜好。
◦ 喜欢拌饭可多留些汤汁。
◦ 整个过程需密切留意。
◦ 最后阶段变化非常迅速。
• 最终成品。
◦ 将红烧肉盛入预热好的盘中。
◦ 可烫几棵小油菜围边。
◦ 既点缀色彩,又解油腻。
◦ 撒上少许葱花或香菜末。
◦ 一道色香味俱全的红烧肉完成。
◦ 肉质软糯,肥而不腻。
◦ 咸中带甜,回味无穷。
◦ 配上一碗白米饭是绝配。
七、 要点总结与升华
• 成功关键。
◦ 选材是基础,务必新鲜。
◦ 焯水步骤不可省略。
◦ 炒糖色是技术核心。
◦ 火候控制是成败关键。
◦ 耐心慢炖是美味保证。
• 变化与创新。
◦ 可加入土豆、鹌鹑蛋同烧。
◦ 吸收肉汤,滋味更丰富。
◦ 也可尝试用啤酒代替水。
◦ 别有一番风味层次。
◦ 但万变不离其宗。
◦ 核心技法仍需掌握。
烹饪是一门需要实践的艺术,红烧肉更是如此。希望这份详尽的食谱能成为您厨房路上的得力助手,愿您能享受从准备到品尝的整个过程,与家人朋友分享这份由时间与匠心凝聚而成的温暖美味。每一次尝试都是一次经验的积累,祝您烹饪愉快,早日成就属于自己的招牌红烧肉!
'''
# Chunk the text. The prob_threshold should be between (0, 1). The lower it is, the more chunks will be generated.
# Therefore adjust it to your need, when prob_threshold is small like 0.000001, each token is one chunk,
# when it is set to 1, the whole text is one chunk.
chunks, token_pos = chunk_text(model, doc, tokenizer, prob_threshold=0.5)
# print chunks
for i, (c, t) in enumerate(zip(chunks, token_pos)):
print(f"-----chunk: {i}----token_idx: {t}--------")
print(c)
```
## Experimental
The following script supports specifying max tokens per chunk. Chunker will be forced to choose a best possible position from history to chunk when it is about to exceed the max_tokens_per_chunk and no token satisfy the prob_threshold. This script can be seen as a new experimental version of the scripts above.
```python
# -*- coding: utf-8 -*-
import torch
from transformers import AutoTokenizer, BertForTokenClassification
import math
model_path = "tim1900/bert-chunker-Chinese-2"
tokenizer = AutoTokenizer.from_pretrained(
model_path,
padding_side="right",
model_max_length=512,
trust_remote_code=True,
)
device = "cpu" # or 'cuda'
model = BertForTokenClassification.from_pretrained(
model_path,
).to(device)
def chunk_text_with_max_chunk_size(model, text, tokenizer, prob_threshold=0.5,max_tokens_per_chunk = 400):
with torch.no_grad():
# slide context window chunking
MAX_TOKENS = 512
tokens = tokenizer(text, return_tensors="pt", truncation=False)
input_ids = tokens["input_ids"]
attention_mask = tokens["attention_mask"][:, 0:MAX_TOKENS]
attention_mask = attention_mask.to(model.device)
CLS = input_ids[:, 0].unsqueeze(0)
SEP = input_ids[:, -1].unsqueeze(0)
input_ids = input_ids[:, 1:-1]
model.eval()
split_str_poses = []
token_pos = []
windows_start = 0
windows_end = 0
logits_threshold = math.log(1 / prob_threshold - 1)
unchunk_tokens = 0
backup_pos = None
best_logits = torch.finfo(torch.float32).min
STEP = round(((MAX_TOKENS - 2)//2)*1.75 )
print(f"Processing {input_ids.shape[1]} tokens...")
# while windows_end <= input_ids.shape[1]:#记得改成windstart
while windows_start < input_ids.shape[1]:#记得改成windstart
windows_end = windows_start + MAX_TOKENS - 2
ids = torch.cat((CLS, input_ids[:, windows_start:windows_end], SEP), 1)
ids = ids.to(model.device)
output = model(
input_ids=ids,
attention_mask=torch.ones(1, ids.shape[1], device=model.device),
)
logits = output["logits"][:, 1:-1, :]
logit_diff = logits[:, :, 1] - logits[:, :, 0]
chunk_decision = logit_diff > - logits_threshold
greater_rows_indices = torch.where(chunk_decision)[1].tolist()
# null or not
if len(greater_rows_indices) > 0 and (
not (greater_rows_indices[0] == 0 and len(greater_rows_indices) == 1)
):
unchunk_tokens_this_window = greater_rows_indices[0] if greater_rows_indices[0]!=0 else greater_rows_indices[1]#exclude the fist index
# manually chunk
if unchunk_tokens + unchunk_tokens_this_window > max_tokens_per_chunk:
big_windows_end = max_tokens_per_chunk - unchunk_tokens
max_value, max_index= logit_diff[:,1:big_windows_end].max(), logit_diff[:,1:big_windows_end].argmax() + 1
if best_logits < max_value:
backup_pos = windows_start + max_index
windows_start = backup_pos
split_str_pos = [tokens.token_to_chars(backup_pos + 1).start]
split_str_poses = split_str_poses + split_str_pos
token_pos = token_pos + [backup_pos]
best_logits = torch.finfo(torch.float32).min
backup_pos = -1
unchunk_tokens = 0
# auto chunk
else:
if len(greater_rows_indices) >= 2:
for gi, (gri0,gri1) in enumerate(zip(greater_rows_indices[:-1],greater_rows_indices[1:])):
if gri1 - gri0 > max_tokens_per_chunk:
greater_rows_indices=greater_rows_indices[:gi+1]
break
split_str_pos = [tokens.token_to_chars(sp + windows_start + 1).start for sp in greater_rows_indices if sp > 0]
split_str_poses = split_str_poses + split_str_pos
token_pos = token_pos+ [sp + windows_start for sp in greater_rows_indices if sp > 0]
windows_start = greater_rows_indices[-1] + windows_start
best_logits = torch.finfo(torch.float32).min
backup_pos = -1
unchunk_tokens = 0
else:
# unchunk_tokens_this_window = min(windows_end - windows_start,STEP)
unchunk_tokens_this_window = min(windows_start+STEP,input_ids.shape[1]) - windows_start
# manually chunk
if unchunk_tokens + unchunk_tokens_this_window > max_tokens_per_chunk:
big_windows_end = max_tokens_per_chunk - unchunk_tokens
if logit_diff.shape[1] > 1:
max_value, max_index= logit_diff[:,1:big_windows_end].max(), logit_diff[:,1:big_windows_end].argmax() + 1
if best_logits < max_value:
backup_pos = windows_start + max_index
windows_start = backup_pos
split_str_pos = [tokens.token_to_chars(backup_pos + 1).start]
split_str_poses = split_str_poses + split_str_pos
token_pos = token_pos + [backup_pos]
best_logits = torch.finfo(torch.float32).min
backup_pos = -1
unchunk_tokens = 0
else:
# auto leave
if logit_diff.shape[1] > 1:
max_value, max_index= logit_diff[:,1:].max(), logit_diff[:,1:].argmax() + 1
if best_logits < max_value:
best_logits = max_value
backup_pos = windows_start + max_index
unchunk_tokens = unchunk_tokens + STEP
windows_start = windows_start + STEP
substrings = [
text[i:j] for i, j in zip([0] + split_str_poses, split_str_poses + [len(text)])
]
token_pos = [0] + token_pos
return substrings, token_pos
# chunking
print("\n>>>>>>>>> Chunking...")
doc = r'''经典中式家常菜:红烧肉 详尽版食谱
红烧肉,作为中华美食殿堂中一颗璀璨的明珠,以其色泽红亮、肥而不腻、入口即化的独特风味,征服了无数食客的味蕾。它不仅仅是一道菜,更是一种情怀,是记忆中妈妈厨房里飘出的诱人香气,是团圆饭桌上最温暖的慰藉。要烹制出一盘完美的红烧肉,需要耐心、技巧以及对细节的专注。以下将为您详尽分解从选材到成品的每一个步骤,力求让您在家也能复刻出餐厅级别的美味。本食谱旨在深入剖析,故篇幅较长,以确保每个环节都清晰透彻。
一、 精选主料:奠定美味的基石
• 猪肉选择。
◦ 首选带皮的五花肉。
◦ 层次分明为佳。
◦ 肥瘦相间是关键。
◦ 厚度约三指左右。
◦ 重量约一斤半为宜。
◦ 确保猪皮完整无缺。
◦ 新鲜肉品呈鲜红色。
◦ 脂肪部分应洁白细腻。
• 预处理工作。
◦ 用镊子拔除残留猪毛。
◦ 将肉块置于冷水中浸泡。
◦ 浸泡时间约三十分钟。
◦ 中途可换水一至两次。
◦ 目的是泡出部分血水。
◦ 然后用刀刮洗猪皮表面。
◦ 彻底清除污物和杂质。
◦ 最后用流动水冲洗干净。
二、 准备辅料:调配灵魂之味
• 主要调味品。
◦ 老抽:负责上色。
◦ 用量需谨慎控制。
◦ 过多会导致发黑发苦。
◦ 生抽:提供咸鲜底味。
◦ 与老抽比例约二比一。
◦ 优质花雕酒是精髓。
◦ 去腥增香效果显著。
◦ 冰糖:首选黄冰糖。
◦ 炒出的糖色更红亮。
◦ 风味也比白糖醇和。
• 香辛料组合。
◦ 生姜一大块,切片。
◦ 大葱一根,切成长段。
◦ 蒜头数瓣,轻轻拍松。
◦ 八角两至三颗,增香。
◦ 桂皮一小段,勿过多。
◦ 香叶两片,增添风味。
◦ 草果一颗,可拍裂开。
◦ 干辣椒依个人口味添加。
• 其他基础材料。
◦ 食用油适量,需耐高温。
◦ 最好使用菜籽油或花生油。
◦ 食盐少许,用于最后调味。
◦ 因为酱油已有咸度。
◦ 准备足量的开水备用。
◦ 切记不可使用冷水。
◦ 冷水会使肉质收缩变柴。
三、 精细加工:关键步骤解析
• 肉块改刀。
◦ 将洗净的五花肉捞出。
◦ 用厨房纸彻底吸干水分。
◦ 这一步非常重要。
◦ 能有效防止后续溅油。
◦ 将肉切成三厘米见方块。
◦ 大小尽量保持均匀一致。
◦ 以确保受热和入味均匀。
◦ 切面应能看到完美层次。
• 焯水去腥。
◦ 冷水下锅,放入切好的肉。
◦ 同时加入几片生姜。
◦ 倒入一汤匙花雕酒。
◦ 开大火煮沸,撇净浮沫。
◦ 浮沫是血水和杂质所致。
◦ 务必撇除干净直至汤清。
◦ 焯水时间约五到八分钟。
◦ 煮至肉块变色定型即可。
• 捞出与冲洗。
◦ 用漏勺将肉块捞出。
◦ 立即放入温水中冲洗。
◦ 洗去表面残留的浮沫。
◦ 注意水温不宜过低。
◦ 再次用厨房纸吸干水分。
◦ 防止入锅时油花四溅。
◦ 此时肉块呈灰白色。
◦ 经过焯水已无肉腥味。
四、 核心工艺:炒糖色与煸炒
• 炒制糖色。
◦ 锅烧热,倒入少量底油。
◦ 放入准备好的冰糖。
◦ 开中小火慢慢搅动。
◦ 观察冰糖融化的过程。
◦ 先从固体变为液态。
◦ 再从小泡转为密集大泡。
◦ 当大泡逐渐回落消失时。
◦ 糖液颜色开始加深。
• 观察颜色变化。
◦ 从浅黄色变为枣红色。
◦ 这个瞬间非常关键。
◦ 枣红色时立即下入肉块。
◦ 过早则甜腻,过晚则发苦。
◦ 动作务必迅速而准确。
◦ 糖色是红亮色泽的来源。
◦ 也是风味层次的基础。
• 煸炒肉块。
◦ 快速颠锅,使每块肉均匀裹上糖色。
◦ 持续翻炒约三到五分钟。
◦ 直到肉块表面微微焦黄。
◦ 部分油脂被煸炒出来。
◦ 这样吃起来肥而不腻。
◦ 同时香味物质充分释放。
◦ 煸出的猪油可倒出部分。
◦ 留作炒青菜风味极佳。
五、 炖煮入味:时间与火候的艺术
• 加入调料。
◦ 沿着锅边烹入花雕酒。
◦ 瞬间激发出浓郁酒香。
◦ 接着倒入适量生抽。
◦ 再加入少许老抽上色。
◦ 放入所有香料:姜、葱、蒜等。
◦ 与肉块一起翻炒均匀。
◦ 让酱香与肉香充分融合。
◦ 翻炒约两分钟至香气扑鼻。
• 注入开水。
◦ 务必一次性加足开水。
◦ 水量要完全没过肉块。
◦ 甚至可以略多一些。
◦ 避免中途再次加水。
◦ 大火烧开后转小火。
◦ 盖上锅盖,慢火焖炖。
◦ 这是“入口即化”的关键。
◦ 时间至少需要一小时。
• 慢炖过程。
◦ 保持汤面微沸即可。
◦ 火候切忌过大过急。
◦ 否则容易烧干且肉不烂。
◦ 期间可偶尔开盖查看。
◦ 用勺子轻轻推动一下。
◦ 防止粘锅底的情况发生。
◦ 但尽量不要频繁翻动。
◦ 以免影响肉块的完整。
六、 收汁与装盘:成就最终美味
• 大火收汁。
◦ 炖煮一小时后。
◦ 用筷子戳一下瘦肉部分。
◦ 若能轻松戳透即表示已软烂。
◦ 此时根据汤汁咸度加盐。
◦ 开大火,将汤汁收浓。
◦ 用锅铲不停搅动。
◦ 防止糊底,并让汤汁变稠。
◦ 均匀包裹在每一块肉上。
• 收汁技巧。
◦ 收到汤汁浓稠如蜜。
◦ 油亮红润的汤汁紧裹肉块。
◦ 锅中泛起密集的大泡。
◦ 即可准备关火出锅。
◦ 收汁程度依个人喜好。
◦ 喜欢拌饭可多留些汤汁。
◦ 整个过程需密切留意。
◦ 最后阶段变化非常迅速。
• 最终成品。
◦ 将红烧肉盛入预热好的盘中。
◦ 可烫几棵小油菜围边。
◦ 既点缀色彩,又解油腻。
◦ 撒上少许葱花或香菜末。
◦ 一道色香味俱全的红烧肉完成。
◦ 肉质软糯,肥而不腻。
◦ 咸中带甜,回味无穷。
◦ 配上一碗白米饭是绝配。
七、 要点总结与升华
• 成功关键。
◦ 选材是基础,务必新鲜。
◦ 焯水步骤不可省略。
◦ 炒糖色是技术核心。
◦ 火候控制是成败关键。
◦ 耐心慢炖是美味保证。
• 变化与创新。
◦ 可加入土豆、鹌鹑蛋同烧。
◦ 吸收肉汤,滋味更丰富。
◦ 也可尝试用啤酒代替水。
◦ 别有一番风味层次。
◦ 但万变不离其宗。
◦ 核心技法仍需掌握。
烹饪是一门需要实践的艺术,红烧肉更是如此。希望这份详尽的食谱能成为您厨房路上的得力助手,愿您能享受从准备到品尝的整个过程,与家人朋友分享这份由时间与匠心凝聚而成的温暖美味。每一次尝试都是一次经验的积累,祝您烹饪愉快,早日成就属于自己的招牌红烧肉!。
'''
# Chunk the text. The prob_threshold should be between (0, 1). The lower it is, the more chunks will be generated.
# Therefore adjust it to your need, when prob_threshold is small like 0.000001, each token is one chunk,
# when it is set to 1, the whole text will be one chunk, and will be forced to choose a best possible position to chunk when it is about to exceed the max_tokens_per_chunk and no token satisfy the prob_threshold.
chunks, token_pos = chunk_text_with_max_chunk_size(model, doc, tokenizer, prob_threshold=0.5, max_tokens_per_chunk = 100)
# print chunks
for i, (c, t) in enumerate(zip(chunks, token_pos)):
print(f"-----chunk: {i}----token_idx: {t}--------")
print(c)
```
## Citation
```bibtex
@article{bert-chunker,
title={bert-chunker: Efficient and Trained Chunking for Unstructured Documents},
author={Yannan Luo},
year={2024},
url={https://github.com/jackfsuia/bert-chunker}
}
```
Base model is from [bge-small-zh-v1.5](https://huggingface.co/BAAI/bge-small-zh-v1.5).