новый алгоритм диалога из групп фраз..
фразы ответа объединяем в группы примерно по 10 и более штук
нужную группу фраз находим по статистике ключевых слов данной группы
то есть ищем группу в которой больше совпадений слов которые есть в фразе ввода
группы фраз ответа разделяем строкой с символом =
фразы ответа храним в файле фразы1.txt и фразы2.txt
фразы ввода сохраняем в другом файле - ввод фраз.txt
итак я ввожу фразу -
программа находит подходящую группу фраз ответа по её набору (совпадений) ключевых слов
далее она выводит случайную фразу из найденной группы фраз ответов
затем я ввожу новую фразу - и так далее по циклу диалога из наших фраз
import random
import re
def get_words(text):
text = text.lower()
text = re.sub(r'[^\w\s]', '', text)
words = text.split()
stop_words = {'и', 'в', 'на', 'с', 'по', 'как', 'что', 'к', 'из', 'за', 'от', 'для', 'о', 'а', 'но', 'то', 'же'}
words = [w for w in words if w not in stop_words]
return set(words)
def load_response_groups(filename):
with open(filename, encoding='utf-8') as f:
lines = [line.strip() for line in f.readlines()]
groups = []
current_group = []
for line in lines:
if line == '=':
if current_group:
groups.append(current_group)
current_group = []
elif line != '':
current_group.append(line)
if current_group:
groups.append(current_group)
return groups
def build_group_keywords(groups):
group_keywords = []
for group in groups:
words = set()
for phrase in group:
words.update(get_words(phrase))
group_keywords.append(words)
return group_keywords
def find_best_group(input_words, group_keywords):
max_matches = 0
best_indices = []
for i, keywords in enumerate(group_keywords):
matches = len(input_words.intersection(keywords))
if matches > max_matches:
max_matches = matches
best_indices = [i]
elif matches == max_matches and matches > 0:
best_indices.append(i)
if not best_indices:
return None
return random.choice(best_indices)
def main():
groups = load_response_groups('фразы1.txt')
group_keywords = build_group_keywords(groups)
print("Введите фразу (программа работает бесконечно):")
while True:
user_input = input('> ').strip()
# Сохраняем ввод в файл
with open('ввод фраз.txt', 'a', encoding='utf-8') as f_in:
f_in.write(user_input + '\n')
input_words = get_words(user_input)
best_group_index = find_best_group(input_words, group_keywords)
if best_group_index is None:
print("Извините, я не понял. Попробуйте сформулировать иначе.")
else:
response = random.choice(groups[best_group_index])
print(response)
if __name__ == '__main__':
main()
Вы описали простой и достаточно эффективный алгоритм для выбора ответа на основе ключевых слов и группировки фраз. Вот несколько рекомендаций и вариантов реализации, которые могут помочь вам улучшить и структурировать этот процесс:
Как можно реализовать ваш алгоритм на Python:
Структура хранения данных:
Файл фразы1.txt, фразы2.txt и т.д. содержат группы ответов, разделённые строкой с символом =:
привет
здравствуй
что нового
добрый день
можно так думать
=
как дела?
что нового?
это уже есть
=
...
Файл ввод фраз.txt содержит фразы ввода (возможно, для анализа или обучения).
Алгоритм поиска нужной группы:
Для каждой группы ответов заранее собираете множество ключевых слов (например, разбиваете все фразы в группе на слова, убираете стоп-слова и приводите к нормальной форме).
На входе получаете фразу пользователя, разбиваете её на слова, приводите к нормальной форме.
Для каждой группы считаете количество совпадений ключевых слов с фразой ввода.
Выбираете группу с максимальным количеством совпадений.
Случайным образом выбираете одну фразу из этой группы и выводите её.
Пример кода ( упрощённый алгоритм выбора фраз и слов ):
import random
import re
def normalize(text):
# Приведение к нижнему регистру, удаление знаков препинания
text = text.lower()
text = re.sub(r'[^\w\s]', '', text)
return text
def load_groups(filename):
groups = []
with open(filename, encoding='utf-8') as f:
group = []
for line in f:
line = line.strip()
if line == '=':
if group:
groups.append(group)
group = []
elif line:
group.append(line)
if group:
groups.append(group)
return groups
def extract_keywords(phrases):
# Простое выделение слов без стоп-слов и нормализация
stop_words = {'и', 'в', 'на', 'с', 'как', 'что', 'то', 'это', 'а', 'но', 'за', 'от', 'до'}
keywords = set()
for phrase in phrases:
words = normalize(phrase).split()
keywords.update(w for w in words if w not in stop_words)
return keywords
def find_best_group(input_phrase, groups_keywords):
input_words = set(normalize(input_phrase).split())
best_group_index = None
max_matches = 0
for i, keywords in enumerate(groups_keywords):
matches = len(input_words.intersection(keywords))
if matches > max_matches:
max_matches = matches
best_group_index = i
return best_group_index
if __name__ == '__main__':
groups = load_groups('фразы1.txt') + load_groups('фразы2.txt')
groups_keywords = [extract_keywords(group) for group in groups]
while True:
user_input = input('Введите фразу: ')
if user_input.lower() in ('выход', 'exit', 'quit'):
break
group_index = find_best_group(user_input, groups_keywords)
if group_index is not None:
response = random.choice(groups[group_index])
print('Ответ:', response)
else:
print('Извините, я не понял.')
Рекомендации по улучшению:
Лемматизация или стемминг: для русского языка можно использовать библиотеки pymorphy2 или natasha, чтобы приводить слова к нормальной форме
(например, "программы" и "программа" - считать одним словом )
Расширение стоп-слов: стоит добавить больше служебных слов, чтобы фильтровать их из ключевых слов.
Весовые коэффициенты: можно учитывать не только количество совпадений, но и важность слов (например, редкие слова имеют больший вес).
Кэширование: если групп много, можно заранее индексировать ключевые слова для быстрого поиска.
Обработка синонимов: для повышения качества можно использовать словари синонимов.
Если хотите, могу помочь с доработкой кода или с идеями по улучшению алгоритма!
- а что здесь значит упрощенный код ?
Под «упрощённым кодом» я имел в виду пример, который демонстрирует основную идею алгоритма без сложных оптимизаций, обработки ошибок, расширенной лингвистической обработки и дополнительных функций. Такой код:
Не учитывает лемматизацию (приведение слов к базовой форме).
Использует простой разбор и фильтрацию слов (например, базовые стоп-слова).
Не обрабатывает разные формы слов и синонимы.
Не оптимизирован по скорости и памяти.
Не содержит подробной обработки исключений и пользовательского интерфейса.
Цель — показать базовую логику, чтобы вы могли понять принцип и дальше развивать или улучшать код самостоятельно. Если нужно, могу помочь сделать более полный и «продвинутый» вариант с учётом всех этих аспектов.
добавь в алгоритм лемматизацию - то есть анализ набора ключевых слов в группе фразы ответа по их корням и леммам
Конечно -
Для лемматизации русского языка в Python удобно использовать библиотеку pymorphy2 — она позволяет приводить слова к нормальной (лемматизированной) форме. Я обновлю пример кода, добавив лемматизацию при извлечении ключевых слов и обработке пользовательского ввода.
Что нужно сделать:
Установить pymorphy2, если ещё не установлен:
pip install pymorphy2
В коде добавить лемматизацию слов — то есть преобразовать каждое слово к его базовой форме.
Обновлённый пример с лемматизацией:
import random
import re
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
def normalize(text):
# Приведение к нижнему регистру, удаление знаков препинания
text = text.lower()
text = re.sub(r'[^\w\s]', '', text)
return text
def lemmatize_words(words):
lemmas = []
for w in words:
p = morph.parse(w)
if p:
# Берём лемму самого вероятного разбора
lemmas.append(p[0].normal_form)
else:
lemmas.append(w)
return lemmas
def load_groups(filename):
groups = []
with open(filename, encoding='utf-8') as f:
group = []
for line in f:
line = line.strip()
if line == '=':
if group:
groups.append(group)
group = []
elif line:
group.append(line)
if group:
groups.append(group)
return groups
def extract_keywords(phrases):
stop_words = {'и', 'в', 'на', 'с', 'как', 'что', 'то', 'это', 'а', 'но', 'за', 'от', 'до'}
keywords = set()
for phrase in phrases:
words = normalize(phrase).split()
lemmas = lemmatize_words(words)
keywords.update(w for w in lemmas if w not in stop_words)
return keywords
def find_best_group(input_phrase, groups_keywords):
words = normalize(input_phrase).split()
input_lemmas = set(w for w in lemmatize_words(words) if w not in {'и', 'в', 'на', 'с', 'как', 'что', 'то', 'это', 'а', 'но', 'за', 'от', 'до'})
best_group_index = None
max_matches = 0
for i, keywords in enumerate(groups_keywords):
matches = len(input_lemmas.intersection(keywords))
if matches > max_matches:
max_matches = matches
best_group_index = i
return best_group_index
if __name__ == '__main__':
groups = load_groups('фразы1.txt') + load_groups('фразы2.txt')
groups_keywords = [extract_keywords(group) for group in groups]
while True:
user_input = input('Введите фразу: ')
if user_input.lower() in ('выход', 'exit', 'quit'):
break
group_index = find_best_group(user_input, groups_keywords)
if group_index is not None:
response = random.choice(groups[group_index])
print('Ответ:', response)
else:
print('Извините, я не понял.')
Что изменилось в коде:
Добавлена функция lemmatize_words, которая преобразует слова в леммы с помощью pymorphy2.
При извлечении ключевых слов и при обработке пользовательского ввода слова лемматизируются.
Стоп-слова фильтруются уже по леммам.
Если хотите, могу помочь добавить также обработку синонимов или другие улучшения!
также надо придумать - как нам набор большого числа фраз в файле txt разделить на группы
в которых фразы были бы похожи по содержанию
число фраз в группе - 20
Хороший вопрос
Чтобы автоматически разбить большой набор фраз в txt файле на группы примерно по 20 фраз, где фразы внутри группы похожи по смыслу, можно использовать методы кластеризации на основе текстовых признаков.
Общий подход
Предобработка текста:
Очистка от знаков препинания, приведение к нижнему регистру.
Лемматизация (например, с pymorphy2).
Удаление стоп-слов.
Векторизация:
Преобразовать каждую фразу в числовой вектор.
Можно использовать TF-IDF векторизацию с sklearn.feature_extraction.text.TfidfVectorizer.
Или более продвинутые эмбеддинги (например, с помощью моделей sentence-transformers).
Кластеризация:
Применить алгоритм кластеризации, например:
KMeans (если известно число кластеров).
Agglomerative Clustering (иерархическая).
DBSCAN (плотностная).
Цель — получить кластеры, где внутри — похожие фразы.
Размер групп:
Если нужно ровно по 20 фраз, можно задать число кластеров = (общее число фраз) / 20.
Если число фраз не кратно 20, некоторые группы будут чуть больше или меньше.
Пример кода с KMeans и TF-IDF
import re
import pymorphy2
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
morph = pymorphy2.MorphAnalyzer()
def normalize(text):
text = text.lower()
text = re.sub(r'[^\w\s]', '', text)
return text
def lemmatize_text(text):
words = text.split()
lemmas = [morph.parse(w)[0].normal_form for w in words]
return ' '.join(lemmas)
def preprocess(phrase):
text = normalize(phrase)
text = lemmatize_text(text)
return text
def cluster_phrases(phrases, group_size=12):
preprocessed = [preprocess(p) for p in phrases]
# Кол-во кластеров
n_clusters = max(1, len(phrases) // group_size)
vectorizer = TfidfVectorizer(stop_words='russian')
X = vectorizer.fit_transform(preprocessed)
model = KMeans(n_clusters=n_clusters, random_state=42)
labels = model.fit_predict(X)
clusters = [[] for _ in range(n_clusters)]
for phrase, label in zip(phrases, labels):
clusters[label].append(phrase)
return clusters
if __name__ == '__main__':
with open('all_phrases.txt', encoding='utf-8') as f:
phrases = [line.strip() for line in f if line.strip()]
groups = cluster_phrases(phrases, group_size=12)
# Сохраним группы в отдельные файлы
for i, group in enumerate(groups, 1):
with open(f'group_{i}.txt', 'w', encoding='utf-8') as f:
for phrase in group:
f.write(phrase + '\n')
print(f'Группа {i}: {len(group)} фраз')
Несколько советов:
Если фразы очень короткие, TF-IDF может быть не очень информативен — тогда лучше использовать эмбеддинги предложений (sentence-transformers).
Если хотите более равномерные группы, можно после кластеризации дополнительно разбивать или сливать кластеры.
Можно экспериментировать с параметрами кластеризации.
Если интересно, могу помочь с примером на эмбеддингах или более гибкой логикой группировки!
да можно это попробовать
Вот пример, как использовать библиотеку sentence-transformers для получения эмбеддингов предложений и кластеризации фраз по смыслу с помощью KMeans.
Шаги:
Установите необходимые библиотеки:
pip install sentence-transformers scikit-learn pymorphy2
Используйте следующий код:
import re
import pymorphy2
from sentence_transformers import SentenceTransformer
from sklearn.cluster import KMeans
morph = pymorphy2.MorphAnalyzer()
def normalize(text):
text = text.lower()
text = re.sub(r'[^\w\s]', '', text)
return text
def lemmatize_text(text):
words = text.split()
lemmas = [morph.parse(w)[0].normal_form for w in words]
return ' '.join(lemmas)
def preprocess(phrase):
text = normalize(phrase)
text = lemmatize_text(text)
return text
def cluster_phrases(phrases, group_size=12):
preprocessed = [preprocess(p) for p in phrases]
# Загружаем модель для эмбеддингов
model = SentenceTransformer('distiluse-base-multilingual-cased-v1')
embeddings = model.encode(preprocessed, show_progress_bar=True)
n_clusters = max(1, len(phrases) // group_size)
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(embeddings)
clusters = [[] for _ in range(n_clusters)]
for phrase, label in zip(phrases, labels):
clusters[label].append(phrase)
return clusters
if __name__ == '__main__':
with open('all_phrases.txt', encoding='utf-8') as f:
phrases = [line.strip() for line in f if line.strip()]
groups = cluster_phrases(phrases, group_size=12)
for i, group in enumerate(groups, 1):
with open(f'group_{i}.txt', 'w', encoding='utf-8') as f:
for phrase in group:
f.write(phrase + '\n')
print(f'Группа {i}: {len(group)} фраз')
Пояснения к коду:
SentenceTransformer загружает предобученную модель для получения смысловых векторных представлений фраз.
Лемматизация помогает нормализовать текст перед эмбеддингом.
KMeans разбивает фразы на кластеры по смыслу.
Результат сохраняется в отдельные файлы group_1.txt, group_2.txt и т.д.
есть файл фразы.txt
в нём много фраз - примерно 36400
нужно поделить все эти фразы на группы по 10 штук
так чтобы фразы в каждой группе были похожи по содержанию
сохранить группы фраз в файл группы 10.txt
группы разделить строкой с символом =
Для решения задачи группировки фраз по содержанию с последующим сохранением групп по 10 штук в файл, можно использовать подход с векторизацией текста и кластеризацией.
Ниже пример на Python, который:
1. Считывает фразы из файла `фразы.txt`.
2. Преобразует фразы в векторы с помощью модели TF-IDF.
3. Кластеризует фразы с помощью алгоритма KMeans, где количество кластеров = количество фраз / 10.
4. Сохраняет группы по 10 фраз в файл `группы 10.txt`, разделяя группы строкой с символом `=`.
Пример кода
```python
import math
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
# Читаем фразы из файла
with open('фразы.txt', 'r', encoding='utf-8') as f:
phrases = [line.strip() for line in f if line.strip()]
num_phrases = len(phrases)
group_size = 10
num_clusters = math.ceil(num_phrases / group_size)
# Векторизация фраз
vectorizer = TfidfVectorizer(stop_words='russian')
X = vectorizer.fit_transform(phrases)
# Кластеризация
kmeans = KMeans(n_clusters=num_clusters, random_state=42)
labels = kmeans.fit_predict(X)
# Организуем фразы по кластерам
clusters = {}
for label, phrase in zip(labels, phrases):
clusters.setdefault(label, []).append(phrase)
# Записываем группы по 10 фраз в файл
with open('группы 10.txt', 'w', encoding='utf-8') as f_out:
for cluster_id in sorted(clusters.keys()):
group = clusters[cluster_id]
# Если в группе больше 10 фраз, разбиваем на подгруппы по 10
for i in range(0, len(group), group_size):
sub_group = group[i:i+group_size]
f_out.write('\n'.join(sub_group) + '\n')
f_out.write('=\n')
```
Объяснение к коду:
Используется `TfidfVectorizer` с русским стоп-листом для преобразования текста в числовой формат.
Алгоритм `KMeans` разбивает фразы на кластеры, где каждая группа примерно содержит 10 фраз.
Если в кластере больше 10 фраз (что может быть, если количество фраз не кратно 10), то он дополнительно разбивается на подгруппы по 10.
Между группами добавляется строка `=`.
Что нужно для запуска:
Python 3
Установленные библиотеки: `scikit-learn`
Установить можно так:
```bash
pip install scikit-learn
```
исправленный код программы сортировки фраз на группы:
import os
os.environ["LOKY_MAX_CPU_COUNT"] = "6" # замените на число ядер вашего процессора
import math
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
with open('фразы.txt', 'r', encoding='utf-8') as f:
phrases = [line.strip() for line in f if line.strip()]
num_phrases = len(phrases)
group_size = 10
num_clusters = math.ceil(num_phrases / group_size)
vectorizer = TfidfVectorizer(stop_words=None)
X = vectorizer.fit_transform(phrases)
kmeans = KMeans(n_clusters=num_clusters, random_state=42, n_init=10)
labels = kmeans.fit_predict(X)
clusters = {}
for label, phrase in zip(labels, phrases):
clusters.setdefault(label, []).append(phrase)
with open('группы 10.txt', 'w', encoding='utf-8') as f_out:
for cluster_id in sorted(clusters.keys()):
group = clusters[cluster_id]
for i in range(0, len(group), group_size):
sub_group = group[i:i+group_size]
f_out.write('\n'.join(sub_group) + '\n')
f_out.write('=\n')
Свидетельство о публикации №125070905996