7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle Cloud InfrastructureAdvent Calendar 2024

Day 20

実はOracleも出している...!? コード生成AI "Oracle Code Assist" とは?

Last updated at Posted at 2024-12-20

はじめに

この記事は、Oracle Cloud Infrastructure Advent Calender 2024 シリーズ 1 Day20の記事として書いています。

皆様はOracle Code Assistをご存知でしょうか?
実はOracleもコード生成AIを出しています。
まだ一般公開はされていませんが、絶賛開発中のプロダクトです。
現状はβ版として、申請をすると一般ユーザの皆様にもご利用いただけます。

この記事では、そんなOracle Code Assistについて少し触れたいと思います。

Oracle Code Assistとは

Oracle Code Assistは、OCIにおけるJava、JavaScript、PL/SQLおよびアプリケーション開発に最適化されたコード生成AIツールです。

現状β版として提供されており、こちらからお申し込み頂けます。1

サポートするIDEは以下の2種類です

  • Visual Studio Code
  • IntelliJ IDEA

IntelliJ IDEAプラグインが先行して開発されています。

Oracle Code Assistのインストール

β版を取得すると、それぞれVSCodeとIntelliJのプラグインとしてzipファイルとvsixファイルがダウンロードできます。

VSCodeのインストール

VSCodeでは拡張機能インストール画面からインストールします。

CleanShot 2024-12-20 at 16.07.05.png

VSIXからのインストールをクリックし、取得したVSIXファイルを選択します。

インストールがされると以下のアイコンがサイドメニューに表示されます。

CleanShot 2024-12-20 at 16.10.26.png

こちらをクリックすると、以下のようにチャット画面が表示されます。

CleanShot 2024-12-20 at 16.10.45.png

IntelliJ IDEAでのインストール

IntelliJ IDEAではプラグインインストール画面からインストールします。

設定画面からプラグインを選択し、ディスクからプラグインをインストールを選択します。
取得したzipファイルを選択します。

CleanShot 2024-12-20 at 16.22.47.png

インストールされると以下のアイコンがサイドバーに表示されます。

CleanShot 2024-12-20 at 16.25.55.png

クリックすると以下のようなチャット画面が表示されます。

CleanShot 2024-12-20 at 16.29.36.png

IntelliJ IDEAでOracle Code Assistを試そう

今回はIntelliJ IDEAでOracle Code Assistを試してみます。

日本語対応もしているので、今回は日本でコード生成を試みます。

CleanShot 2024-12-20 at 16.36.17.png

こんな感じでコードを出してくれました。

全体はこんなコードでした。

package org.example;

import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
import com.oracle.bmc.streaming.StreamClient;
import com.oracle.bmc.streaming.model.*;
import com.oracle.bmc.streaming.requests.GetMessagesRequest;
import com.oracle.bmc.streaming.responses.GetMessagesResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class GetMessagesExample {

    public static void main(String[] args) throws IOException {
        // OCIの認証情報ファイル(.oci/config)のパスを指定します。
        String configFilePath = "~/.oci/config";

        // 認証情報プロバイダーを作成します。
        ConfigFileAuthenticationDetailsProvider provider =
                new ConfigFileAuthenticationDetailsProvider(configFilePath);

        // Stream Clientを作成します。
        StreamClient streamClient = new StreamClient(provider);

        // ストリームのOCIDを指定します。
        String streamOcid = "ocid1.stream.oc1.iad.<unique_id>";

        // メッセージを取得するリクエストを作成します。
        GetMessagesRequest request = GetMessagesRequest.builder()
                .streamId(streamOcid)
                .limit(10) // 取得するメッセージ数を指定します。
                .build();

        try {
            // メッセージを取得します。
            GetMessagesResponse response = streamClient.getMessages(request);

            // 取得したメッセージを処理します。
            List<Message> messages = response.getItems();
            for (Message message : messages) {
                System.out.println("Key: " + message.getKey());
                System.out.println("Value: " + message.getValue());
            }
        } catch (Exception e) {
            System.err.println("Error getting messages: " + e.getMessage());
        } finally {
            // Stream Clientを閉じます。
            streamClient.close();
        }
    }
}

実は最近のOCI SDKでは非推奨のコードが含まれていたりしますが、そこはLLMの情報が古いということにしておきましょう...

Oracle Code Assistでは、以下のようにクラスやメソッドの上部に複数のラベルが表示されます。

CleanShot 2024-12-20 at 17.06.13.png

以下の機能が提供されているようです。

  • テストコード生成
  • コードドキュメント(Javaで言えばJavaDoc)やコードコメントの生成
  • クラスの説明
  • Chatへの対象コードのコピーアンドペースト

今回はテストコード生成を試してみます。

Generate Unit Testをクリックするとチャット画面に以下のようなコードが生成されました。

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class GetMessagesExampleTest {

    private MockedStatic<ConfigFileAuthenticationDetailsProvider> configFileAuthenticationDetailsProviderMockedStatic;
    private MockedStatic<StreamClient> streamClientMockedStatic;

    private ByteArrayOutputStream outContent;
    private ByteArrayOutputStream errContent;

    @BeforeEach
    public void setUp() {
        configFileAuthenticationDetailsProviderMockedStatic = Mockito.mockStatic(ConfigFileAuthenticationDetailsProvider.class);
        streamClientMockedStatic = Mockito.mockStatic(StreamClient.class);

        outContent = new ByteArrayOutputStream();
        errContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));
    }

    @AfterEach
    public void tearDown() {
        configFileAuthenticationDetailsProviderMockedStatic.close();
        streamClientMockedStatic.close();
        System.setOut(System.out);
        System.setErr(System.err);
    }

    @Test
    public void testMainSuccess() throws Exception {
        // Arrange
        var provider = mock(ConfigFileAuthenticationDetailsProvider.class);
        configFileAuthenticationDetailsProviderMockedStatic.when(() -> ConfigFileAuthenticationDetailsProvider.builder().build()).thenReturn(provider);

        var streamClient = mock(StreamClient.class);
        streamClientMockedStatic.when(() -> new StreamClient(any())).thenReturn(streamClient);

        var getMessagesResponse = mock(GetMessagesResponse.class);
        when(streamClient.getMessages(any())).thenReturn(getMessagesResponse);

        var messages = new ArrayList<>();
        messages.add(mock(Message.class));
        when(getMessagesResponse.getItems()).thenReturn(messages);

        // Act
        String[] args = {};
        GetMessagesExample.main(args);

        // Assert
        assertEquals("Key: " + messages.get(0).getKey() + "\n" +
                "Value: " + messages.get(0).getValue() + "\n", outContent.toString());
        verify(streamClient, times(1)).close();
    }

    @Test
    public void testMainFailure() throws Exception {
        // Arrange
        var provider = mock(ConfigFileAuthenticationDetailsProvider.class);
        configFileAuthenticationDetailsProviderMockedStatic.when(() -> ConfigFileAuthenticationDetailsProvider.builder().build()).thenReturn(provider);

        var streamClient = mock(StreamClient.class);
        streamClientMockedStatic.when(() -> new StreamClient(any())).thenReturn(streamClient);

        when(streamClient.getMessages(any())).thenThrow(new RuntimeException("Error"));

        // Act
        String[] args = {};
        GetMessagesExample.main(args);

        // Assert
        assertEquals("Error getting messages: Error\n", errContent.toString());
        verify(streamClient, times(1)).close();
    }

    @Test
    public void testMainEmptyMessages() throws Exception {
        // Arrange
        var provider = mock(ConfigFileAuthenticationDetailsProvider.class);
        configFileAuthenticationDetailsProviderMockedStatic.when(() -> ConfigFileAuthenticationDetailsProvider.builder().build()).thenReturn(provider);

        var streamClient = mock(StreamClient.class);
        streamClientMockedStatic.when(() -> new StreamClient(any())).thenReturn(streamClient);

        var getMessagesResponse = mock(GetMessagesResponse.class);
        when(streamClient.getMessages(any())).thenReturn(getMessagesResponse);

        when(getMessagesResponse.getItems()).thenReturn(null);

        // Act
        String[] args = {};
        GetMessagesExample.main(args);

        // Assert
        assertEquals("No messages found.\n", outContent.toString());
        verify(streamClient, times(1)).close();
    }

    @Test
    public void testMainIOException() {
        // Arrange
        assertThrows(IOException.class, () -> {
            // Act
            String[] args = {"invalid"};
            GetMessagesExample.main(args);
        });
    }
}

異常系も含まれていて、思ったよりしっかりしたテストコードが生成されていますね!!

おわりに

今回はまだβ版ではありますが、Oracleのコード生成AIであるOracle Code Assistを紹介しました!
まだまだ発展途上ではあるので、未完成な部分もありますが、今度の発展に期待ですね!
皆様からのフィードバックもお待ちしておりますので、お時間がある方はベータプログラムに参加申請して頂き、ぜひ忌憚なきご意見をお寄せいただけるとありがたいです!!

参考

  1. Oracleプロファイルが必要です。また、承認プロセスがあります。このベータプログラムは情報提供のみを目的としており、機能の提供を約束するものではなく、購入の決定を行う際に依拠すべきものではありません。

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?