สร้างแชทบ็อตกับ Gemma

ดูใน ai.google.dev เรียกใช้ใน Google Colab เปิดใน Vertex AI ดูแหล่งที่มาใน GitHub

โมเดลภาษาขนาดใหญ่ (LLM) เช่น Gemma เชี่ยวชาญในการสร้างคำตอบที่เป็นประโยชน์ จึงเหมาะอย่างยิ่งสำหรับการสร้างผู้ช่วยเสมือนและแชทบ็อต

โดยทั่วไปแล้ว LLM จะทำงานในลักษณะที่ไม่เก็บสถานะ หมายความว่าไม่มีหน่วยความจำส่วนตัวสำหรับจัดเก็บการสนทนาในอดีต พรอมต์หรือคำถามแต่ละรายการจะได้รับการประมวลผลแยกกัน โดยไม่คำนึงถึงการโต้ตอบก่อนหน้านี้ อย่างไรก็ตาม แง่มุมสำคัญของการสนทนาอย่างเป็นธรรมชาติคือความสามารถในการรักษาบริบทจากการโต้ตอบก่อนหน้านี้ หากต้องการก้าวข้ามข้อจำกัดนี้และทำให้ LLM รักษาบริบทการสนทนาได้ คุณต้องให้ข้อมูลที่เกี่ยวข้องอย่างชัดเจน เช่น ประวัติการสนทนา (หรือส่วนที่เกี่ยวข้อง) ในพรอมต์ใหม่แต่ละรายการที่แสดงต่อ LLM

บทแนะนำนี้จะแสดงวิธีพัฒนาแชทบ็อตโดยใช้ตัวแปรโมเดลที่ปรับแต่งตามวิธีการของ Gemma

ตั้งค่า

การตั้งค่า Gemma

หากต้องการจบบทแนะนำนี้ คุณจะต้องทำตามวิธีการตั้งค่าที่การตั้งค่า Gemma ก่อน วิธีการตั้งค่า Gemma จะแสดงวิธีดำเนินการต่อไปนี้

  • เข้าถึง Gemma ใน kaggle.com
  • เลือกรันไทม์ของ Colab ที่มีทรัพยากรเพียงพอที่จะเรียกใช้ โมเดล Gemma 2B
  • สร้างและกำหนดค่าชื่อผู้ใช้และคีย์ API ของ Kaggle

หลังจากตั้งค่า Gemma เสร็จแล้ว ให้ไปยังส่วนถัดไปซึ่งจะตั้งค่าตัวแปรสภาพแวดล้อมสำหรับสภาพแวดล้อม Colab

ตั้งค่าตัวแปรสภาพแวดล้อม

ตั้งค่าตัวแปรสภาพแวดล้อมสำหรับ KAGGLE_USERNAME และ KAGGLE_KEY

import os
from google.colab import userdata

# Note: `userdata.get` is a Colab API. If you're not using Colab, set the env
# vars as appropriate for your system.
os.environ["KAGGLE_USERNAME"] = userdata.get('KAGGLE_USERNAME')
os.environ["KAGGLE_KEY"] = userdata.get('KAGGLE_KEY')

ติดตั้งการอ้างอิง

ติดตั้ง Keras และ KerasNLP

# Install Keras 3 last. See https://keras.io/getting_started/ for more details.
pip install -q tensorflow-cpu
pip install -q -U keras-nlp tensorflow-hub
pip install -q -U "keras>=3"
pip install -q -U tensorflow-text

เลือกแบ็กเอนด์

Keras เป็น API การเรียนรู้เชิงลึกที่มีหลายกรอบและมีระดับสูงซึ่งออกแบบมาให้ใช้งานง่าย Keras 3 ให้คุณเลือกแบ็กเอนด์ ได้แก่ TensorFlow, JAX หรือ PyTorch ทั้ง 3 วิธีนี้เหมาะกับบทแนะนำนี้

import os

# Select JAX as the backend
os.environ["KERAS_BACKEND"] = "jax"

# Pre-allocate 100% of TPU memory to minimize memory fragmentation
os.environ["XLA_PYTHON_CLIENT_MEM_FRACTION"] = "1.0"

นำเข้าแพ็กเกจ

นำเข้า Keras และ KerasNLP

import keras
import keras_nlp

# for reproducibility
keras.utils.set_random_seed(42)

สร้างอินสแตนซ์ของโมเดล

KerasNLP ให้บริการนำสถาปัตยกรรมโมเดลยอดนิยมจำนวนมากมาใช้ ในบทแนะนำนี้ คุณจะได้สร้างอินสแตนซ์ของโมเดลโดยใช้ GemmaCausalLM ซึ่งเป็นโมเดล Gemma จากต้นทางถึงปลายทางสำหรับโมเดลภาษาทั่วไป โมเดลภาษาทั่วไปจะคาดการณ์โทเค็นถัดไปตามโทเค็นก่อนหน้า

สร้างอินสแตนซ์โมเดลโดยใช้เมธอด from_preset:

gemma_lm = keras_nlp.models.GemmaCausalLM.from_preset("gemma2_instruct_2b_en")

ฟังก์ชัน GemmaCausalLM.from_preset() จะสร้างอินสแตนซ์โมเดลจากสถาปัตยกรรมและน้ำหนักที่กำหนดล่วงหน้า ในโค้ดด้านบน สตริง "gemma2_instruct_2b_en" ระบุค่าที่กำหนดล่วงหน้าของโมเดล Gemma 2 2B ที่มีพารามิเตอร์ 2 พันล้านรายการ นอกจากนี้ยังมีโมเดล Gemma ที่มีพารามิเตอร์ 7B, 9B และ 27B ให้ใช้งานด้วย คุณดูสตริงโค้ดสำหรับโมเดล Gemma ได้ในรูปแบบโมเดลใน Kaggle

ใช้เมธอด summary เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดล

gemma_lm.summary()

จากข้อมูลสรุปจะเห็นได้ว่าโมเดลนี้มีพารามิเตอร์ที่ฝึกได้ 2.6 พันล้านรายการ

กำหนดฟังก์ชันตัวช่วยการจัดรูปแบบ

from IPython.display import Markdown
import textwrap

def display_chat(prompt, text):
  formatted_prompt = "<font size='+1' color='brown'>🙋‍♂️<blockquote>" + prompt + "</blockquote></font>"
  text = text.replace('•', '  *')
  text = textwrap.indent(text, '> ', predicate=lambda _: True)
  formatted_text = "<font size='+1' color='teal'>🤖\n\n" + text + "\n</font>"
  return Markdown(formatted_prompt+formatted_text)

def to_markdown(text):
  text = text.replace('•', '  *')
  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))

กำลังสร้างแชทบ็อต

โมเดล gemma2_instruct_2b_en ที่ปรับแต่งตามคำสั่งของ Gemma ได้รับการปรับแต่งเพื่อให้เข้าใจโทเค็นการเลี้ยวต่อไปนี้

<start_of_turn>user\n  ... <end_of_turn>\n
<start_of_turn>model\n ... <end_of_turn>\n

บทแนะนำนี้ใช้โทเค็นเหล่านี้เพื่อสร้างแชทบ็อต โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับโทเค็นการควบคุม Gemma ที่หัวข้อการจัดรูปแบบและวิธีการของระบบ

สร้างโปรแกรมช่วยแชทเพื่อจัดการสถานะการสนทนา

class ChatState():
  """
  Manages the conversation history for a turn-based chatbot
  Follows the turn-based conversation guidelines for the Gemma family of models
  documented at https://ai.google.dev/gemma/docs/formatting
  """

  __START_TURN_USER__ = "<start_of_turn>user\n"
  __START_TURN_MODEL__ = "<start_of_turn>model\n"
  __END_TURN__ = "<end_of_turn>\n"

  def __init__(self, model, system=""):
    """
    Initializes the chat state.

    Args:
        model: The language model to use for generating responses.
        system: (Optional) System instructions or bot description.
    """
    self.model = model
    self.system = system
    self.history = []

  def add_to_history_as_user(self, message):
      """
      Adds a user message to the history with start/end turn markers.
      """
      self.history.append(self.__START_TURN_USER__ + message + self.__END_TURN__)

  def add_to_history_as_model(self, message):
      """
      Adds a model response to the history with start/end turn markers.
      """
      self.history.append(self.__START_TURN_MODEL__ + message)

  def get_history(self):
      """
      Returns the entire chat history as a single string.
      """
      return "".join([*self.history])

  def get_full_prompt(self):
    """
    Builds the prompt for the language model, including history and system description.
    """
    prompt = self.get_history() + self.__START_TURN_MODEL__
    if len(self.system)>0:
      prompt = self.system + "\n" + prompt
    return prompt

  def send_message(self, message):
    """
    Handles sending a user message and getting a model response.

    Args:
        message: The user's message.

    Returns:
        The model's response.
    """
    self.add_to_history_as_user(message)
    prompt = self.get_full_prompt()
    response = self.model.generate(prompt, max_length=2048)
    result = response.replace(prompt, "")  # Extract only the new response
    self.add_to_history_as_model(result)
    return result

แชทกับโมเดล

เริ่มแชทกับโมเดล

chat = ChatState(gemma_lm)
message = "Tell me, in a few words,  how to compute all prime numbers up to 1000?"
display_chat(message, chat.send_message(message))

🙋‍♂️

บอกวิธีคำนวณจำนวนเฉพาะทั้งหมดให้ได้ 1,000 คำสั้นๆ หน่อย
🤖

Sieve of Eratosthenes

สนทนาต่อ

message = "Now in Python! No numpy, please!"
display_chat(message, chat.send_message(message))

🙋‍♂️

อยู่ใน Python แล้ว! ไม่เอาน่า งั้นก็
🤖

def sieve_of_eratosthenes(n):
  """Returns a list of prime numbers up to n."""
  primes = [True] * (n + 1)
  primes[0] = primes[1] = False
  for i in range(2, int(n**0.5) + 1):
    if primes[i]:
      for j in range(i * i, n + 1, i):
        primes[j] = False
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)

คำอธิบาย

  1. การเริ่มต้น:

    • primes = [True] * (n + 1): สร้างรายการ primes ของค่าบูลีน โดยเบื้องต้นจะถือว่าจำนวนทั้งหมดเป็นเฉพาะค่า
    • primes[0] = primes[1] = False: กำหนดให้ 0 และ 1 เป็นแบบไม่เจาะจงระดับ
  2. การเน้นย้ำ:

    • for i in range(2, int(n**0.5) + 1):: วนซ้ำจาก 2 ถึงรากที่ 2 ของ n เราต้องตรวจสอบจนถึงรากที่สองเท่านั้น เนื่องจากจำนวนผสมจะต้องมีตัวประกอบเฉพาะน้อยกว่าหรือเท่ากับรากที่สอง
    • if primes[i]:: ถ้ามีการทำเครื่องหมาย i ว่าเป็นรายการหลัก:
      • for j in range(i * i, n + 1, i):: ทำเครื่องหมายพหุคูณทั้งหมดของ i ว่าเป็นค่าที่ไม่ตรง
  3. ผลลัพธ์

    • return [i for i, is_prime in enumerate(primes) if is_prime]: สร้างรายการดัชนีที่ primes[i] เป็น "จริง" ซึ่งแสดงจำนวนเฉพาะ

โปรดแจ้งให้เราทราบหากต้องการคำอธิบายเพิ่มเติมเกี่ยวกับส่วนใด

message = "Thank you, it works! Can you explain the code in French?"
display_chat(message, chat.send_message(message))

🙋‍♂️

ขอบคุณ มันได้ผล! ช่วยอธิบายรหัสเป็นภาษาฝรั่งเศสหน่อยได้ไหม
🤖

เบียน ซูร์! Voici une explication du code en français :

def sieve_of_eratosthenes(n):
  """Retourne une liste de nombres premiers jusqu'à n."""
  primes = [True] * (n + 1)
  primes[0] = primes[1] = False
  for i in range(2, int(n**0.5) + 1):
    if primes[i]:
      for j in range(i * i, n + 1, i):
        primes[j] = False
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)

ข้อยกเว้น:

  1. การเริ่มต้น

    • primes = [True] * (n + 1): Crée une liste primes de valeurs booléennes, เริ่มต้น supposant que tous les nombres sont premiers
    • primes[0] = primes[1] = False: การแข่งขัน Définit 0 et 1 ครั้งแรกที่ไม่ใช่วิดีโอพรีเมียร์
  2. การทบทวน:

    • for i in range(2, int(n**0.5) + 1):: Itère de 2 jusqu'à la racine carrée de n Nous ne devons vérifier que jusqu'à la racine carrée car tout nombreComposit doit avoir unfacteur premier inférieur ou égal à sa racine carrée.
    • if primes[i]:: Si i est considéré comme premier:
      • for j in range(i * i, n + 1, i):: Marquer tous les Multiples de i เป็นการแข่งขันที่ไม่ใช่วิดีโอพรีเมียร์
  3. ผลลัพธ์:

    • return [i for i, is_prime in enumerate(primes) if is_prime]: Crée une liste des indices où primes[i] est vrai, représentant les nombres premiers.

N'hésitez pas à medemander si vous avez besoin d'une explicationplus détaillée de quelque เลือก!

message = "Great! Now add those explanations as comments in the code."
display_chat(message, chat.send_message(message))

🙋‍♂️

เยี่ยมมาก เพิ่มคำอธิบายเหล่านั้นเป็นความคิดเห็นในโค้ด
🤖

def sieve_of_eratosthenes(n):
  """Retourne une liste de nombres premiers jusqu'à n."""
  # Initialise une liste de boolean avec True pour tous les nombres de 0 à n
  primes = [True] * (n + 1)
  # Définit 0 et 1 comme non-premiers
  primes[0] = primes[1] = False
  # Itère de 2 à la racine carrée de n
  for i in range(2, int(n**0.5) + 1):
    # Si i est considéré comme premier
    if primes[i]:
      # Itère sur tous les multiples de i
      for j in range(i * i, n + 1, i):
        # Définit les multiples de i comme non-premiers
        primes[j] = False
  # Retourne la liste des indices des nombres premiers
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)

ข้อยกเว้น:

  • การเริ่มต้น
    • primes = [True] * (n + 1): Crée une liste primes de valeurs booléennes, เริ่มต้น supposant que tous les nombres sont premiers
    • primes[0] = primes[1] = False: การแข่งขัน Définit 0 et 1 ครั้งแรกที่ไม่ใช่วิดีโอพรีเมียร์
  • การทบทวน:
    • for i in range(2, int(n**0.5) + 1):: Itère de 2 jusqu'à la racine carrée de n Nous ne devons vérifier que jusqu'à la racine carrée car tout nombreComposit doit avoir unfacteur premier inférieur ou égal à sa racine carrée.
    • if primes[i]:: Si i est considéré comme premier:
      • for j in range(i * i, n + 1, i):: Marquer tous les Multiples de i เป็นการแข่งขันที่ไม่ใช่วิดีโอพรีเมียร์
  • ผลลัพธ์:
    • return [i for i, is_prime in enumerate(primes) if is_prime]: Crée une liste des indices où primes[i] est vrai, représentant les nombres premiers.

ทดสอบการตอบสนองที่สร้างขึ้นโดยการเรียกใช้โค้ดที่สร้างขึ้น

def sieve_of_eratosthenes(n):
  """Retourne une liste de nombres premiers jusqu'à n."""
  # Initialise une liste de boolean avec True pour tous les nombres de 0 à n
  primes = [True] * (n + 1)
  # Définit 0 et 1 comme non-premiers
  primes[0] = primes[1] = False
  # Itère de 2 à la racine carrée de n
  for i in range(2, int(n**0.5) + 1):
    # Si i est considéré comme premier
    if primes[i]:
      # Itère sur tous les multiples de i
      for j in range(i * i, n + 1, i):
        # Définit les multiples de i comme non-premiers
        primes[j] = False
  # Retourne la liste des indices des nombres premiers
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]

ใช้เมธอด get_history เพื่อดูวิธีที่คลาส Chat เก็บรักษาบริบททั้งหมดไว้

print(chat.get_history())
<start_of_turn>user
Tell me, in a few words,  how to compute all prime numbers up to 1000?<end_of_turn>
<start_of_turn>model
**Sieve of Eratosthenes.** 
<end_of_turn><start_of_turn>user
Now in Python! No numpy, please!<end_of_turn>
<start_of_turn>model

```python
def sieve_of_eratosthenes(n):
  """Returns a list of prime numbers up to n."""
  primes = [True] * (n + 1)
  primes[0] = primes[1] = False
  for i in range(2, int(n**0.5) + 1):
    if primes[i]:
      for j in range(i * i, n + 1, i):
        primes[j] = False
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)
```

**Explanation:**

1. **Initialization:**
   - `primes = [True] * (n + 1)`: Creates a list `primes` of boolean values, initially assuming all numbers are prime.
   - `primes[0] = primes[1] = False`: Sets 0 and 1 as non-prime.

2. **Iteration:**
   - `for i in range(2, int(n**0.5) + 1):`: Iterates from 2 to the square root of `n`. We only need to check up to the square root because any composite number must have a prime factor less than or equal to its square root.
   - `if primes[i]:`: If `i` is marked as prime:
     - `for j in range(i * i, n + 1, i):`: Marks all multiples of `i` as non-prime.

3. **Result:**
   - `return [i for i, is_prime in enumerate(primes) if is_prime]`: Creates a list of indices where `primes[i]` is True, representing the prime numbers.


Let me know if you'd like a more detailed explanation of any part! 
<end_of_turn><start_of_turn>user
Thank you, it works! Can you explain the code in French?<end_of_turn>
<start_of_turn>model
Bien sûr ! Voici une explication du code en français :

```python
def sieve_of_eratosthenes(n):
  """Retourne une liste de nombres premiers jusqu'à n."""
  primes = [True] * (n + 1)
  primes[0] = primes[1] = False
  for i in range(2, int(n**0.5) + 1):
    if primes[i]:
      for j in range(i * i, n + 1, i):
        primes[j] = False
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)
```

**Explication:**

1. **Initialisation:**
   - `primes = [True] * (n + 1)`: Crée une liste `primes` de valeurs booléennes, initialement supposant que tous les nombres sont premiers.
   - `primes[0] = primes[1] = False`: Définit 0 et 1 comme non-premiers.

2. **Itération:**
   - `for i in range(2, int(n**0.5) + 1):`: Itère de 2 jusqu'à la racine carrée de `n`. Nous ne devons vérifier que jusqu'à la racine carrée car tout nombre composite doit avoir un facteur premier inférieur ou égal à sa racine carrée.
   - `if primes[i]:`: Si `i` est considéré comme premier:
     - `for j in range(i * i, n + 1, i):`:  Marquer tous les multiples de `i` comme non-premiers.

3. **Resultat:**
   - `return [i for i, is_prime in enumerate(primes) if is_prime]`: Crée une liste des indices où `primes[i]` est vrai, représentant les nombres premiers.


N'hésitez pas à me demander si vous avez besoin d'une explication plus détaillée de quelque chose! 
<end_of_turn><start_of_turn>user
Great! Now add those explanations as comments in the code.<end_of_turn>
<start_of_turn>model

```python
def sieve_of_eratosthenes(n):
  """Retourne une liste de nombres premiers jusqu'à n."""
  # Initialise une liste de boolean avec True pour tous les nombres de 0 à n
  primes = [True] * (n + 1)
  # Définit 0 et 1 comme non-premiers
  primes[0] = primes[1] = False
  # Itère de 2 à la racine carrée de n
  for i in range(2, int(n**0.5) + 1):
    # Si i est considéré comme premier
    if primes[i]:
      # Itère sur tous les multiples de i
      for j in range(i * i, n + 1, i):
        # Définit les multiples de i comme non-premiers
        primes[j] = False
  # Retourne la liste des indices des nombres premiers
  return [i for i, is_prime in enumerate(primes) if is_prime]

primes = sieve_of_eratosthenes(1000)
print(primes)
```

**Explication:**

* **Initialisation:**
    * `primes = [True] * (n + 1)`:  Crée une liste `primes` de valeurs booléennes, initialement supposant que tous les nombres sont premiers.
    * `primes[0] = primes[1] = False`: Définit 0 et 1 comme non-premiers.
* **Itération:**
    * `for i in range(2, int(n**0.5) + 1):`: Itère de 2 jusqu'à la racine carrée de `n`. Nous ne devons vérifier que jusqu'à la racine carrée car tout nombre composite doit avoir un facteur premier inférieur ou égal à sa racine carrée.
    * `if primes[i]:`: Si `i` est considéré comme premier:
        * `for j in range(i * i, n + 1, i):`:  Marquer tous les multiples de `i` comme non-premiers.
* **Resultat:**
    * `return [i for i, is_prime in enumerate(primes) if is_prime]`: Crée une liste des indices où `primes[i]` est vrai, représentant les nombres premiers. 



<end_of_turn>

สรุปและอ่านเพิ่มเติม

ในบทแนะนำนี้ คุณได้เรียนรู้วิธีแชทกับโมเดลที่ปรับแต่ง Gemma 2B Instruction โดยใช้ Keras ใน JAX

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Gemma ได้ในคู่มือและบทแนะนำเหล่านี้