CoderCastrov logo
CoderCastrov
Gpt 3 - Gpt 3

Open Source AI Parser for HTML Elements

Open Source AI Parser for HTML Elements
просмотров
15 мин чтение
#Gpt 3 - Gpt 3

Daath AI Parser

Daath AI Parser - это открытое приложение, которое использует OpenAI для парсинга видимого текста элементов HTML. Оно построено на основе FastAPI. Готово к настройке в качестве сервера и может быть вызвано из любого языка. В настоящее время размещено на ai.kagermanov.com. Интерактивный пример на Replit Ссылка на репозиторий



Базовое использование

  • Скопируйте внешний HTML элемента, который вы хотите разобрать

  • Используйте путь для предустановленного парсера

Вы можете найти поддерживаемые предустановленные парсеры и их поля на странице Daath Preset Parsers

  • Используйте ваш ключ API OpenAI

Сначала вам нужно зарегистрировать бесплатную учетную запись. Вы можете найти ваш ключ API здесь.

  • Отправьте POST-запрос к конечной точке
import requests
uri = "https://ai.kagermanov.com/classify"

headers = {"Content-Type": "application/json"}
data = {
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Coffee shop</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Iconic Seattle-based coffeehouse chain</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ],
  "openai_key": "<OPENAI KEY>"
}
r = requests.post(url=uri, headers=headers, json=data)
print(r.json()["results"])
  • Результат:
{
    "results": [
      {
          "Адрес": "Nicosia",
          "Описание или отзыв": "Iconic Seattle-based coffeehouse chain",
          "Стоимость": "€€",
          "Количество отзывов": "418",
          "Рейтинг": "4.0",
          "Название": "Y Coffee",
          "Тип": "Кофейня"
      }
    ]
}

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

Парсинг нескольких элементов

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

import requests

uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "path": "google.google_local_results",
  "targets": [
    "X Coffee 4.1(23) · €€ · Кофейня Никосия Цепь кофеен для кофе и закусок",
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Оценка 4.0 из 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Умеренно дорого\" role=\"img\">€€</span> · Кофейня</div><div>Никосия</div><div class=\"pJ3Ci\"><span>Иконическая кофейня из Сиэтла</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>",
    # Некоторые другие элементы между ними ...
    "Z Coffee 4.6(13) · € · Кафе Никосия На вынос"
  ],
  "openai_key": "<OPENAI KEY>"
}
r = requests.post(url=uri, headers=headers, json=data)
print(r.json()["results"])
  • Несколько результатов
{
    "results": [
      {
          "Адрес": "Никосия",
          "Описание или отзыв": "Цепь кофеен для кофе и закусок",
          "Дороговизна": "€€",
          "Количество отзывов": "23",
          "Рейтинг": "4.1",
          "Название": "X Coffee",
          "Тип": "Кофейня"
      },
      {
          "Адрес": "Никосия",
          "Описание или отзыв": "Иконическая кофейня из Сиэтла",
          "Дороговизна": "€€",
          "Количество отзывов": "418",
          "Рейтинг": "4.0",
          "Название": "Y Coffee",
          "Тип": "Кофейня"
      },
      # Некоторые другие результаты между ними ...
      {
          "Адрес": "Никосия",
          "Описание или отзыв": "На вынос",
          "Дороговизна": "€",
          "Количество отзывов": "13",
          "Рейтинг": "4.6",
          "Название": "Z Coffee",
          "Тип": "Кафе"
      }
    ]
}

Проектирование пользовательских парсеров

Помимо предустановленных парсеров, в Daath AI Parser также предусмотрена возможность создания собственных парсеров. Для этого нужно указать промпт, примеры и детали модели OpenAI в ключе classifier. Вот разбивка такого пользовательского парсера:

{
  "classifier": {
    "main_prompt": "Строка, команда модели для классификации каждого элемента, который вам нужен. `NUMBER_OF_LABELS` используется для автоматического определения размера всех уникальных меток в каждом примере с помощью `#$``max_tokens`�.",
    "data": "Словарь, детали модели, которую вы хотите использовать. Тот же поле данных, которое вы бы использовали в обычном вызове API OpenAI, за исключением `parse_only`",
    "model_specific_token_size": "Целое число, максимальное количество токенов, разрешенных для модели. Это используется для определения места разделения множественных вызовов промпта в заданной команде. Разумно установить его чуть ниже максимального количества токенов, разрешенных моделью. Например, если модель разрешает 4000 токенов, вы можете установить его равным 3800. Это связано с тем, что количество токенов, создаваемых `product_options`, определяется стандартами GPT-2, и оно может быть выше фактического количества токенов модели.",
    "openai_endpoint": "Строка, конечная точка, из которой вы хотите вызвать модель. Например: `https://api.openai.com/v1/completions`",
    "explicitly_excluded_strings": "Список, список строк, которые вы хотите исключить из результатов. Например, если вы хотите исключить переносы строк, вы можете добавить \"\n\" в список.",
    "examples_for_prompt": [
      {
        "text": "Строка, которую вы хотите классифицировать.",
        "classifications": {
          "метка_1": "Строка, значение метки_1 для данного текста.",
          "метка_2": "Строка, значение метки_2 для данного текста.",
          # Дополнительные метки
        }
      },
      # Дополнительные примеры
    ]
  }
}

Вот пример скрипта с пользовательским парсером:

{
  "classifier": {
    "main_prompt": "Строка, команда модели для классификации каждого элемента, который вам нужен. `NUMBER_OF_LABELS` используется для автоматического определения размера всех уникальных меток в каждом примере с помощью `Daath AI Parser`.",
    "data": "Словарь, детали модели, которую вы хотите использовать. Тот же поле данных, которое вы бы использовали в обычном вызове API OpenAI, за исключением `max_tokens`",
    "model_specific_token_size": "Целое число, максимальное количество токенов, разрешенных для модели. Это используется для определения места разделения множественных вызовов промпта в заданной команде. Разумно установить его чуть ниже максимального количества токенов, разрешенных моделью. Например, если модель разрешает 4000 токенов, вы можете установить его равным 3800. Это связано с тем, что количество токенов, создаваемых `Daath AI Parser`, определяется стандартами GPT-2, и оно может быть выше фактического количества токенов модели.",
    "openai_endpoint": "Строка, конечная точка, из которой вы хотите вызвать модель. Например: `https://api.openai.com/v1/completions`",
    "explicitly_excluded_strings": "Список, список строк, которые вы хотите исключить из результатов. Например, если вы хотите исключить переносы строк, вы можете добавить \"\n\" в список.",
    "examples_for_prompt": [
      {
        "text": "Строка, которую вы хотите классифицировать.",
        "classifications": {
          "метка_1": "Строка, значение метки_1 для данного текста.",
          "метка_2": "Строка, значение метки_2 для данного текста.",
          # Дополнительные метки
        }
      },
      # Дополнительные примеры
    ]
  }
}
{
    "results": [
      {
          "Address": "Nicosia",
          "Description Or Review": "Iconic Seattle-based coffeehouse chain",
          "Expensiveness": "€€",
          "Number Of Reviews": "418",
          "Rating": "4.0",
          "Title": "Y Coffee",
          "Type": "Coffee shop"
      }
    ]
}
{
  # ...
  "examples_for_prompt": [
    {
      "text": "Stumptown Coffee Roasters, Medium Roast Organic Whole Bean Coffee Gifts - Holler Mountain 12 Ounce Bag with Flavor Notes of Citrus Zest, Caramel and Hazelnut 12 Ounce 4.3 4.3 out of 5 stars (8,311) Options: 2 sizes, 6 flavors 2 sizes, 6 flavors Climate Pledge Friendly uses sustainability certifications to highlight products that support our commitment to help preserve the natural world. Time is fleeting. Learn more Product Certification (1) USDA Organic",
      "classifications": {
        "line": "3",
        "title": "Stumptown Coffee Roasters, Medium Roast Organic Whole Bean Coffee Gifts - Holler Mountain 12 Ounce Bag with Flavor Notes of Citrus Zest, Caramel and Hazelnut",
        "scale": "12 Ounce",
        "rating": "4.3",
        "reviews": "8,311",
        "product_options": "2 sizes#$6 flavors#$",
        "tags": "Climate Pledge Friendly#$USDA Organic#$"
      }
    },
    #...
  ]
  #...
}
````prompts_only````
{
  "results": [
    {"error": "Ошибка с локальной машины"}
  ]
}
{
  "results": [
    {"error": "Максимальный размер токена достигнут для этого промпта. Он будет пропущен."}
  ]
}

Результат пользовательского парсера будет таким же, как и предустановленного:

{
  "results": [
    {
      "Line": "X",
      "Product Options": [
        "X",
        "X"
      ],
      "Rating": "X",
      "Reviews": "X",
      "Scale": "X",
      "Tags": [
        "X",
        "X"
      ],
      "Title": "X"
    }
  ]
}

allowed_concurrency``Daath AI Parser``allowed_concurrency

Вы также можете получить массивы из своих промптов, разделяя результаты специальным двойным символом ����. Вот пример использования этой функции в ключе openai_key�����, предоставленном в приведенном ниже примере:

{
  "prompts": [
    "Строка, отдельные промпты, которые вам нужно вызвать на конечной точке OpenAI. Разделены на несколько вызовов, если вызовы превышают максимальное количество токенов, разрешенное конечной точкой.",
  ],
  "prompt_objects": {
    "invalid_lines_indexes": "Список, массив элементов, текст которых уже превышает разрешенный порог. Эти результаты будут пропущены и будут возвращены с ошибкой в конечном ответе.",
    "desired_lines": "Список, массив текстового содержимого элементов HTML.",
    "labels": "Список, массив меток, которые пользователь хочет классифицировать."
  }
}
{
  "results": [
    {
        "Address": "Nicosia",
        "Description Or Review": "Иконическая кофейня из Сиэтла",
        "Expensiveness": "€€",
        "Number Of Reviews": "418",
        "Rating": "4.0",
        "Title": "Y Coffee",
        "Type": "Кофейня"
    }
  ]
}

credentials.py``mock_name``pytest

Создание пользовательского парсера с таким примером приведет к следующей структуре:

{
  "results": [
    {
      "message": "Вы превысили текущую квоту, пожалуйста, проверьте свой план и данные о платеже.",
      "type": "insufficient_quota",
      "param": null,
      "code": null
    }
  ]
}

Выполнение серверных вызовов без раскрытия API-ключа

  • Только вызовы промптов

Вы можете получить только промпты, которые вам нужно вызвать на конечной точке OpenAI с помощью ключа ��������������.

import requests

uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "prompts_only": True,
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Кофейня</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Иконическая кофейня из Сиэтла</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ]
}
r = requests.post(url=uri, headers=headers, json=data)
print(r.json())

Вот разбивка ответа такого вызова:

{
  "results": [
    {
      "message": "Неверный ключ API: <Ваш Op*****Key>. Вы можете найти свой ключ API по адресу https://beta.openai.com.",
      "type": "invalid_request_error",
      "param": null,
      "code": "invalid_api_key"
    }
  ]
}

Вот пример ответа:

import requests

uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Coffee shop</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Iconic Seattle-based coffeehouse chain</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ],
  "openai_key": "<OPENAI KEY>",
  "classifier": {
    "main_prompt": "Таблица с NUMBER_OF_LABELS ячейками в каждой строке, содержащая сводку различных частей текста на каждой строке, даже если они не уникальны:\n\n",
    "data": {
      "model": "text-davinci-003",
      "temperature": 0.001,
      "top_p": 0.9,
      "best_of": 2,
      "frequency_penalty": 0,
      "presence_penalty": 0
    },
    "model_specific_token_size": 3800,
    "openai_endpoint": "https://api.openai.com/v1/completions",
    "explicitly_excluded_strings": [
      "Order",
      "Website",
      "Directions",
      "\n"
    ],
    "examples_for_prompt": [
      {
        "text": "Houndstooth Coffee 4.6(824) · $$ · Coffee shop 401 Congress Ave. #100c · In Frost Bank Tower Closed ⋅ Opens 7AM Cozy hangout for carefully sourced brews",
        "classifications": {
          "line": "1",
          "title": "Houndstooth Coffee",
          "rating": "4.1",
          "number_of_reviews": "824",
          "expensiveness": "$$",
          "type": "Coffee Shop",
          "address": "401 Congress Ave. #100c · In Frost Bank Tower",
          "open_hours": "Opens 7AM",
          "description_or_review": "Cozy hangout for carefully sourced brews"
        }
      },
      # Дополнительные примеры ...
    ]
  }
}
r = requests.post(url=uri, headers=headers, json=data)
print(r.json()["results"])
  • Вызовы на стороне сервера к OpenAI

Вы можете делать вызовы к OpenAI с вашего сервера. Настройка параметров модели должна быть такой же, как у используемого вами предустановленного парсера или предоставленного вами пользовательского парсера. Параметр ������������ должен быть вычислен на стороне сервера для каждого вызова. Вот пример выполнения вызова на стороне сервера:

import os
import openai
import requests

uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "prompts_only": True,
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Кофейня</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Иконическая кофейня из Сиэтла</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ]
}
response_from_daath_ai_parser = requests.post(url=uri, headers=headers, json=data)
openai.api_key = os.getenv("OPENAI_API_KEY")
prompts = response_from_daath_ai_parser["prompts"]
responses = []
for prompt in prompts:
  response = openai.Completion.create(
    model="text-davinci-003",
    prompt=prompt,
    temperature=0.001,
    max_tokens=400,
    top_p=0.9,
    best_of=2,
    frequency_penalty=0,
    presence_penalty=0
  )
  responses.append(response)
print(responses)
  • Только вызов парсера

Вы можете собрать ответы на стороне сервера, а затем сделать вызов с использованием ������������, чтобы получить разобранные результаты. Вот пример вызова только для разбора:

import os
import openai
import requests

# Вызовы промптов
uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "prompts_only": True,
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Кофейня</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Иконическая кофейня из Сиэтла</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ]
}
response_from_daath_ai_parser = requests.post(url=uri, headers=headers, json=data)
openai.api_key = os.getenv("OPENAI_API_KEY")
prompts = response_from_daath_ai_parser["prompts"]
responses = []
# Вызов на стороне сервера к OpenAI
for prompt in prompts:
  response = openai.Completion.create(
    model="text-davinci-003",
    prompt=prompt,
    temperature=0.001,
    max_tokens=400,
    top_p=0.9,
    best_of=2,
    frequency_penalty=0,
    presence_penalty=0
  )
  responses.append(response)
# Вызов только для разбора
data = {
  "path": "google.google_local_results",
  "parse_only": {
    "responses": responses
    "prompt_objects": response_from_daath_ai_parser["prompt_objects"]
  }
}
response_from_daath_ai_parser = requests.post(url=uri, headers=headers, json=data)
print(response_from_daath_ai_parser.json())

Вот пример ответа с только разбором:

���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������



Ожидаемые ошибки

Различные ошибки OpenAI возвращаются в ответе, чтобы пользователю не приходилось постоянно переключаться:

����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

Если возникает ошибка связи в хостинге для одного или нескольких параллельных запросов, она будет иметь следующий вид:

�������������������������������������������������������������������������

Если переданный вами элемент уже превышает максимальный размер токена, ошибка будет иметь следующий вид:

��������������������������������������������������������������������������������������������������������������������������

Если у вас возникнут другие ошибки, не стесняйтесь создавать об этом отчеты.


Настройка разрешенной конкурентности и ключа API для клиентских вызовов

Вы можете настроить количество разрешенной конкурентности для клиентских вызовов с помощью ключа ���������������������. Максимальное количество вызовов, которые вы можете сделать в минуту, все еще должно быть настроено вами. Вы можете вставить задержку между вызовами к �����������������, чтобы избежать превышения лимита, установленного OpenAI. Вот пример скрипта, где разрешенная конкурентность равна 2:

import requests

uri = "https://ai.kagermanov.com/classify"
headers = {"Content-Type": "application/json"}
data = {
  "allowed_concurrency": 2,
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Кофейня</div><div>Nicosia</div><div class=\"pJ3Ci\"><span>Iconic Seattle-based coffeehouse chain</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ],
  "openai_key": "<OPENAI KEY>"
}
r = requests.post(url=uri, headers=headers, json=data)
print(r.json()["results"])

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

Руководство по внесению изменений

Если вы хотите внести вклад в этот проект, вы можете открыть pull request. Вы также можете создать issue, если у вас есть вопросы или предложения.

  • Добавление нового парсера предустановок

Вы можете создать промпт в OpenAI Playground, который создает таблицу, подобную этой:

Table

Затем вы можете преобразовать его в форму словаря, как показано в следующем примере:

# app/classify/parsers/google/google_local_results.py

from app.schemas import *
def commands():
  return json_to_pydantic({
    "main_prompt": "Таблица с NUMBER_OF_LABELS ячеек в каждой строке, содержащая сводку различных частей текста на каждой строке:\n\n",
    "data": {
      "model": "text-davinci-003",
      "temperature": 0.001,
      "top_p": 0.9,
      "best_of": 2,
      "frequency_penalty": 0,
      "presence_penalty": 0
    },
    "model_specific_token_size": 3800,
    "openai_endpoint": "https://api.openai.com/v1/completions",
    "explicitly_excluded_strings": [
      "Order",
      "Website",
      "Directions",
      "\n"
    ],
    "examples_for_prompt": [
      {
        "text": "Houndstooth Coffee 4.6(824) · $$ · Coffee shop 401 Congress Ave. #100c · In Frost Bank Tower Closed ⋅ Opens 7AM Cozy hangout for carefully sourced brews",
        "classifications": {
          "line": "1",
          "title": "Houndstooth Coffee",
          "rating": "4.1",
          "number_of_reviews": "824",
          "expensiveness": "$$",
          "type": "Coffee Shop",
          "address": "401 Congress Ave. #100c · In Frost Bank Tower",
          "open_hours": "Opens 7AM",
          "description_or_review": "Cozy hangout for carefully sourced brews"
        }
      },
      # Дополнительные примеры ...
    ]
  })
  • Модульное тестирование

Вы можете легко добавить модульные тесты к вашему вкладу с помощью �����������.

# app/classify/tests/unit_tests/test_google_local_results.py
# ...
def test_google_local_results_successful_response():
  targets = [
    "app/classify/tests/data/targets/electronic-shops-successful.json"
  ]

for target_filename in targets:
    with open(target_filename) as json_file:
      target = json.load(json_file)
    r = client.post("/classify", json=target)
    result_filename = target['mock_name'].replace('.json','-result.json')
    result_filename = result_filename.replace('/targets/', '/results/')
    with open(result_filename) as json_file:
      result = json.load(json_file)
    assert r.status_code == 200
    assert r.json() == result
    assert len(r.json()['results']) > 0
    assert ("message" not in r.json()['results'][0])
# ...

Создайте json для вызова сервера localhost:

# app/classify/tests/data/targets/coffee-shops-successful.json
{
  "path": "google.google_local_results",
  "targets": [
    "<div jscontroller=\"AtSb\" class=\"w7Dbne\" data-record-click-time=\"false\" id=\"tsuid_25\" jsdata=\"zt2wNd;_;BvbRxs V6f1Id;_;BvbRxw\" jsaction=\"rcuQ6b:npT2md;e3EWke:kN9HDb\" data-hveid=\"CBUQAA\"><div jsname=\"jXK9ad\" class=\"uMdZh tIxNaf\" jsaction=\"mouseover:UI3Kjd\"><div class=\"VkpGBb\"><div class=\"cXedhc\"><a class=\"vwVdIc wzN8Ac rllt__link a-no-hover-decoration\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" tabindex=\"0\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEAE\"><div><div class=\"rllt__details\"><div class=\"dbg0pd\" aria-level=\"3\" role=\"heading\"><span class=\"OSrXXb\">Y Coffee</span></div><div><span class=\"Y0A0hc\"><span class=\"yi40Hd YrbPuc\" aria-hidden=\"true\">4.0</span><span class=\"z3HNkc\" aria-label=\"Rated 4.0 out of 5,\" role=\"img\"><span style=\"width:56px\"></span></span><span class=\"RDApEe YrbPuc\">(418)</span></span> · <span aria-label=\"Moderately expensive\" role=\"img\">€€</span> · Кофейня</div><div>Никосия</div><div class=\"pJ3Ci\"><span>Знаковая кофейня из Сиэтла</span></div></div></div></a><a class=\"uQ4NLd b9tNq wzN8Ac rllt__link a-no-hover-decoration\" aria-hidden=\"true\" tabindex=\"-1\" jsname=\"kj0dLd\" data-cid=\"12176489206865957637\" jsaction=\"click:h5M12e;\" role=\"link\" data-ved=\"2ahUKEwiS1P3_j-P7AhXnVPEDHa0oAiAQvS56BAgVEA4\"><g-img class=\"gTrj3e\"><img id=\"pimg_3\" src=\"https://lh5.googleusercontent.com/p/AF1QipPaihclGQYWEJpMpBnBY8Nl8QWQVqZ6tF--MlwD=w184-h184-n-k-no\" class=\"YQ4gaf zr758c wA1Bge\" alt=\"\" data-atf=\"4\" data-frt=\"0\" width=\"92\" height=\"92\"></g-img></a></div></div></div></div>"
  ],
  "mock_name": "app/classify/tests/data/results/coffee-shops-successful-result.json"
}

Запустите модульный тест с использованием �������� один раз, чтобы сгенерировать json.

Они будут созданы только при первом вызове, чтобы не исчерпывать кредиты при тестировании. Вот пример результата:

# app/classify/tests/data/results/coffee-shops-successful-result.json
{
  "results": [
    {
        "Адрес": "Никосия",
        "Описание или обзор": "Иконическая сеть кофеен из Сиэтла",
        "Стоимость": "€€",
        "Количество отзывов": "418",
        "Рейтинг": "4.0",
        "Название": "Y Coffee",
        "Тип": "Кофейня"
    }
  ]
}

Level Up Coding

Спасибо, что являетесь частью нашего сообщества! Перед тем, как вы уйдете:

  • 👏 Поставьте лайк этой статье и подпишитесь на автора 👉
  • 📰 Просмотрите больше материалов в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | LinkedIn | Newsletter

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите удивительную работу