2.2 👩‍🎨 Дизайн промптов в LangChain

⚔️ Spam 🆚 Crypto

Представьте, что вас внезапно охватила страсть к миру криптовалют и вы решили погрузиться в эту увлекательную тему. Ваш первый шаг - присоединиться к тематическому чату в телеграме, где обсуждаются криптовалюты и всё, что с ними связано. Однако, как только вы открываете этот чат, вас буквально заваливает потоком сообщений - от советов и аналитики до сомнительных предложений и рекламы курсов. Вы стоите перед задачей отделить полезные сообщения от мусора и спама.

И вот здесь на помощь приходят LLM и могучий ChatGPT. Ваша задача - создать такой запрос, благодаря которому модель сможет определять, что является реальными и полезными сообщениями от пользователей, а что бесполезным спамом.

Что на входе? Вам предоставляется датасет с двумя столбцами: text_id (уникальный идентификатор сообщения) и text (содержание сообщения).

import pandas as pd
df = pd.read_csv('https://stepik.org/media/attachments/lesson/1110806/100_crypto_messages.csv')

Что сделать? Для каждого сообщения необходимо определить, является ли оно спамом (1) или не спамом (0) и записать эту информацию в столбец is_spam.
Что на выходе? csv файл, содержащий два столбца - text_id и is_spam.
Что использовать? В этой задаче не подразумевается использование сторонних ML библиотек, кроме API ChatGPT и библиотеки pandas для обработки данных.
Замечание: Точность вашего решения (доля верных ответов) должна быть не ниже 75%.


template = '''Если текст представленный в разделе Context является спамом ответь 1, иначе ответь 0

  Context: {context}

  Answer: '''

Ничего хитромудрого я не придумал, а написал вот такой промт

prompt_template = """тебе будет передан текст сообщения. Очень вероятно, что он будет содеражть тематику криптовалют. Опередели по содерданию является ли текст спамом

 

Context: {text_input}

 

Question: Это спам?

 

Answer: Если спам верни 1, если нет - верни 0. Ничего кроме цифр

"""

Точность 93%

Комментарий закреплён

Здесь файл с ответами, по которому сравнивается точность в системе. Можно посмотреть и проанализировать разницу со своими ответами :)

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 1.0.

@Никита_Тенишев, а где промпт?

Через примеры результат получился лучше, чем без них.

examples = [
   {
    "query": "Удаленная работа. От нас: Зп от 2500$",
    "answer": "1"
}, {
    "query": "Удалённый заработок. Время 1-2часа в день.",
    "answer": "1"
}, {
    "query": "Меня всегда интересовал вопрос безопасности хранения криптовалюты. Какие лучшие методы 
    хранения считаются наиболее надежными?",
    "answer": "0"
}
]
prefix = """Ответь на вопрос, исходя из контекста ниже. Если на вопрос невозможно ответить, используя предоставленную информацию ответь «0».
Твоя задача - для каждого сообщения необходимо определить, является ли оно спамом или не спамом. Тематика сообщений - криптовалюты.
Если сообщение спам - выведи "1", если сообщение не спам - выведи "0".
Вот несколько примеров:
"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.99.

@Егошин_Михаил, это через FewShotPromptTemplate получается?

 @Егошин_Михаил, а можете скрипт выложить, что то с suffix не получается

Использовал IlyaGusev/saiga_mistral_7b_lora. Без части, где я модели рассказываю какой сегодня день и какая она вся распрекрасная, результат тот же. Хотя в прошлом задании он был хуже где-то на 10 балов.

 

prefix = """ Сейчас 24 октября 2020 года, 16 часов дня. Ты свеж, бодр и ОЧЕНЬ хочешь

качествено выполнять свою работу, ни одна деталь не ускользает от тебя.

Ты опытный и ОЧЕНЬ ВНИМАТЕЛЬНЫЙ аналитик. Ты знаешь, что за успешное выполнение задачи,

которая будет описана ниже тебе дадут 10 тысяч долларов.

Твоя задача ВНИМАТЕЛЬНО И ТОЧНО прочитать сообщение из социальной сети и понять СПАМ это или нет.

В ответе ты укажешь только 0, если сообщение НЕ спам или 1, если это не спам

 

При принятии решения руководствуйся следующим:

- Сообщения взяты из каналов про криптовалюты, поэтому они либо содержат аналитику по

  криптовалам, вопросы по ним либо спам. Если сообщение не содержит никакой аналитической информации, то

  это спам;

- если в сообщении предлагаеться удаленная работа, то это спам;

- если в сообщении предлагаеться "быстро заработать денег", то это спам.

"""

 

examples = [

    {"query": "Удаленная работа. От нас: Зп от 2500$", "answer": 1},

    {

        "query": "Удалённый заработок. Время 1-2часа в день. Можно без опыта всему обучим. заработок в долларах. Возраст 20+",

        "answer": 1,

    },

    {

        "query": "Я слышал, что некоторые банки начали экспериментировать с использованием блокчейна для улучшения системы денежных переводов. Это может изменить финансовую индустрию?",

        "answer": 0,

    },

    {

        "query": "Что вы думаете о концепции децентрализованных бирж (DEX)? Какие преимущества они предоставляют по сравнению с традиционными биржами?",

        "answer": 0,

    },

]

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.92.

@Глеб_Будник, оригинальный промпт -). Интересно, сколько токенов ушло на задание?

С учетом ошибки в промте:

В ответе ты укажешь только 0, если сообщение НЕ спам или 1, если это не спам

отличный результат. Показывает стабильность модели к ошибкам, возможно, за счет избыточности информации в промпте.

Promt:

Ты ассистент, который фильтрует сообщения от спама. Интересует только информация о мире криптовалют. На выход принимается только целое число: 1 или 0.
1 — если сообщение явно похоже на СПАМ, содержит рекламу, предложение, совет
0 — полезная информация
Context: {text_input}
Question: Определи категорию сообщения
Answer: 

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.95.

@Ivan_Barmashov, Круто. Короткий, четко сформулированный промпт и отличный результат.

Сохраню, как пример )

def classify_spam(text):

# Запрос к API OpenAI

response = client.chat.completions.create(

model="gpt-3.5-turbo",

messages=[

{

"role": "system",

"content": (

"Ты ассистент, который помогает фильтровать сообщения от спама. "

"Сообщения, которые предлагают удаленную работу, заработок, содержат рекламу, предложения обучения "

"или советы по заработку, должны быть помечены как СПАМ (ответ 1). "

"Сообщения, которые содержат полезную информацию о мире криптовалют, должны быть помечены как НЕ СПАМ (ответ 0). "

"Примеры спама: 'Удаленная работа с заработком от 2500$', 'Обучение и заработок на криптовалютах'. "

"Примеры полезной информации: 'Новости о текущем состоянии биткоина'. "

"Ответ должен быть только в формате целого числа: 1 (СПАМ) или 0 (НЕ СПАМ)."

),

},

{

"role": "user",

"content": f"Message: {text}"

}

],

temperature=0,

)

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.97.

prompt_input = '''Представьте, что вас внезапно охватила страсть к миру криптовалют и вы решили погрузиться в эту увлекательную тему. Ваш первый шаг - присоединиться к тематическому чату в телеграме, где обсуждаются криптовалюты и всё, что с ними связано. Однако, как только вы открываете этот чат, вас буквально заваливает потоком сообщений - от советов и аналитики до сомнительных предложений и рекламы курсов. Вы стоите перед задачей отделить полезные сообщения от мусора и спама.

если сомневаешься, пиши 0

 '''

question_input = "Это спам?"

answer_output = "если спам, 1, иначе 0"

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 1.0.

С температурой 1 задачи детектирования решаются лучше, чем с 0.

import pandas as pd
import os
from utils import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
# Загрузка данных
df = pd.read_csv('100_crypto_messages.csv')
# Установка ключа API, если он еще не установлен
course_api_key = os.environ.get('OPENAI_API_KEY', '____')
# Инициализация модели с использованием ChatOpenAI
llm = ChatOpenAI(model_name="gpt-4o", temperature=1, course_api_key=course_api_key)
# Создание шаблона для prompt'а
prompt_template = PromptTemplate(
    input_variables=["text"],
    template="You are an expert in detecting spam messages. Determine if the following message is spam (1) or not spam (0). Respond with only '1' or '0': {text}"
)
# Создание цепочки для выполнения запросов
chain = LLMChain(llm=llm, prompt=prompt_template)
# Функция для предсказания спама
def predict_spam(text):
    result = chain.run(text=text)
    return result.strip()  # Преобразуем результат в 0 или 1
# Применение функции ко всем текстам
df['is_spam'] = df['text'].apply(predict_spam)
# Сохранение результата в CSV
df[['text_id', 'is_spam']].to_csv('spam_predictions.csv', index=False)

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.95.

template = """

Начальные данные: Меня охватила страсть к миру криптовалют и я решил погрузиться в эту увлекательную тему. Я добавился в один чат.

Однако, как только я открыл этот чат, меня буквально заваливает потоком сообщений - от советов и аналитики до сомнительных предложений и рекламы курсов.

Твоя задача отделить полезные сообщения от мусора и спама. Верни только целочисленное число: 1 - является спамои, 0 - не является спамом.

Context: {text_input}

Question: Является ли данное сообщение из чата спамом или нет? Если является спамом, ответь: 1. Если не является спамом, ответь: 0.

Answer:

"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 1.0.

Пример промпта при работе с нейронкой yandex gpt pro:

prompt_template = """Тебе будет дан текст, этот текст взят из тематического чата по криптовалютам, в котором общаются между собой люди и обсуждают криптовалюту.
Context: {text_input}
Question: Текст является спамом?
Answer: Твой ответ на вопрос должен содержать только одно число, без дополнительных слов и символов. Если спам: 1, если не спам: 0
"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.82.

from utils import NDTOpenAI

from langchain import PromptTemplate

 

client = NDTOpenAI(

    api_key= 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2Njk1NmI1ZTc0MzA4NjQyOTdkODFlMDYiLCJleHAiOjE3NTI2MDQzNzN9.0FLkPXvoJQl6rg7zfHsSqaNexPjPhL7TttGCu9MQIcY',  # ключ для доступа к апи

)


 

def funct(text):

 

    template =  ''' Предложение : {text} \n Это предложение из чата посвященного криптовалютам. Определи является ли данный текст спамом или рекламой или посвящен обсуждению криптовалют  \n

              Верни 1 если текст является спамом, 0 если нет \n

               "Твой ответ (просто цифра без слов) :  '''

 

    prompt_template = PromptTemplate( input_variables = ["text"] , template = template)


 

    prompt = prompt_template.format(text = text)



    messages = [

        {

            "role": "user",  # Роль - ассистент или юзер

            "content": prompt ,  # Сам промпт для подачи в ChatGPT

        }

    ]

 

    response = client.chat.completions.create(

        model="gpt-3.5-turbo",  # модель для выбора

        messages=messages,  # сообщение

        temperature=0,  # степень креативности ответа

    )

 

    return response.choices[0].message.content

 

df['spam_Id'] = df['text'].apply(funct)

 

df

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.95.

template = """Прочти сообщение тематического чата в телеграмме по криптовалюте. 
Context: {text_input}
Question: Является ли это сообщение спамом (1), предложением о работе (1) или не спамом (0)? Внимание: ответь только числом (int) 1 или 0
Answer: ...
"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.95.

0.98 по методике из прошлой задачи

prompt_template = """В контексте приведено сообщение из чата по криптовалютам. Сообщение является либо спамом, либо полезным сообщением. Спамом являются все сообщения с предложением работы или заработка. Ответь на вопрос используя информацию из контекста.

 

Context: {text_input}

 

Question: Является ли сообщение спамом? Если да - ответь 1, если нет - 0. Ответ должен содержать только 1 или 0, без дополнительных пояснений

 

Answer: ...

"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.98.

prompt_template = """Анализируем телеграм чат, где обсуждаются криптовалюты и всё, что с ними связано. 
Ответь на вопрос используя информацию из контекста.
Если на вопрос нельзя ответить, то ответь 0.
Context: {text_input}
Question: Определи, является ли сообщение спамом или не спамом. Сомнительные предложения и навязчивая реклама - спам.
Answer: Ответ в виде числа, где 1 - спам, 0 - не спам.
"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.98.

Вот с таким промптом точность ответа 81%: 

# Напишите промпт, указав инструкцию, запрос и выходной индикатор

template = """

As an enthusiast newly passionate about the world of cryptocurrencies, I've joined a Telegram chat dedicated to discussing all things related to cryptocurrencies. Upon entering the chat, I find myself inundated with a deluge of messages. These range from insightful advice and analysis to dubious offers and advertisements for courses. Faced with the challenge of sifting through this torrent of information, I seek to distinguish the valuable messages from the trash and spam.

Given the explosion of interest in cryptocurrencies, this chat encompasses a broad spectrum of discussions. Legitimate messages often contain thoughtful insights, analysis of market trends, sharing of experiences, or questions seeking deeper understanding. On the other hand, spam messages might include unsolicited advertisements, promises of quick profits without basis, requests for personal information under suspicious circumstances, and links to questionable websites.

Context: {text_input}

Considering the dynamics of cryptocurrency discussions and the types of messages described, please help me classify each message based on its content and intention.

Question: Does this message represent a valuable contribution to the chat, offering real insights or genuine queries about cryptocurrencies, or is it merely spam, cluttering the discussion with irrelevant or misleading information?

Answer: Please respond with 'valuable' for messages that contribute positively to the discussion, or 'spam' for messages that do not.

"""

prompt_template = PromptTemplate(

    input_variables=["text_input"],

    template=template

)

 Ну и далее код:

spam_labels = [] # Список, где будем хранить ответы модели

for text_input in tqdm(df['text']):

    prompt = prompt_template.format(text_input=text_input) # Добавляем сообщение в промпт

    spam_label = llm.predict(prompt) # Сохраняем ответ модели

    spam_labels.append(spam_label) # Добавляем ответ в список

# Конвертируем текстовые ответы в числовые значения

spam_labels = [1 if label == 'spam' else 0 for label in spam_labels]

 

# Добавляем числовые метки к датафрейму

df['is_spam'] = spam_labels # Создаём новый столбец из ответов модели

# Сохраняем итоговый датафрейм в новый CSV файл, содержащий 'text_id' и 'is_spam'

output_df = df[['text_id', 'is_spam']]

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.81.

Context: Сообщение из чата о пользователей о криптовалютах в котором много спама о необоснованном обогощении

Question: Является ли спамом сообщение: {}

Answer: 1 если спам, 0 иначе только одно из этих чисел

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.94.

template = """ 
Ты система поиска спапа. 
Тебе на вход подаются данные и нужно определить спам это или нет. 
Если сообщение спам, то необходимо вернуть 1. 
Если сообщение не спам, то нужно вернуть 0. 
Результат не должен быть развернутым, тольком метки 1 или 0. 
###
Context: {text_input}
###
Question: Это спам?
###
Answer:
"""
prompt_template = PromptTemplate(
    input_variables=["text_input"],
    template=template
)
prompt_template

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.97.

+

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.78.

prompt_template = '''
Тебе дано сообщение из чата о криптовалюте.
Если оно является реальным и полезным сообщением от пользователя на тему криптовалюты - выдай 0.
Иначе, если оно является спамом (например, сомнительные предложения или реклама курсов) - то выдай 1.
Context: {context}
Answer:
'''

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.97.

Кажется моё решение самое простое, но эффективное😂😅

prompt_template = """Ответь на вопрос используя информацию из контекста. Являляеться оно спамом или не спапом. Отвечашь можешь только 1 или 0. Где 1 - спам, а 0 - не спам.

Examples:

Удаленная работа. От нас: Зп от 2500$ = 1

Что вы думаете о концепции децентрализованных бирж (DEX)? Какие преимущества они предоставляют по сравнению с традиционными биржами? = 0

Context: {text_input}

Question: Определи, является ли оно спамом или не спамом. Если спам, то выдай 1, если нет то 0.

Answer:

"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.99.

prompt_template = """Действуй как спам-фильтр телеграм-канала, посвященного крипотовалютам и криптотрейдингу.
Твоя задача пометить как спам (метка 1) сообщения, посвященные легкому заработку, скаму, фроду, фишингу и прочих мошеннических сообщений.
Если сообщение носит целевой характер, и не относится к спами либо к мошенничеству, то его нужно пометить меткой 0.

Context: {text_input}

Question: Определи является ли сообщение спамом (мета 1) либо целевым (метка 0), в случае пограничных сообщений опирайся на контекст и косвенные признаки ?

Answer: 1 или 0"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.84.

Похвалюсь своим )) 

# Напишите промпт, указав инструкцию, запрос и выходной индикатор

template = """...

Context: Определи относится ли сообщение к спаму. Ответь "1", если да, "0", если нет. Пример сообщений, которые относятся к спаму: Предложения заработка и работы, поиск помощников

Question: {text_input}

Answer: ...

"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.92.

Чем проще - тем лучше...

template = """
Дан текст сообщения из чата о криптовалютах. Определите, содержит ли это сообщение полезную информацию или является спамом.
Текст сообщения: {text_input}
Вопрос: Является ли это сообщение спамом или содержит полезную информацию? Если это спам, ответьте '1', иначе ответьте '0'.
Ответ:
"""

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.95.

# Напишите промпт, указав инструкцию, запрос и выходной индикатор

template = """ Ответь на вопрос, опираясь на контекст ниже.

Если на вопрос нельзя ответить, используя информацию из контекста,

ответь '0'

Context: {text_input}

Question: 'Необходимо определить, является ли текст спамом (1) или не спамом (0)'

Answer: ...

"""

prompt_template = PromptTemplate(

    input_variables=["text_input"],

    template=template

)

Отлично! Теперь можешь оставить свой промпт во вкладке «‎Решения»‎ и посмотреть как решили другие Вы побили порог в 0.75: ваша точность 0.9.

template = """Ответь на вопрос, опираясь на контекст ниже.
Если много знаков вопроса, капса, призывов к действию, то это спам.
Если на вопрос нельзя ответить, используя информацию из контекста,
ответь '1'.

Context: {context}

Question: {query}

Answer: """

Вы побили порог в 0.75: ваша точность 0.81.

Пришлось потратить ~300000 токенов от API курса)))

template = """Ответь на вопрос, опираясь на тему "Изучение криптовалюты".
Если ответ на вопрос "Да", то отправь цифру 1, иначе цифру 0.
Признаки спама: предлагают заработок и писать в лс, конкретное число. 
Context: {text_input}
Question: Это сообщение является спамом?
Answer:
"""
# Init LLM
prompt = PromptTemplate(template=template, input_variables=["text_input"])
openai_llm = ChatOpenAI(temperature=0.0, max_tokens=4, course_api_key=course_api_key)
llm_chain = LLMChain(prompt=prompt, llm=openai_llm)
# Решаем задачу с помощью LLM курса
target_list = []
for text_input in tqdm(df['text']):
    target_list.append(llm_chain.run(text_input))
df_sub = df.copy()
df_sub['is_spam'] = list(map(int, target_list))
df_sub.to_csv('submission_2.2.7.csv', index=False)

Вы побили порог в 0.75: ваша точность 0.93.

def make_prompt(txt):

prompt = """

Веди себя как система, специализирующаяся на том,

чтобы определять спам письма. Сообщения разнообразны,

среди них есть как легитимные обсуждения криптовалютных

трендов, советы по безопасности, образовательные ресурсы,

так и спам, содержащий предложения, рекламные акции

и потенциально вводящую в заблуждение информацию.

Сценарий классификации должен быть чувствителен к общим шаблонам

спама, таким как агрессивный маркетинговый язык, обещания

легких денег или ссылки на внешние сайты. Однако при этом

он должен избегать ложных срабатываний, распознавая настоящие

сообщения, связанные с обсуждением криптовалют или советами.

Твой ответ должен содержать только цифру 0 если сообщение

не является спамом, и 1, если является.\n

Текст для анализа:\n ***

"""

 

prompt+= f'{txt}*** \nОтвет:'

return prompt

Вы побили порог в 0.75: ваша точность 0.93.