Пошаговый разбор

Урок 2 из 32 курса «Llama: сценарии использования»: официальный курс Llama Cookbook (Мета Лама) на русском языке. Этот урок бесплатный.

Учебное пособие

В этом учебном пособии мы разобьём пример текстового документа на фрагменты и сгенерируем контекстные ключевые слова для каждого из них, используя 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}

Полезные гиды