Новости об искусственном интеллекте
Модели ИИ
Сервисы
Исследования
The Time AI

Новости искусственного интеллекта

Инструкции/ Разработка

Как подготовить копию CSV для ИИ: оставить нужные столбцы и заменить имена кодами на Mac

Создаём отдельный CSV только с row_id и topic, не перезаписываем исходник и вручную проверяем свободный текст перед передачей ИИ.

ИнструкцияПроверка ·
Система
macOS 27.0.1
Программы
Python 3.12.14
Подробности проверки
  • macOS 27.0.1 (build 26A434), arm64
  • Python 3.12.14
  • только стандартная библиотека.
  • На синтетическом fixture проверены точный output, неизменность исходника, разные row_id для одинаковых имён, отказы при существующем output, одинаковых путях, неверных заголовках и короткой строке.
  • Свободный topic переносится дословно и требует ручного просмотра.
Ноутбук и две папки с документами на рабочем столе как образ отдельной минимизированной CSV-копии для передачи ИИ
Фото: TheTimeAI

Передавать ИИ всю выгрузку только ради одного столбца рискованно и обычно не нужно. Для задачи вроде группировки тем достаточно сделать отдельную копию: убрать name, email и city, а вместо исходной личности дать каждой строке технический row_id. Исходный CSV при этом остаётся нетронутым.

Ниже — воспроизводимый способ для Mac с уже установленным Python 3.9 или новее. Скрипт использует только стандартную библиотеку Python, принимает учебный CSV с заголовками name,email,city,topic и создаёт новый файл только с row_id,topic. Режим записи x не позволяет случайно заменить существующий результат.

Что этот способ меняет — и чего не обещает

  • name, email и city не попадают в новую копию.
  • row_id создаётся заново по порядку строк: R0001, R0002 и далее.
  • Одинаковые имена в разных строках получают разные row_id. Скрипт не решает, относятся ли строки к одному человеку.
  • Таблица соответствий имён и кодов не создаётся и не сохраняется.
  • topic переносится дословно, поэтому его нужно прочитать вручную перед отправкой.
  • Результат не следует называть автоматически анонимным: свободный текст может содержать имя, телефон, адрес, номер заказа или другую чувствительную деталь.
Белый список полей: в результат попадает только явно выбранное
Поле исходникаДействиеПоле результата
nameисключить—
emailисключить—
cityисключить—
порядок строкисоздать локальный кодrow_id
topicоставить после ручного просмотраtopic
Схема белого списка: name, email и city исключаются, а новая CSV-копия содержит только построчный row_id и topic после ручного просмотра
Фото: TheTimeAI
Открыть крупнее

Что потребуется

  • Mac и приложение «Терминал».
  • Уже доступная команда python3 версии 3.9 или новее. Ничего устанавливать ради инструкции не нужно.
  • Отдельная копия CSV, а не единственный оригинал.
  • CSV в UTF-8 с запятой как разделителем, двойными кавычками для сложных значений и точными заголовками name,email,city,topic в этом порядке.

Шаг 1. Проверьте Python и подготовьте папку

В Терминале проверьте путь и версию Python. Если command -v ничего не выводит, версия ниже 3.9 или macOS предлагает установить дополнительные инструменты, остановитесь: этот гайд не требует и не описывает установку. Затем создайте отдельную учебную папку и перейдите в неё.

bash
command -v python3
python3 --version
mkdir csv-minimize-check
cd csv-minimize-check

Для рабочего файла используйте другое имя папки и сначала скопируйте CSV туда через Finder. Не открывайте скрипту оригинал, если он является единственной копией.

Шаг 2. Создайте учебный CSV

Сохраните следующий текст как sample.csv в UTF-8. Здесь имя «Анна Соколова» повторяется намеренно, но строки имеют разные email, city и topic. Скрипт не будет считать имя уникальным ключом и не станет связывать эти строки.

csv
name,email,city,topic
Анна Соколова,anna@example.test,Казань,Нужен план публикаций на неделю
Иван Петров,ivan@example.test,Пермь,"Сводная таблица: продажи, возвраты"
Анна Соколова,anna2@example.test,Омск,Черновик FAQ по доставке

Шаг 3. Сохраните скрипт с белым списком

Сохраните код ниже как prepare_csv_copy.py в той же папке. EXPECTED_FIELDS фиксирует контракт входа, а OUTPUT_FIELDS — единственные два столбца результата. Скрипт сначала полностью читает и проверяет CSV, затем открывает новый выходной файл в режиме x. Если такой файл уже есть, скрипт сообщает об ошибке, а существующие байты не заменяются.

python
#!/usr/bin/env python3
"""Create a minimized CSV copy with row-local identifiers."""

from __future__ import annotations

import csv
import io
import sys
from pathlib import Path


EXPECTED_FIELDS = ["name", "email", "city", "topic"]
OUTPUT_FIELDS = ["row_id", "topic"]


class CopyError(Exception):
    pass


def create_copy(source: Path, destination: Path) -> int:
    source = source.expanduser()
    destination = destination.expanduser()

    try:
        source_path = source.resolve(strict=True)
    except OSError as error:
        raise CopyError(f"не удалось открыть исходный файл: {error}") from error
    destination_path = destination.resolve(strict=False)

    if source_path == destination_path:
        raise CopyError("исходный и выходной пути должны различаться")
    if not source_path.is_file():
        raise CopyError("исходный путь должен указывать на обычный файл")
    if not destination_path.parent.is_dir():
        raise CopyError(f"папка результата не существует: {destination_path.parent}")

    minimized: list[dict[str, str]] = []
    try:
        with source_path.open("r", encoding="utf-8-sig", newline="") as stream:
            reader = csv.DictReader(
                stream,
                delimiter=",",
                quotechar='"',
                doublequote=True,
                skipinitialspace=False,
                strict=True,
            )
            if reader.fieldnames != EXPECTED_FIELDS:
                raise CopyError(
                    "ожидались заголовки строго в порядке: "
                    + ",".join(EXPECTED_FIELDS)
                )

            for row_number, row in enumerate(reader, 2):
                if None in row or any(value is None for value in row.values()):
                    raise CopyError(
                        f"логическая строка {row_number}: число полей не совпадает с заголовками"
                    )
                minimized.append(
                    {
                        "row_id": f"R{len(minimized) + 1:04d}",
                        "topic": row["topic"],
                    }
                )
    except UnicodeError as error:
        raise CopyError(f"CSV не декодируется как UTF-8: {error}") from error
    except csv.Error as error:
        raise CopyError(f"ошибка CSV: {error}") from error
    except OSError as error:
        raise CopyError(f"не удалось прочитать исходный CSV: {error}") from error

    buffer = io.StringIO(newline="")
    writer = csv.DictWriter(
        buffer,
        fieldnames=OUTPUT_FIELDS,
        delimiter=",",
        quotechar='"',
        doublequote=True,
        lineterminator="\n",
        extrasaction="raise",
    )
    writer.writeheader()
    writer.writerows(minimized)

    try:
        with destination_path.open("x", encoding="utf-8", newline="") as output:
            output.write(buffer.getvalue())
    except FileExistsError as error:
        raise CopyError(
            f"выходной файл уже существует и не будет заменён: {destination_path}"
        ) from error
    except OSError as error:
        raise CopyError(f"не удалось создать выходной CSV: {error}") from error

    return len(minimized)


def main(arguments: list[str]) -> int:
    if len(arguments) != 3:
        print(
            "Использование: python3 prepare_csv_copy.py ИСХОДНИК.csv КОПИЯ.csv",
            file=sys.stderr,
        )
        return 2
    try:
        count = create_copy(Path(arguments[1]), Path(arguments[2]))
    except CopyError as error:
        print(f"ОШИБКА: {error}", file=sys.stderr)
        return 1
    print(f"Готово: строк {count}; создан новый файл: {arguments[2]}")
    print("Перед передачей вручную просмотрите весь столбец topic.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))

Параметр newline="" передаёт обработку переводов строк модулю csv. DictReader связывает значения с заголовками, но код дополнительно требует точный набор полей и останавливается при лишнем или пропущенном значении. Кодировка входа utf-8-sig принимает обычный UTF-8 и вариант с BOM; выход всегда создаётся в UTF-8.

Шаг 4. Создайте и сравните новую копию

  1. Запустите скрипт с отдельными путями входа и выхода.
  2. Убедитесь, что он сообщает о трёх строках и напоминает просмотреть topic.
  3. Выведите результат и сравните его с ожидаемыми строками ниже.
  4. Проверьте, что sample.csv по-прежнему содержит четыре исходных столбца.
bash
python3 prepare_csv_copy.py sample.csv share-copy.csv
cat share-copy.csv
cat sample.csv
csv
row_id,topic
R0001,Нужен план публикаций на неделю
R0002,"Сводная таблица: продажи, возвраты"
R0003,Черновик FAQ по доставке

У двух строк с именем «Анна Соколова» получились R0001 и R0003, потому что код относится к строке, а не к личности. Если изменить порядок строк или обработать другой файл, row_id изменится. Не используйте его для объединения наборов данных или восстановления личности.

Таблица точного результата учебного прогона с тремя row_id и перечнем проверенных отказов: существующий выход, одинаковый путь и плохие строки
Фото: TheTimeAI
Открыть крупнее

Шаг 5. Обязательно прочитайте topic вручную

Удаление столбцов не очищает свободный текст. Откройте share-copy.csv в текстовом редакторе или табличной программе и последовательно прочитайте каждую ячейку topic. Ищите реальные имена, email, телефоны, адреса, номера документов и заказов, внутренние ссылки, секреты, точные даты и редкие сочетания деталей, по которым можно узнать человека.

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

Шаг 6. Проверьте защитные отказы

Повторите команду с тем же share-copy.csv. Скрипт должен завершиться с ошибкой «выходной файл уже существует» и не менять файл. Затем попробуйте передать sample.csv одновременно как вход и выход: скрипт должен отказать до записи. Эти проверки важны перед работой с настоящей копией.

bash
python3 prepare_csv_copy.py sample.csv share-copy.csv
echo $?
python3 prepare_csv_copy.py sample.csv sample.csv
echo $?

В обоих случаях ожидается код 1. Если нужно создать результат заново, сначала проверьте содержимое и выберите другое имя, например share-copy-2.csv. Такой порядок сохраняет предыдущую версию для сравнения и не требует удалять её вслепую.

Шаг 7. Примените способ к рабочей копии

  1. Сделайте отдельную копию исходного файла через Finder.
  2. Проверьте, что заголовки и CSV-диалект совпадают с принятым контрактом. Другие названия столбцов изменяйте только осознанно в EXPECTED_FIELDS.
  3. Оставьте в OUTPUT_FIELDS и словаре внутри minimized.append только сведения, которые действительно нужны выбранной задаче.
  4. Запустите скрипт с новым именем результата.
  5. Вручную прочитайте весь topic и только после этого передавайте созданную копию ИИ.

Ограничения

  • Это минимизация полей для конкретной задачи, а не универсальная анонимизация и не юридическая оценка допустимости передачи.
  • Скрипт не ищет персональные данные, секреты и косвенные идентификаторы внутри topic.
  • row_id стабилен только внутри одной созданной копии и не обозначает уникального человека.
  • Скрипт рассчитан на конкретный CSV-диалект и хранит выбранные строки в памяти до записи. Для очень больших файлов нужен другой проверенный процесс.
  • Имя самого файла и название папки тоже могут раскрывать контекст; перед отправкой проверьте их отдельно.
  • Даже минимальный CSV может быть чувствительным. Передавайте его только тому инструменту и в тот контекст, которые разрешены правилами вашей организации.

Как отменить изменения

Исходный CSV скрипт не меняет. Чтобы отменить результат, сначала выполните pwd и убедитесь, что находитесь в созданной учебной папке. Затем переместите в Корзину только созданные вами share-copy.csv и prepare_csv_copy.py. Не используйте рекурсивное удаление, домашнюю папку, переменную пути или широкий шаблон. Если результат нужно сохранить для аудита, оставьте его локально и не отправляйте.

Когда копия готова

Считайте технический этап завершённым, когда результат содержит только row_id и topic, точный учебный пример воспроизводится, существующий файл не заменяется, вход и выход различаются, а весь свободный текст просмотрен человеком. Это уменьшает объём передаваемых данных, но окончательное решение об отправке зависит от содержания и правил вашей работы.

Поделиться

ВКонтактеTelegramWhatsApp

К другим инструкциям