Учебное пособие
В этом учебном пособии мы разобьём пример текстового документа на фрагменты и сгенерируем контекстные ключевые слова для каждого из них, используя Llama 3.1.
Начнём с установки необходимых пакетов. Для инференса модели Llama мы используем DeepInfra, но вы можете воспользоваться услугами любого другого поставщика инференса.
#Установка зависимостей
!pip install tiktoken
!pip install openai
from config import DEEPINFRA_API_KEY
Сначала получите содержимое вашего документа. Для этого учебного пособия рекомендуемый размер документа составляет от 2 000 до 20 000 токенов.
document_content = ""
with open('./data/llama_article.txt', 'r') as file:
document_content = file.read()
Затем мы разобьём содержимое документа на фрагменты размером от 300 до 1000 токенов.
#разбиение на фрагменты (простой способ)
def split_into_chunks(content, chunk_size):
import tiktoken
enc = tiktoken.get_encoding("o200k_base")
a = enc.encode(content)
left, chunks = 0, []
while left < len(a):
arr = a[left : left+chunk_size]
chunks.append(enc.decode(arr))
left+=chunk_size
return chunks
chunks = split_into_chunks(document_content, 400)
#генерация фрагментированного содержимого
chunked_content = ""
for idx, text in enumerate(chunks):
chunked_content+=f"### Chunk {idx+1} ###\n{text}\n\n"
Теперь ваше `chunked_content` выглядит следующим образом:
### Chunk 1 ###
{chunk1}
### Chunk 2 ###
{chunk2}
..
Далее сгенерируем контекстные ключевые слова для лучшего представления фрагментов при создании embeddings. Здесь мы используем серверы DeepInfra для инференса.
from openai import OpenAI
openai = OpenAI(api_key=DEEPINFRA_API_KEY, base_url="https://api.deepinfra.com/v1/openai")
def deepinfra_run(system_prompt, user_message):
chat_completion = openai.chat.completions.create(
model="meta-llama/Meta-Llama-3.1-405B-Instruct",
messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": user_message}],
max_tokens=4096
)
return chat_completion.choices[0].message.content
system_prompt = '''
Каждый фрагмент разделён как ### Chunk [id] ###. Для каждого фрагмента сгенерируйте ключевые слова, необходимые для полного понимания фрагмента без необходимости обращаться к предыдущим фрагментам.
Не используйте просто "Список услуг", так как неясно, о каких услугах идёт речь. Убедитесь, что охвачены все фрагменты.
Пример вывода:
Chunk 1: BMW X5, pricings in France
Chunk 2: BMW X5, discounts
'''
keywords_st = deepinfra_run(system_prompt, chunked_content)
print(keywords_st)
Далее нам нужно разобрать сгенерированные ключевые слова в массив.
import re
def parse_keywords(content):
result = []
lines = content.strip().split('\n')
current_chunk = []
inline_pattern = re.compile(r'^\s*[^#:]+\s*:\s*(.+)$') # Соответствует строкам вида "Chunk1: word1, word2"
section_pattern = re.compile(r'^###\s*[^#]+\s*###$') # Соответствует строкам вида "### Chunk1 ###"
for line in lines:
line = line.strip()
if not line: continue
inline_match = inline_pattern.match(line)
if inline_match:
words_str = inline_match.group(1)
words = [word.strip() for word in words_str.split(',') if word.strip()]
result.append(words)
continue
if section_pattern.match(line):
if current_chunk:
result.append(current_chunk)
current_chunk = []
continue
if current_chunk is not None:
words = [word.strip() for word in line.split(',') if word.strip()]
current_chunk.extend(words)
if current_chunk:
result.append(current_chunk)
return result
keywords = parse_keywords(keywords_st)
print(keywords)
Теперь вы можете изменять фрагменты, используя сгенерированные ключевые слова.
Например,
chunk1 = #{keywords1}\n{chunk1}