Search
Write a publication
Pull to refresh
12
0
Роман @vQFd4

Researcher, IT entrepreneur & software engineer

Send message

да, вот такой, например, он с постресом и с мариябд умеет
https://github.com/nixys/nxs-data-anonymizer

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

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import normalize, MinMaxScaler
from sentence_transformers import SentenceTransformer
import matplotlib.pyplot as plt
import seaborn as sns

# Инициализация модели
model = SentenceTransformer('sergeyzh/LaBSE-ru-turbo')

# Пример данных
surveys = [
    {
        'answers': {
            'q1': 'Ежедневно',
            'q2': 4,
            'q3': 'Прекрасный сервис и дружелюбный персонал.'
        }
    },
    {
        'answers': {
            'q1': 'Часто',
            'q2': 5,
            'q3': 'Отличное обслуживание.'
        }
    },
    {
        'answers': {
            'q1': 'Часто',
            'q2': 4,
            'q3': 'Обслуживание отстойное. Персонал - идиоты'
        }
    },
    {
        'answers': {
            'q1': 'Иногда',
            'q2': 1,
            'q3': 'Плохое обслуживание. Крайне недоволен работой.'
        }
    },
    {
        'answers': {
            'q1': 'Никогда',
            'q2': 3,
            'q3': 'Абсолютно неудовлетворен'
        }
    },
    {
        'answers': {
            'q1': 'Ежедневно',
            'q2': 4,
            'q3': 'Кретины! Худшее, что я когда-либо видел!'
        }
    },
    # ... другие анкеты
]

# Приоритеты вопросов
question_weights = {
    'q1': 0,
    'q2': 0,
    'q3': 5
}

# Кодирование категориальных ответов
categorical_mapping = {
    'Никогда': 0,
    'Иногда': 1,
    'Часто': 2,
    'Ежедневно': 3
}

# Собираем и масштабируем значения q1 и q2
q1_q2_values = []
for survey in surveys:
    q1_value = categorical_mapping.get(survey['answers'].get('q1'), 0)
    q1_weighted = question_weights['q1'] * q1_value
    q2_value = survey['answers'].get('q2', 0)
    q2_weighted = question_weights['q2'] * q2_value
    q1_q2_values.append([q1_weighted, q2_weighted])

q1_q2_values = np.array(q1_q2_values)

# Масштабирование значений q1 и q2
scaler = MinMaxScaler()
q1_q2_scaled = scaler.fit_transform(q1_q2_values)

# Предварительная обработка текстовых ответов с использованием эмбеддингов
text_answers = [survey['answers']['q3'] for survey in surveys]

# Вычисление эмбеддингов для текстовых ответов
embeddings = model.encode(text_answers)

# Применение веса к эмбеддингам
embeddings_weighted = embeddings * question_weights['q3']

# Формирование векторов анкет
survey_vectors = []
for idx in range(len(surveys)):
    vector = q1_q2_scaled[idx]
    embedding_vector = embeddings_weighted[idx]
    full_vector = np.concatenate([vector, embedding_vector])
    survey_vectors.append(full_vector)

# Нормализация итоговых векторов
survey_vectors = np.array(survey_vectors)
survey_vectors_normalized = normalize(survey_vectors)

# Расчет косинусного сходства между всеми анкетами
similarities = cosine_similarity(survey_vectors_normalized)

# Вывод матрицы сходства
print("Матрица сходства:")
print(similarities)

# Построение тепловой карты
plt.figure(figsize=(8, 6))
sns.heatmap(similarities, annot=True, cmap='Blues',
            xticklabels=[f'Анкета {i}' for i in range(len(surveys))],
            yticklabels=[f'Анкета {i}' for i in range(len(surveys))])
plt.title('Матрица косинусного сходства между анкетами')
plt.show()

В принципе можно так сделать, особенно, если анкеты состоят только из свободных ответов (то есть без выбора вариантов), ну и опять же тут надо смотреть на количество ответов в анкете и характер вопросов. Иногда в такой ситуации лучше применить не суммирование, а конкатенацию векторных представлений отдельных вопросов.

ну кроме стандартного стеммера для русского языка доступен как минимум сноубол

"russian_snowball": {
  "type":     "snowball",
  "language": "Russian"
}

ну естественно стеммер с переопределением. Как мне кажется по сравнению с предыдущими версиями эластика ничего не изменилось. Ну и опять же можно плагин установить, который улучшит морфологический анализ для русского языка

https://github.com/nickyat/elasticsearch-analysis-morphology?tab=readme-ov-file

возможно его потребуется пересобрать под более свежую версию эластика (там в зависимостях стоит Elasticsearch 8.9.1) 

И в Dockerfile описано как собранный плагин подключить к Elasticsearch


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

https://github.com/nickyat/elasticsearch-analysis-morphology?tab=readme-ov-file

возможно его потребуется пересобрать под более свежую версию эластика (там в зависимостях стоит Elasticsearch 8.9.1)

И в Dockerfile описано как собранный плагин подключить к Elasticsearch

Вроде как ничего с поддержкой русского языка не изменилось
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lang-analyzer.html

В принципе сложно что-то добавить к статье Егора Рогова, учитывая, что он непосредственно общается с людьми, которые этот индекс спроектировали и знает, как все утроено изнутри :)
https://habr.com/ru/companies/postgrespro/articles/452116/,

Но может какие-то отдельные мои комментарии вам помогут.

Например, в наших задачах RUM предпочтительнее, поскольку нам важно делать ранжирование результатов поисковой выдачи по релевантности при полнотекстовом поиске, используя GIN вы в таких запросах преимуществ никаких не получаете, а вот с RUM все значительно шустрее происходит.

Скажем тут

CREATE TABLE articles (
    id serial PRIMARY KEY,
    content text,
    created_at timestamp
);

CREATE INDEX articles_content_rum_idx ON articles USING rum (to_tsvector('english', content) rum_tsvector_ops);

-- Получаем топ-5 статей по ключевым словам "AI" и "ML"
SELECT id, content
FROM articles
WHERE to_tsvector('english', content) @@ to_tsquery('AI & ML')
ORDER BY content <=> to_tsquery('AI & ML')
LIMIT 5;

RUM индекс выполняет index_scan, чтобы сразу отсортировать и вернуть 5 самых релевантных записей. Для GIN индексам потребовался бы полный скан и сортировка после поиска.

Еще комментируя статью Егора, наверное, отмечу, что у него упоминается возможность использовать RUM для исключающих ограничений

> Note that, unlike GIN, RUM supports index scan — otherwise, it would not have been possible to return exactly the required number of results in queries with «limit» clause. There is no need for the counterpart of «gin_fuzzy_search_limit» parameter accordingly. And as a consequence, the index can be used to support exclusion constraints.
Но я кроме как простого полного сравнения tsvector примера придумать не смог (( То есть, например как GIST использовать RUM не получиться, что исключать какие-то куски текста, например

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT,
    tsv tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED,
    EXCLUDE USING rum (tsv WITH =)
);


В данном примере мы создаем исключающее ограничение на поле tsv с использованием индекса RUM. Оператор WITH = указывает, что мы хотим исключить случаи, когда значение tsv совпадает у двух разных записей. Индекс RUM здесь необходим, поскольку он поддерживает операцию равенства на типе tsvector и может эффективно выполнять такое сравнение благодаря возможностям индексного сканирования.


на самом деле сравнивать postgresql со специализированным поисковым движком бессмысленно, понятно, что в последнем и скорость и функциональность в среднем будет больше/лучше. Но! Если вы своем приложении используете не самые сложные процессы полнотекстового поиска, то постгрес будет норм выбором, потому что
1/ не потребуется городить доп инфру
2/ не потребуется городить CDC процесс в поисковой движок
3/ не потребуется решать проблемы с нарушением консистентности по сути двух отдельных баз данных (постгреса и, например, эластика)
4/ все будет в одном месте с понятным единообразным апи и простым процессом интеграции в ваше приложение.

Естественно, окончательное решение нужно будет принимать оглядываясь на циферки: нормально ли все фт и нфт закрыты, но для старта постгрес будет очень даже нормальным выбором, как показывает практика внедрения в проектах вокруг (например, Discourse и gitlab).

я прекрасно понимаю, что тяжело начать делать что-то новое, особенно, когда не очень хорошо разбираешься в принципе в компьютерных технологиях, но сейчас АИ модели предлагают достаточно простой и понятный пользовательский интерфейс. Помню в 2010-х приходилось написать кучу строк кода, чтобы получить гораздо меньшее того, что сейчас можно описать модели на обычном человеческом языке. Просто надо постепенно начинать и учиться этим пользоваться, так же как текстовым редактором или таблицами в эксель. Для педагога это реально полезное подспорье в плане подготовки урока: это и гораздо более приятный поиск и саммаризация информации, и возможность быстро смоделировать решение задачи или просто рассмотреть какой-то социальный феномен с разных сторон. Это реально помогает уже на уроке сделать гораздо более интересный рассказ темы, чем просто пересказ учебника.

пичем подготовка будет занимать в разы меньше времени, чем при блуждании в обычном поисковике по интернету или попытках найти что-то релевантное к теме урока в книгах

я не понял, в чем пойнт? Учителя не хотят пользоваться доступным инструментарием, чтобы облегчить себе жизнь? Или в том, что они ничего не хотят делать из-за низких зарплат? Или "в отрасли мало платят, поэтому уже ничего не поможет"?

ты вообще о чем? давай, ты сперва книжечку Любжина почитаешь, ок? или для начала просто прочтешь статью. Никто не предлагает заменять педагога ИИ, где ты это нашел в статье?

Современная система образования в РФ мягко говоря не в лучшем состоянии. Педагог индивидуальный подход предложить ученику в современной школе (в большей перцентиле) не может. В такой ситуации хотя бы технические решения могут попытаться сгладить ситуацию, предлагая интерактив для учеников, а не просто долбежку в учебник.

в данном случае учитель сможет более творчески подходить к созданию заданий, это могут быть уже не просто однотипные примеры, требующие наработки механистических навыков, а задания, требующие творческого подхода. Да, возможно ученики будут использовать ИИ, чтобы его решить, но для этого потребуется уже задавать ИИ вопросы из изучаемого домена, а для этого с доменом придется познакомиться, это тоже определенные образовательные усилия и определенная исследовательская работа, что, очевидно, ценно в контексте общего образовательного процесса

ну как бы ни list, ни Redis Streams не являются альтернативами для Redis Sentinel или Redis Cluster. List или, например, ZSet, или Redis Streams решают проблему персистентности сообщений и в каком-то виде обеспечивают гарантии доставки. Их использование совместно с Redis Sentinel или Redis Cluster это тоже отдельная история, которую по-хорошему лучше отдельно описать, там есть свои нюансы касающиеся ожиданий гарантий доставки

В целом да, но иногда эти гарантии и не требуются из-за природы бизнес-процесса. Например, rabbit тоже не все так просто, особенно, если вы решит сделать HA кластер. Даже с quorum queues он вполне успешно может терять сообщения

На самом деле вопросы производительности я не обсуждаю, тут все про HA. Производительность если и упоминаю, то косвенно исключительно из общих соображений, например в конфигурации Sentinel мастер управляет всеми каналами, что сказывается на производительности, и в этом случает Redis Cluster предпочтительнее.

А так да, постараюсь сделать load test в равнении с rabbit/kafka

Если коротко отвечать, то никак, я об этом упомянул в статье в разделе ограничений. Но в целом в зависимости от вариантов использования Pub/Sub
1/ это может в принципе не требоваться из-за особенностей реализуемого бизнес-процесса
2/ можно воспользоваться List + AOF
3/ можно попробовать реализовать OutBox/inBox + подтверждение доставки на стороне приложения

А в чем прикол, к примеру, вот этого курса https://stepik.org/course/Applied-Computer-Science-Docker-2496/
Где программа, где контент? Они скрыты? Если так, как получить к ним доступ? Или это просто набор тупых вопросов по докеру?

Information

Rating
Does not participate
Location
Тверь, Тверская обл., Россия
Works in
Registered
Activity

Specialization

Backend Developer, Software Architect
Lead
From 700,000 ₽
Designing application architecture
Creating project architecture
High-loaded systems
Database
PostgreSQL
Java
Java Spring Framework
Docker
Kubernetes
Apache Kafka