はじめに
この記事は、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では拡張機能インストール画面からインストールします。
VSIXからのインストール
をクリックし、取得したVSIXファイルを選択します。
インストールがされると以下のアイコンがサイドメニューに表示されます。
こちらをクリックすると、以下のようにチャット画面が表示されます。
IntelliJ IDEAでのインストール
IntelliJ IDEAではプラグインインストール画面からインストールします。
設定画面からプラグイン
を選択し、ディスクからプラグインをインストール
を選択します。
取得したzipファイルを選択します。
インストールされると以下のアイコンがサイドバーに表示されます。
クリックすると以下のようなチャット画面が表示されます。
IntelliJ IDEAでOracle Code Assistを試そう
今回はIntelliJ IDEAでOracle Code Assistを試してみます。
日本語対応もしているので、今回は日本でコード生成を試みます。
こんな感じでコードを出してくれました。
全体はこんなコードでした。
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では、以下のようにクラスやメソッドの上部に複数のラベルが表示されます。
以下の機能が提供されているようです。
- テストコード生成
- コードドキュメント(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
を紹介しました!
まだまだ発展途上ではあるので、未完成な部分もありますが、今度の発展に期待ですね!
皆様からのフィードバックもお待ちしておりますので、お時間がある方はベータプログラムに参加申請して頂き、ぜひ忌憚なきご意見をお寄せいただけるとありがたいです!!
参考
-
Oracleプロファイルが必要です。また、承認プロセスがあります。このベータプログラムは情報提供のみを目的としており、機能の提供を約束するものではなく、購入の決定を行う際に依拠すべきものではありません。 ↩