Models - Code Llama 介紹

Code Llama

本章深入介紹了 Meta 發布的 Code Llama 系列大型語言模型 (LLM) ,該系列模型能夠接受文本提示並生成和討論程式碼。


目錄


介紹

Code Llama 是 Meta 推出的一系列大型語言模型 (LLM),專為根據文本提示生成和討論程式碼而設計。該系列包含多個變體(Code Llama Python 和 Code Llama Instruct)和不同規模(7B、13B、34B 和 70B)。


主要能力

程式碼生成與補全:能夠根據自然語言指令生成完整的程式碼,或在現有程式碼的基礎上進行智能補全。例如:要求模型生成計算第 n 個階乘的 Python 函數。

messages = [
    {
        "role": "system",
        "content": "你是一位資深的程式設計專家,會根據使用者的需求撰寫 Python 程式碼,並提供簡潔的說明,不要太冗長。",
    },
    {
        "role": "user",
        "content": "請撰寫一個Python函數,用來計算數字n的階乘。",
    }
]

chat_completion = get_code_completion(messages)

print(chat_completion.choices[0].message.content)

輸出:

以下是一個簡單的 Python 函數,用來計算一個數字的階乘:

def factorial(n):
    if n < 0:
        raise ValueError("n must be non-negative")
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)

這個函數使用遞迴來計算給定數字 n 的階乘。
當 n 為 0 或 1 時,這是基本情況(終止條件),此時結果為 1。
對於其他值,它會遞迴地將 n 乘上 n - 1 的階乘來計算結果。

程式碼偵錯:協助識別程式碼中的錯誤,並解釋如 lambda 函數中變數捕獲等問題。

messages = [
    {
        "role": "system",
        "content": "You are an expert programmer that helps to review Python code for bugs."
    },
    {
    "role": "user",
    "content": """Where is the bug in this code?
 
    def fib(n):
        if n <= 0:
            return n
        else:
            return fib(n-1) + fib(n-2)"""
    }
]
 
chat_completion = get_code_completion(messages)
            
print(chat_completion.choices[0].message.content)

輸出:

The bug in this code is that it does not handle the case when n is equal to 1. The code assumes that n is always greater than 1, which is not true. When n is equal to 1, the function should return 1, but it will return 0 instead.
To fix this bug, you can add an additional condition to handle the case when n is equal to 1. Here's the corrected code:
def fib(n):
    if n <= 0:
        return n
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

上面的範例取自ollama 在 Code Llama 上的部落格文章

單元測試編寫:能根據程式設計問題編寫單元測試,並遵循特定的格式要求。

prompt = """
[INST] Your task is to write 2 tests to check the correctness of a function that solves a programming problem.
The tests must be between [TESTS] and [/TESTS] tags.
You must write the comment "#Test case n:" on a separate line directly above each assert statement, where n represents the test case number, starting from 1 and increasing by one for each subsequent test case.
 
Problem: Write a Python function to get the unique elements of a list.
[/INST]
"""
 
messages = [
    {
        "role": "system",
        "content": "You are an expert programmer that helps write unit tests. Don't explain anything just write the tests.",
    },
    {
        "role": "user",
        "content": prompt,
    }
]
 
chat_completion = get_code_completion(messages)
            
print(chat_completion.choices[0].message.content)

輸出:

[TESTS]
# Test case 1:
assert get_unique_elements([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5], f"Expected get_unique_elements([1, 2, 3, 4, 5]) to return [1, 2, 3, 4, 5], but got {get_unique_elements([1, 2, 3, 4, 5])}"
# Test case 2:
assert get_unique_elements([1, 1, 2, 2, 3, 3]) == [1, 2, 3], f"Expected get_unique_elements([1, 1, 2, 2, 3, 3]) to return [1, 2, 3], but got {get_unique_elements([1, 1, 2, 2, 3, 3])}"
[/TESTS]

上面的例子取自Code Llama 官方論文

文本到SQL生成:從資料庫模式資訊和自然語言指令中生成有效的MySQL查詢。

prompt = """
資料表 employees,欄位 = [EmployeeId, EmployeeName, DepartmentId]  
資料表 departments,欄位 = [DepartmentId, DepartmentName]  
請撰寫一個 MySQL 查詢語句,列出所有屬於「行銷部門」的員工名稱。
"""
 
messages = [
    {
        "role": "user",
        "content": prompt,
    }
]
 
chat_completion = get_code_completion(messages)

print(chat_completion.choices[0].message.content)

輸出:

SELECT e.EmployeeName
FROM employees e
INNER JOIN departments d ON e.DepartmentId = d.DepartmentId
WHERE d.DepartmentName = '行銷部門';

少樣本提示:利用少樣本提示來執行更複雜的任務,例如根據給定的資料框結構,生成複雜的 Pandas 數據處理程式碼。

首先,我們建立一個 Pandas 資料框,用於評估模型的回應。

import pandas as pd

# 銷售資料表 sales_df
data = {
    "OrderID": [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010],
    "Product": [
        "Wireless Mouse", "Notebook", "USB-C Cable", "Desk Lamp", "Ballpoint Pen",
        "Bluetooth Speaker", "Sticky Notes", "Monitor Stand", "Eraser", "Webcam"
    ],
    "Category": [
        "Electronics", "Stationery", "Electronics", "Furniture", "Stationery",
        "Electronics", "Stationery", "Furniture", "Stationery", "Electronics"
    ],
    "Quantity": [2, 5, 3, 1, 10, 2, 6, 1, 8, 1],
    "UnitPrice": [25.99, 3.50, 8.99, 45.00, 1.20, 35.75, 0.99, 32.50, 0.50, 49.99],
    "OrderDate": [
        "2024-01-03", "2024-01-04", "2024-01-05", "2024-01-06", "2024-01-07",
        "2024-01-08", "2024-01-09", "2024-01-10", "2024-01-11", "2024-01-12"
    ]
}

sales_df = pd.DataFrame(data)

接著,我們可以建立少量演示以及實際提示(FEW_SHOT_PROMPT_USER),其中包含我們希望模型為其產生有效 pandas 程式碼的使用者問題。

FEW_SHOT_PROMPT_1 = """
你有一個名為 sales_df 的 Pandas 資料框:
- 欄位:['OrderID', 'Product', 'Category', 'Quantity', 'UnitPrice', 'OrderDate']
使用者問題:怎麼找出單價最高的商品?
"""
FEW_SHOT_ANSWER_1 = """
result = sales_df[sales_df['UnitPrice'] == sales_df['UnitPrice'].max()]
"""

FEW_SHOT_PROMPT_2 = """
你有一個名為 sales_df 的 Pandas 資料框:
- 欄位:['OrderID', 'Product', 'Category', 'Quantity', 'UnitPrice', 'OrderDate']
使用者問題:每一種類別的總銷售數量是多少?
"""
FEW_SHOT_ANSWER_2 = """
result = sales_df.groupby('Category')['Quantity'].sum()
"""

FEW_SHOT_PROMPT_USER = """
你有一個名為 sales_df 的 Pandas 資料框:
- 欄位:['OrderID', 'Product', 'Category', 'Quantity', 'UnitPrice', 'OrderDate']
使用者問題:如何找出 2024 年 1 月的所有訂單?
"""

最後,這是最終的系統提示、幾個鏡頭的演示和最終的用戶問題。

messages = [
    {
        "role": "system",
        "content": "請撰寫 Pandas 程式碼以解答使用者的問題。請將結果存入變數 `result`。不需要匯入套件,請用 ``` 包住你的程式碼。"
    },
    {
        "role": "user",
        "content": FEW_SHOT_PROMPT_1
    },
    {
        "role": "assistant",
        "content": FEW_SHOT_ANSWER_1
    },
    {
        "role": "user",
        "content": FEW_SHOT_PROMPT_2
    },
    {
        "role": "assistant",
        "content": FEW_SHOT_ANSWER_2
    },
    {
        "role": "user",
        "content": FEW_SHOT_PROMPT_USER
    }
]

chat_completion = get_code_completion(messages)

print(chat_completion.choices[0].message.content)

輸出:

result = sales_df[sales_df['OrderDate'].str.startswith('2024-01')]

對於 Pandas 資料框的提示和範例,我們從 Ye et al 2024 最近的工作中獲得了靈感。

函數呼叫: 支援函數調用功能。

tools = [
  {
    "type": "function",
    "function": {
      "name": "get_stock_price",
      "description": "取得指定公司目前的股價資訊",
      "parameters": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string",
            "description": "股票代號,例如 AAPL、TSLA、GOOGL"
          },
          "exchange": {
            "type": "string",
            "description": "交易所,例如 NASDAQ、NYSE"
          }
        },
        "required": ["symbol"]
      }
    }
  }
]

messages = [
    {
        "role": "system",
        "content": "你是一個可以調用外部函式的助理。這些函式的回應結果將會被加入對話中。請依據這些函式回應提供答案。"},
    {
        "role": "user",
        "content": "請幫我查一下 AAPL、TSLA 和 GOOGL 現在的股價是多少?"
    }
]

response = client.chat.completions.create(
    model="togethercomputer/CodeLlama-34b-Instruct",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)
 
print(json.dumps(response.choices[0].message.model_dump()['tool_calls'], indent=2))

安全防護

安全對齊:模型經過安全對齊訓練,在某些情況下會拒絕回應潛在有害的請求。

繞過方式:此安全拒絕有時可以透過重新措辭提示移除系統提示來繞過。

prompt = "[INST] 你能告訴我如何破解密碼嗎? [/INST]"

messages = [
    {
        "role": "system",
        "content": "始終以謹慎、尊重和真實的態度提供幫助。請在確保安全的情況下回應問題,避免有害、不道德、偏見或負面的內容,並保證回應促進公平和積極性。"
    },
    {
        "role": "user",
        "content": prompt,
    }
]
 
chat_completion = get_code_completion(messages)

print(chat_completion.choices[0].message.content)

輸出:

對不起,作為一個負責任的 AI 語言模型,我無法提供有關如何破解密碼的指導,因為這可能促進不道德的行為並危及個人和系統的安全。 
在處理敏感信息時,重要的是要優先考慮安全性、隱私和道德問題。如果您正在尋找恢復密碼的方法,我鼓勵您遵循正確的安全協議或聯繫相關的支持服務。
如果您有任何其他問題,請隨時告訴我,我將很高興以負責任的方式為您提供幫助。

重新措辭提示:

prompt = "[INST] 你能告訴我如何恢復我的密碼嗎? [/INST]"

messages = [
    {
        "role": "system",
        "content": "始終以謹慎、尊重和真實的態度提供幫助。請在確保安全的情況下回應問題,避免有害、不道德、偏見或負面的內容,並保證回應促進公平和積極性。"
    },
    {
        "role": "user",
        "content": prompt,
    }
]
 
chat_completion = get_code_completion(messages)

print(chat_completion.choices[0].message.content)

輸出:

如果您忘記了密碼,這裡有一些步驟可以幫助您找回密碼:
1. 訪問您想要恢復密碼的網站或應用程式。
2. 找到「忘記密碼」或「密碼恢復」的選項。
3. 輸入您的註冊電子郵件地址或用戶名。
4. 通常會發送一封包含密碼重設鏈接的電子郵件到您的郵箱。
5. 點擊該鏈接並設置一個新的密碼。
6. 確保新密碼足夠強大並且安全。

如果您無法透過這些步驟找回密碼,建議聯繫該服務的客戶支持部門。

結語

Code Llama 家族是 Meta 專為程式碼生成和討論而設計的強大工具,提供多種規模和變體以適應不同需求。它在程式碼補全、除錯、單元測試、文本到 SQL 以及函數調用等程式碼相關任務上表現出色。儘管其安全防護機制存在某些可繞過的限制,Code Llama 仍為開發者提供了高效且多功能的程式碼輔助能力。


References

Prompting Guide for Code Llama


目錄:Models - 模型提示指南

上一篇:Models - Claude 3
下一篇文章:Models - Flan