Техническое практическое руководство Duet AI для разработчиков Codelab

1. Цели

Цель этого семинара — предоставить пользователям и практикам практическое обучение Duet AI.

В этой лаборатории вы узнаете следующее:

  1. Активируйте Duet AI в своем проекте GCP и настройте его для использования в IDE и облачной консоли.
  2. Используйте Duet AI для генерации, завершения и объяснения кода.
  3. Используйте Duet AI для объяснения и устранения проблем с приложением.
  4. Функции искусственного интеллекта Duet, такие как чат IDE и многоходовой чат, чат и встроенная генерация кода, интеллектуальные действия, такие как объяснение кода и подтверждение чтения, и многое другое.

Повествование

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

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

Поскольку разработчик новичок в компании, он будет использовать Duet AI для генерации, объяснения и документации кода.

После написания кода службы администратор платформы будет использовать Duet AI (чат), чтобы помочь создать артефакт (докер-контейнер), а также ресурсы, необходимые для развертывания артефакта в GCP (например, реестр артефактов, разрешения IAM, хранилище кода, вычислительные инфраструктура, например GKE или CloudRun и т. д.).

После развертывания приложения в GCP оператор приложения/SRE будет использовать Duet AI (и Cloud Ops), чтобы устранить ошибку в новом сервисе.

Персона

Семинар охватывает следующих персон:

  1. Разработчик приложений . Требуются некоторые знания в области программирования и разработки программного обеспечения.

Этот вариант семинара Duet AI предназначен только для разработчиков. Никаких знаний об облачных ресурсах GCP не требуется. Скрипты по сборке необходимых ресурсов GCP для запуска этого приложения можно найти здесь . Вы можете следовать инструкциям в этом руководстве, чтобы развернуть необходимые ресурсы GCP.

2. Подготовка среды

Активация Duet AI

Вы можете активировать Duet AI в проекте GCP либо через API (инструменты gcloud или IaC, такие как Terraform), либо через пользовательский интерфейс Cloud Console.

Чтобы активировать Duet AI в проекте Google Cloud, вы включаете API Cloud AI Companion и предоставляете пользователям роли «Пользователь Cloud AI Companion» и «Просмотр использования службы» (IAM).

Через gcloud

Активируйте Cloud Shell:

Настройте PROJECT_ID , USER и включите Cloud AI Companion API.

export PROJECT_ID=<YOUR PROJECT ID>
export USER=<YOUR USERNAME> # Use your full LDAP, e.g. name@example.com
gcloud config set project ${PROJECT_ID}
gcloud services enable cloudaicompanion.googleapis.com --project ${PROJECT_ID}

Вывод выглядит следующим образом:

Updated property [core/project].
Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.

Предоставьте учетной записи ПОЛЬЗОВАТЕЛЯ роль пользователя Cloud AI Companion и роли средства просмотра использования службы управления идентификацией и доступом (IAM). API Cloud Companion лежит в основе функций как IDE, так и консоли, которые мы будем использовать. Разрешение «Просмотр использования службы» используется для быстрой проверки перед включением пользовательского интерфейса в консоли (так что пользовательский интерфейс Duet отображается только в проектах, в которых включен API).

gcloud projects add-iam-policy-binding  ${PROJECT_ID} \
--member=user:${USER} --role=roles/cloudaicompanion.user

gcloud projects add-iam-policy-binding  ${PROJECT_ID} \
--member=user:${USER} --role=roles/serviceusage.serviceUsageViewer

Вывод выглядит следующим образом:

...
- members:
  - user:<YOUR USER ACCOUNT>
  role: roles/cloudaicompanion.user

...
- members:
  - user:<YOUR USER ACCOUNT>
  role: roles/serviceusage.serviceUsageViewer

Через облачную консоль

Чтобы включить API, перейдите на страницу Cloud AI Companion API в консоли Google Cloud.

В селекторе проектов выберите проект.

Нажмите Включить .

Страница обновится и отобразит статус «Включено» . Duet AI теперь доступен в выбранном проекте Google Cloud всем пользователям, имеющим необходимые роли IAM.

Чтобы предоставить роли IAM, необходимые для использования Duet AI, перейдите на страницу IAM .

В столбце «Основной» найдите своего ПОЛЬЗОВАТЕЛЯ, для которого вы хотите предоставить доступ к Duet AI, а затем щелкните значок карандаша ✏️ Изменить основного в этой строке.

На панели «Изменить доступ» нажмите « Добавить другую роль» .

В разделе «Выберите роль» выберите «Пользователь Cloud AI Companion» .

Нажмите «Добавить другую роль» и выберите «Просмотр использования службы» .

Нажмите Сохранить .

Настройка IDE

Разработчики могут выбирать из множества IDE, которые лучше всего соответствуют их потребностям. Поддержка кода Duet AI доступна в нескольких IDE, таких как Visual Studio Code , IDE JetBrains (IntelliJ, PyCharm, GoLand, WebStorm и др.), Cloud Workstations , Cloud Shell Editor .

В этой лабораторной работе вы можете использовать либо Cloud Workstations , либо Cloud Shell Editor.

В этом семинаре используется редактор Cloud Shell.

Обратите внимание, что настройка облачных рабочих станций может занять 20–30 минут.

Для немедленного использования используйте Cloud Shell Editor .

Откройте редактор Cloud Shell, щелкнув значок карандаша ✏️ в верхней строке меню Cloud Shell.

Cloud Shell Editor имеет пользовательский интерфейс и UX, очень похожий на VSCode.

d6a6565f83576063.png

Нажмите CTRL (в Windows)/CMD (в Mac) + (запятая), чтобы открыть панель «Настройки».

В строке поиска введите «duet ai».

Убедитесь или включите Cloudcode › Duet AI: включить и Cloudcode › Duet AI › Встроенные предложения: включить автоматически

111b8d587330ec74.png

В нижней строке состояния нажмите Cloud Code — Войти и следуйте инструкциям по входу.

Если вы уже вошли в систему, в строке состояния отображается надпись Cloud Code — No project .

Нажмите Cloud Code — проект отсутствует, и вверху появится раскрывающийся список действий. Нажмите «Выбрать проект Google Cloud» .

3241a59811e3c84a.png

Начните вводить свой идентификатор ПРОЕКТА, и ваш проект должен появиться в списке.

c5358fc837588fe.png

Выберите свой PROJECT_ID из списка проектов.

Нижняя строка состояния обновится и отобразит идентификатор вашего проекта. Если это не так, возможно, вам придется обновить вкладку редактора Cloud Shell.

Нажмите на значок Duet AI. d97fc4e7b594c3af.png в левой строке меню, и появится окно чата Duet AI. Если вы получили сообщение «Выберите проект GCP». Нажмите и повторно выберите проект.

Теперь вы видите окно чата Duet AI.

781f888360229ca6.png

3. Настройка инфраструктуры

d3234d237f00fdbb.png

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

  1. Экземпляр Cloud SQL с базой данных.
  2. Кластер GKE для запуска контейнерной службы.
  3. Реестр артефактов для хранения образа Docker.
  4. Облачный репозиторий исходного кода для кода.

В терминале Cloud Shell клонируйте следующий репозиторий и выполните следующие команды, чтобы настроить инфраструктуру в вашем проекте GCP.

# Set your project
export PROJECT_ID=<INSERT_YOUR_PROJECT_ID>
gcloud config set core/project ${PROJECT_ID}

# Enable Cloudbuild and grant Cloudbuild SA owner role 
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)')
gcloud services enable cloudbuild.googleapis.com
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com --role roles/owner

# Clone the repo
git clone https://github.com/duetailabs/dev.git ~/duetaidev
cd ~/duetaidev

# Run Cloudbuild to create the necessary resources
gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID}

# To destroy all GCP resources, run the following
# gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} --config=cloudbuild_destroy.yaml

4. Разработка сервиса Python Flask

9745ba5c70782e76.png

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

  1. package-service.yaml — спецификация Open API для службы пакетов, содержащая такие данные, как высота, ширина, вес и специальные инструкции по обработке.
  2. data_model.py — модель данных для спецификации API службы пакетов. Также создает таблицу packages в базе данных Product_details.
  3. connect_connector.py — соединение CloudSQL (определяет движок, сеанс и базовый ORM)
  4. db_init.py — генерирует образцы данных в таблицу packages .
  5. main.py — служба Python Flask с конечной точкой GET для получения сведений о пакете из данных packages на основе Product_id.
  6. test.py — Модульный тест
  7. requirement.txt — требования Python
  8. Dockerfile — для контейнеризации этого приложения.

Если во время упражнений у вас возникнут какие-либо неприятные проблемы, все окончательные файлы для справки находятся в ПРИЛОЖЕНИИ этой кодовой лаборатории.

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

В терминале Cloud Shell выполните следующую команду, чтобы клонировать репозиторий.

cd ~
gcloud source repos clone shipping shipping
cd ~/shipping 

Откройте боковую панель чата Duet AI в левом меню редактора Cloud Shell. Значок выглядит так 8b135a000b259175.png . Теперь вы можете использовать Duet AI для помощи в написании кода.

пакет-service.yaml

Не открывая никаких файлов, попросите Duet создать спецификацию Open API для службы доставки.

Подсказка 1. Создайте спецификацию OpenAPI yaml для службы, которая предоставляет информацию о доставке и упаковке с учетом числового идентификатора продукта. Услуга должна включать информацию о высоте, ширине, глубине, весе упаковки и любые специальные инструкции по обращению.

ba12626f491a1204.png

В правом верхнем углу окна сгенерированного кода перечислены три параметра.

Вы можете либо COPY 71194556d8061dae.png код и ВСТАВЬТЕ его в файл.

Вы можете ADD df645de8c65607a.png код текущего открытого файла в редакторе.

Или вы можете OPEN a4c7ed6d845df343.png код в новом файле.

Нажмите кнопку OPEN a4c7ed6d845df343.png код в новом файле.

Нажмите CTRL/CMD + s чтобы сохранить файл, и сохраните его в папке приложения с именем package-service.yaml . Нажмите ОК.

f6ebd5b836949366.png

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

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

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

data_model.py

Затем вы создаете файл Python модели данных для службы на основе спецификации OpenAPI.

Открыв файл package-service.yaml , введите следующую строку.

Подсказка 1. Используя ORM Python sqlalchemy, создайте модель данных для этой службы API. Также включите отдельную функцию и основную точку входа, которая создает таблицы базы данных.

b873a6a28bd28ca1.png

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

Во-первых, существует класс Package of kind Base , который определяет модель данных для базы данных packages , как показано ниже:

class Package(Base):
    __tablename__ = 'packages'

    id = Column(Integer, primary_key=True)
    product_id = Column(String(255))
    height = Column(Float)
    width = Column(Float)
    depth = Column(Float)
    weight = Column(Float)
    special_handling_instructions = Column(String(255))

Далее вам понадобится функция, которая создает таблицу в базе данных следующим образом:

def create_tables(engine):
    Base.metadata.create_all(engine)

Наконец, вам нужна основная функция, которая запускает функцию create_tables для фактического построения таблицы в базе данных CloudSQL, как показано ниже:

if __name__ == '__main__':
    from sqlalchemy import create_engine

    engine = create_engine('sqlite:///shipping.db')
    create_tables(engine)

    print('Tables created successfully.')

Обратите внимание, что main функция — создание движка с использованием локальной базы данных sqlite . Чтобы использовать CloudSQL, вам необходимо его изменить. Вы сделаете это немного позже.

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле data_model.py (обратите внимание на подчеркивание в имени, а не на тире).

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

Connect-connector.py

Создайте коннектор CloudSQL.

Открыв файл data_model.py , введите следующие запросы.

Подсказка 1. Используя библиотеку cloud-sql-python-connector, создайте функцию, которая инициализирует пул соединений для экземпляра Cloud SQL Postgres.

ed05cb6ff85d34c5.png

Обратите внимание, что в ответе не используется библиотека cloud-sql-python-connector . Вы можете уточнить подсказки, чтобы немного подтолкнуть Duet, добавив подробности в ту же ветку чата.

Давайте воспользуемся другой подсказкой.

Подсказка 2. Необходимо использовать библиотеку Cloud-sql-python-connector.

d09095b44dde35bf.png

Убедитесь, что он использует библиотеку cloud-sql-python-connector .

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле с именем connect_conector.py . Возможно, вам придется вручную импортировать библиотеку pg8000 , см. файл ниже.

Очистите историю чата Duet AI и, открыв файл connect_connector.py , сгенерируйте DB engine , sessionmaker и base ORM, которые будут использоваться в приложении.

Подсказка 1. Создайте движок, класс создателя сеансов и базовую ORM, используя метод Connect_with_connector.

6e4214b72ab13a63.png

Ответ может добавить engine , Session и Base в файл connect_connector.py .

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

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

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

Обновление data_model.py

Вам нужно использовать движок, созданный на предыдущем шаге (в файле connect_connector.py ), чтобы создать таблицу в базе данных CloudSQL.

Очистите историю чата Duet AI. Откройте файл data_model.py . Попробуйте следующую подсказку.

Подсказка 1. В основной функции импортируйте и используйте движок из Connect_connector.py.

2e768c9b6c523b9a.png

Вы должны увидеть engine импорта ответов из connect_connector (для CloudSQL). create_table использует этот движок (вместо локальной базы данных sqlite по умолчанию).

Обновите файл data_model.py .

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

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

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

требования.txt

Создайте файл requirements.txt для приложения.

Откройте файл connect_connector.py и data_model.py и введите следующую строку.

Подсказка 1. Создайте файл требований pip для этой модели данных и сервиса.

Подсказка 2. Создайте файл требований pip для этой модели данных и службы, используя последние версии.

69fae373bc5c6a18.png

Убедитесь, что имена и версии верны. Например, в ответе выше имя и версия google-cloud-sql-connecter неверны. Вручную исправьте версии и создайте файл requirements.txt , который выглядит следующим образом:

cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0

В командном терминале выполните следующее:

pip3 install -r requirements.txt

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

Создание таблицы пакетов в CloudSQL

Задайте переменные среды для коннектора базы данных CloudSQL.

export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)')
export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)")
export DB_USER=evolution
export DB_PASS=evolution
export DB_NAME=product_details

Теперь запустите data_model.py.

python data_model.py

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

Tables created successfully.

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

gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details

После ввода пароля (тоже эволюции ) получите таблицы.

product_details=> \dt

Вывод аналогичен следующему:

           List of relations
 Schema |   Name   | Type  |   Owner   
--------+----------+-------+-----------
 public | packages | table | evolution
(1 row)

Вы также можете проверить модель данных и сведения о таблице.

product_details=> \d+ packages

Вывод аналогичен следующему:

                                                                        Table "public.packages"
            Column             |       Type        | Collation | Nullable |               Default                | Storage  | Compression | Stats target | Description 
-------------------------------+-------------------+-----------+----------+--------------------------------------+----------+-------------+--------------+-------------
 id                            | integer           |           | not null | nextval('packages_id_seq'::regclass) | plain    |             |              | 
 product_id                    | integer           |           | not null |                                      | plain    |             |              | 
 height                        | double precision  |           | not null |                                      | plain    |             |              | 
 width                         | double precision  |           | not null |                                      | plain    |             |              | 
 depth                         | double precision  |           | not null |                                      | plain    |             |              | 
 weight                        | double precision  |           | not null |                                      | plain    |             |              | 
 special_handling_instructions | character varying |           |          |                                      | extended |             |              | 
Indexes:
    "packages_pkey" PRIMARY KEY, btree (id)
Access method: heap

Введите \q , чтобы выйти из CloudSQL.

db_init.py

Далее давайте добавим примеры данных в таблицу packages .

Очистите историю чата Duet AI. Открыв файл data_model.py , попробуйте выполнить следующие запросы.

Подсказка 1. Создайте функцию, которая создает 10 строк образцов пакетов и фиксирует их в таблице пакетов.

Подсказка 2. Используя сеанс Connect_connector, создайте функцию, которая создает 10 строк образцов пакетов и фиксирует их в таблице пакетов.

34a9afc5f04ba5.png

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле db_init.py .

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

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

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

Создание образцов данных пакетов

Запустите db_init.py из командной строки.

python db_init.py

Вывод аналогичен следующему:

Packages created successfully.

Снова подключитесь к экземпляру CloudSQL и убедитесь, что образец данных добавлен в таблицу пакетов.

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

gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details

После ввода пароля (тоже эволюции ) получите все данные из таблицы packages.

product_details=> SELECT * FROM packages;

Вывод аналогичен следующему:

 id | product_id | height | width | depth | weight |   special_handling_instructions   
----+------------+--------+-------+-------+--------+-----------------------------------
  1 |          0 |     10 |    10 |    10 |     10 | No special handling instructions.
  2 |          1 |     10 |    10 |    10 |     10 | No special handling instructions.
  3 |          2 |     10 |    10 |    10 |     10 | No special handling instructions.
  4 |          3 |     10 |    10 |    10 |     10 | No special handling instructions.
  5 |          4 |     10 |    10 |    10 |     10 | No special handling instructions.
  6 |          5 |     10 |    10 |    10 |     10 | No special handling instructions.
  7 |          6 |     10 |    10 |    10 |     10 | No special handling instructions.
  8 |          7 |     10 |    10 |    10 |     10 | No special handling instructions.
  9 |          8 |     10 |    10 |    10 |     10 | No special handling instructions.
 10 |          9 |     10 |    10 |    10 |     10 | No special handling instructions.
(10 rows)

Введите \q , чтобы выйти из CloudSQL.

main.py

Открыв файлы data_model.py , package-service.yaml и connect_connector.py , создайте main.py для приложения.

Подсказка 1. Использование библиотеки Python flask. Создайте реализацию, которая использует конечные точки отдыха HTTP для этой службы.

Подсказка 2. Использование библиотеки Python flask — создайте реализацию, которая использует конечные точки отдыха http для этой службы. импортируйте и используйте SessionMaker из Connect_conector.py для данных пакетов.

Подсказка 3. Использование библиотеки Python flask — создайте реализацию, которая использует конечные точки отдыха http для этой службы. импортируйте и используйте Package из data_model.py и SessionMaker из Connect_conector.py для данных пакетов.

Подсказка 4. Использование библиотеки Python flask — создайте реализацию, которая использует конечные точки отдыха http для этой службы. импортируйте и используйте Package из data_model.py и SessionMaker из Connect_conector.py для данных пакетов. Используйте IP-адрес хоста 0.0.0.0 для app.run.

6d794fc52a90e6ae.png

Обновите требования для main.py

Подсказка: Создайте файл требований для main.py.

1cc0b318d2d4ca2f.png

Добавьте это в файл requirements.txt . Обязательно используйте Flask версии 3.0.0.

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле main.py

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

5. Тестирование и запуск приложения.

Установите требования.

pip3 install -r requirements.txt

Запустите main.py

python main.py

Вывод аналогичен следующему:

 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://10.88.0.3:5000
Press CTRL+C to quit

На втором терминале проверьте конечную точку /packages/<product_id> .

curl localhost:5000/packages/1

Вывод аналогичен следующему:

{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}

Вы также можете протестировать любой другой идентификатор продукта в образце данных.

Введите CTRL_C , чтобы выйти из работающего Docker-контейнера в терминале.

Генерация модульных тестов

Открыв файл main.py , сгенерируйте модульные тесты.

Подсказка 1. Создайте модульные тесты.

e861e5b63e1b2657.png

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле test.py

В функции test_get_package должен быть определен product_id . Вы можете добавить его вручную.

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

Сбросьте историю чата Duet AI, щелкнув значок корзины. f574ca2c1e114856.png в верхней части боковой панели Duet AI.

Запуск модульных тестов

Запустите модульный тест.

python test.py

Вывод аналогичен следующему:

.
----------------------------------------------------------------------
Ran 1 test in 1.061s

OK

Закройте все файлы в редакторе Cloud Shell и очистите историю чата, нажав значок корзины. 1ecccfe10d6c540.png в верхней строке состояния.

Докерфайл

Создайте Dockerfile для этого приложения.

Откройте main.py и попробуйте выполнить следующие запросы.

Подсказка 1. Создайте файл Dockerfile для этого приложения.

Подсказка 2. Создайте файл Dockerfile для этого приложения. Скопируйте все файлы в контейнер.

9c473caea437a5c3.png

Вам также необходимо установить ENVARS для INSTANCE_CONNECTION_NAME , DB_USER , DB_PASS и DB_NAME . Вы можете сделать это вручную. Ваш Dockerfile должен выглядеть следующим образом:

FROM python:3.10-slim

WORKDIR /app

COPY . ./

RUN pip install -r requirements.txt

# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details

CMD ["python", "main.py"]

Использование кнопки OPEN a4c7ed6d845df343.png код в новом рабочем процессе с файлами, как и раньше. Сохраните код в файле Dockerfile.

Окончательный файл находится в разделе ПРИЛОЖЕНИЕ этой лаборатории кода. Если это не так, вручную внесите соответствующие изменения.

Локальный запуск приложения

Открыв Dockerfile , попробуйте следующую подсказку.

Подсказка 1. Как мне локально запустить контейнер с помощью этого файла Dockerfile?

570fd5c296ca8c83.png

Следуйте инструкциям.

# Build
docker build -t shipping .
# And run
docker run -p 5000:5000 -it shipping

Вывод аналогичен следующему:

 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.17.0.2:5000
Press CTRL+C to quit

Из второго окна терминала получите доступ к контейнеру.

curl localhost:5000/packages/1

Вывод аналогичен следующему:

{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}

Контейнерное приложение работает.

Введите CTRL_C , чтобы выйти из работающего Docker-контейнера в терминале.

Создание образа контейнера в реестре артефактов

Создайте образ контейнера и отправьте его в реестр артефактов.

cd ~/shipping
gcloud auth configure-docker us-central1-docker.pkg.dev
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping .
docker push us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping

Контейнер приложения теперь находится по адресу us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping , который можно развернуть в GKE.

6. Развертывание приложения в кластере GKE

Кластер GKE Autopilot был создан, когда вы создавали ресурсы GCP для этого семинара. Подключитесь к кластеру GKE.

gcloud container clusters get-credentials gke1 \
    --region=us-central1

Аннотируйте учетную запись службы Kubernetes по умолчанию с учетной записью службы Google.

kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com

Вывод аналогичен следующему:

serviceaccount/default annotated

Подготовьте и примените файл k8s.yaml.

cp ~/duetaidev/k8s.yaml_tmpl ~/shipping/.
export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)')
export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)")
export IMAGE_REPO=us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
envsubst < ~/shipping/k8s.yaml_tmpl > k8s.yaml
kubectl apply -f k8s.yaml

Вывод аналогичен следующему:

deployment.apps/shipping created
service/shipping created

Подождите, пока модули не заработают и службе не будет назначен IP-адрес внешнего балансировщика нагрузки.

kubectl get pods
kubectl get service shipping

Вывод аналогичен следующему:

# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
shipping-f5d6f8d5-56cvk   1/1     Running   0          4m47s
shipping-f5d6f8d5-cj4vv   1/1     Running   0          4m48s
shipping-f5d6f8d5-rrdj2   1/1     Running   0          4m47s

# kubectl get service shipping
NAME       TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
shipping   LoadBalancer   34.118.225.125   34.16.39.182   80:30076/TCP   5m41s

Для кластеров GKE Autopilot подождите несколько минут, пока ресурсы не будут готовы.

Доступ к услуге через EXTERNAL-IP адрес.

export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1

Вывод аналогичен следующему:

{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}

7. Дополнительный балл: устранение неполадок приложения.

Удалите роль IAM клиента CloudSQL из учетной записи службы cloudsqlsa . Это вызывает ошибку подключения к базе данных CloudSQL.

gcloud projects remove-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/cloudsql.client"

Перезапустите модуль доставки.

kubectl rollout restart deployment shipping

После перезапуска модуля попробуйте снова получить доступ к службе shipping .

export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1 

Вывод аналогичен следующему:

...
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>

Проверьте журналы, перейдя в Kubernetes Engine > Рабочие нагрузки.

d225b1916c829167.png

Нажмите на развертывание shipping , а затем вкладку «Журналы» .

1d0459141483d6a7.png

Нажмите «Просмотр» в обозревателе журналов. df8b9d19a9fe4c73.png значок в правой части строки состояния. Откроется новое окно обозревателя журналов .

e86d1c265e176bc4.png

Нажмите на одну из записей об ошибках Traceback , а затем нажмите «Объяснить эту запись журнала» .

d6af045cf03008bc.png

Вы можете прочитать объяснение ошибки.

Далее давайте воспользуемся Duet AI, чтобы помочь устранить ошибку.

Попробуйте следующую подсказку.

Подсказка 1. Помогите мне устранить эту ошибку.

9288dd6045369167.png

Введите сообщение об ошибке в командной строке.

Подсказка 2: Запрещено: участник IAM, прошедший проверку подлинности, не уполномочен выполнять запросы API. Убедитесь, что «API администратора Cloud SQL» включен в вашем проекте GCP, а роль «Клиент Cloud SQL» предоставлена ​​субъекту IAM.

f1e64fbdc435d31c.png

А потом.

Подсказка 3. Как назначить роль клиента Cloud SQL учетной записи службы Google с помощью gcloud?

bb8926b995a8875c.png

Назначьте роль Cloud SQL Client файлу cloudsqlsa .

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/cloudsql.client"

Подождите несколько минут и попробуйте снова получить доступ к приложению.

export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1

Вывод аналогичен следующему:

{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}

Вы успешно использовали Duet AI в облачном журналировании , обозревателе журналов и функции объяснения журналов для устранения проблемы.

8. Заключение

Поздравляем! Вы успешно завершили эту лабораторную работу.

В этой лаборатории вы узнали следующее:

  1. Активируйте Duet AI в своем проекте GCP и настройте его для использования в IDE и облачной консоли.
  2. Используйте Duet AI для генерации, завершения и объяснения кода.
  3. Используйте Duet AI для объяснения и устранения проблем с приложением.
  4. Функции искусственного интеллекта Duet, такие как чат IDE и многоходовой чат, чат и встроенная генерация кода, интеллектуальные действия, такие как объяснение кода и подтверждение чтения, и многое другое.

9. Приложение

пакет-service.yaml

swagger: "2.0"
info:
 title: Shipping and Package Information API
 description: This API provides information about shipping and packages.
 version: 1.0.0
host: shipping.googleapis.com
schemes:
 - https
produces:
 - application/json
paths:
 /packages/{product_id}:
   get:
     summary: Get information about a package
     description: This method returns information about a package, including its height, width, depth, weight, and any special handling instructions.
     parameters:
       - name: product_id
         in: path
         required: true
         type: integer
         format: int64
     responses:
       "200":
         description: A successful response
         schema:
           type: object
           properties:
             height:
               type: integer
               format: int64
             width:
               type: integer
               format: int64
             depth:
               type: integer
               format: int64
             weight:
               type: integer
               format: int64
             special_handling_instructions:
               type: string
       "404":
         description: The product_id was not found

data_model.py

from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base

from connect_connector import engine

Base = declarative_base()

class Package(Base):
    __tablename__ = 'packages'

    id = Column(Integer, primary_key=True)
    product_id = Column(Integer, nullable=False)
    height = Column(Float, nullable=False)
    width = Column(Float, nullable=False)
    depth = Column(Float, nullable=False)
    weight = Column(Float, nullable=False)
    special_handling_instructions = Column(String, nullable=True)

def create_tables():
    Base.metadata.create_all(engine)

if __name__ == '__main__':
    create_tables()

    print('Tables created successfully.')

Connect_connector.py

import os

from google.cloud.sql.connector import Connector, IPTypes
import sqlalchemy

# You may need to manually import pg8000 and Base as follows
import pg8000
from sqlalchemy.ext.declarative import declarative_base


def connect_with_connector() -> sqlalchemy.engine.base.Engine:
   """Initializes a connection pool for a Cloud SQL instance of Postgres."""
   # Note: Saving credentials in environment variables is convenient, but not
   # secure - consider a more secure solution such as
   # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
   # keep secrets safe.
   instance_connection_name = os.environ[
       "INSTANCE_CONNECTION_NAME"
   ]  # e.g. 'project:region:instance'
   db_user = os.environ["DB_USER"]  # e.g. 'my-database-user'
   db_pass = os.environ["DB_PASS"]  # e.g. 'my-database-password'
   db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

   ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

   connector = Connector()

   def getconn() -> sqlalchemy.engine.base.Engine:
       conn: sqlalchemy.engine.base.Engine = connector.connect(
           instance_connection_name,
           "pg8000",
           user=db_user,
           password=db_pass,
           db=db_name,
           ip_type=ip_type,
       )
       return conn

   pool = sqlalchemy.create_engine(
       "postgresql+pg8000://",
       creator=getconn,
       # ...
   )
   return pool

# Create a connection pool
engine = connect_with_connector()

# Create a sessionmaker class to create new sessions
SessionMaker = sqlalchemy.orm.sessionmaker(bind=engine)

# Create a Base class for ORM
# You may need to manually fix the following
Base = declarative_base()

db_init.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from connect_connector import engine

from data_model import Package

def create_packages():
    # Create a session
    session = sessionmaker(bind=engine)()

    # Create 10 sample packages
    for i in range(10):
        package = Package(
            product_id=i,
            height=10.0,
            width=10.0,
            depth=10.0,
            weight=10.0,
            special_handling_instructions="No special handling instructions."
        )

        # Add the package to the session
        session.add(package)

    # Commit the changes
    session.commit()

if __name__ == '__main__':
    create_packages()

    print('Packages created successfully.')

main.py

from flask import Flask, request, jsonify

from data_model import Package
from connect_connector import SessionMaker

app = Flask(__name__)

session_maker = SessionMaker()

@app.route("/packages/<int:product_id>", methods=["GET"])
def get_package(product_id):
  """Get information about a package."""

  session = session_maker

  package = session.query(Package).filter(Package.product_id == product_id).first()

  if package is None:
    return jsonify({"message": "Package not found."}), 404

  return jsonify(
      {
          "height": package.height,
          "width": package.width,
          "depth": package.depth,
          "weight": package.weight,
          "special_handling_instructions": package.special_handling_instructions,
      }
  ), 200

if __name__ == "__main__":
  app.run(host="0.0.0.0")

test.py

import unittest

from data_model import Package
from connect_connector import SessionMaker

from main import app

class TestPackage(unittest.TestCase):

    def setUp(self):
        self.session_maker = SessionMaker()

    def tearDown(self):
        self.session_maker.close()

    def test_get_package(self):
        """Test the `get_package()` function."""

        package = Package(
        product_id=11, # Ensure that the product_id different from the sample data
        height=10,
        width=10,
        depth=10,
        weight=10,
        special_handling_instructions="Fragile",
        )

        session = self.session_maker

        session.add(package)
        session.commit()

        response = app.test_client().get("/packages/11")

        self.assertEqual(response.status_code, 200)

        self.assertEqual(
            response.json,
            {
                "height": 10,
                "width": 10,
                "depth": 10,
                "weight": 10,
                "special_handling_instructions": "Fragile",
            },
        )

if __name__ == "__main__":
    unittest.main()

требования.txt

cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Flask==3.0.0
gunicorn==20.1.0
psycopg2-binary==2.9.3

Докерфайл

FROM python:3.10-slim

WORKDIR /app

COPY . ./

RUN pip install -r requirements.txt

# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details

CMD ["python", "main.py"]