Geminiで生成した定義からOpenAPI codegenでコード生成しKotlin Multiplatformで使用する件

# 概要
(自分メモ)
実際の要求と応答をGeminiに与えopenapi定義ファイルを生成し、swagger codegenでクライアントコードを生成しkotlinで使用する例
楽だわ

# 環境
- Windows 11 
- Gemini 2.0 flash ([Gemini API Key](https://aistudio.google.com/apikey) を用意) ※APIではgemini-1.5-flashを使用
- Java 21

# OpenAPI定義ファイル作成
```:Geminiに自身のQuick Startページから定義を作るよう依頼し..
下記要求と応答を表現するopenapi3.0.yamlを生成して
- データ型はschemas:として定義
- keyは全API共通なのでのsecurity:に定義

要求:
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"contents": [{"parts":[{"text": "Write a story about a magic backpack."}]}]}'

応答:
{
  "candidates": 
  # ..中略..
  "modelVersion": "gemini-1.5-flash"
}
```

```yaml: ...て作ってもらった gemini.yml
openapi: 3.0.0
info:
  title: Gemini API
  version: v1beta
servers:
  - url: 'https://generativelanguage.googleapis.com/v1beta'
components:
  schemas:
    Part:
      type: object
      properties:
        text:
          type: string
    Content:
      type: object
      properties:
        parts:
          type: array
          items:
            $ref: '#/components/schemas/Part'
        role:
          type: string
    Candidate:
      type: object
      properties:
        content:
          $ref: '#/components/schemas/Content'
        finishReason:
          type: string
        avgLogprobs:
          type: number
          format: float
    UsageMetadata:
      type: object
      properties:
        promptTokenCount:
          type: integer
        candidatesTokenCount:
          type: integer
        totalTokenCount:
          type: integer
    GenerateContentRequest:
      type: object
      properties:
        contents:
          type: array
          items:
            type: object
            properties:
              parts:
                type: array
                items:
                  $ref: '#/components/schemas/Part'
    GenerateContentResponse:
      type: object
      properties:
        candidates:
          type: array
          items:
            $ref: '#/components/schemas/Candidate'
        usageMetadata:
          $ref: '#/components/schemas/UsageMetadata'
        modelVersion:
          type: string
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: query
      name: key
paths:
  '/models/gemini-1.5-flash:generateContent':
    post:
      description: desc
      summary: Generates content using the Gemini model.
      operationId: generateContent # ※
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateContentRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerateContentResponse'
      security: []
      parameters:
        - schema:
            type: string
          in: query
          name: key
          required: true
```
```yaml:※一部呼び出し側に合うよう調整
  '/models/gemini-1.5-flash:generateContent':
    post:
      description: desc
      summary: Generates content using the Gemini model.
+     operationId: generateContent
```

[Swagger](https://editor-next.swagger.io/)に突っ込んで実行できることを確認 [➜](https://qiita.com/shokkaa/items/f51ace7619a97d97eff7#%E3%83%A1%E3%83%A2%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7swagger-editor)
# ソース
```kotlin:App.kt(抜粋)
expect val GEMINI_API_KEY: String

suspend fun appGemini() {
    val client = HttpClient { install(ContentNegotiation) { json(Json) } }
    val api = DefaultApi("https://generativelanguage.googleapis.com/v1beta", client)
    val prompt = "GeminiとOpenAPIに関する今日のTipsを一つ教えて"
    val req = GenerateContentRequest(listOf(GenerateContentRequestContentsInner(listOf(Part(prompt)))))
    val res = api.generateContent(GEMINI_API_KEY, req).body()
    println(Json.encodeToString(res.candidates?.get(0)?.content?.parts?.get(0)?.text))
    client.close()
}
```
[全ソース](https://github.com/kyoya-p/samples/tree/master/2024/openapi/geminiTrial)

# テスト実行
```sh
GEMINI_API_KEY='AIza************'
sh gradlew jvmRun -DmainClass=MainKt  # jvmの場合
sh gradlew jsNodeRun                  # node.jsの場合
```

# Build & Run
```

```

# (メモ)ローカルでSwagger Editor
```sh
wget https://github.com/swagger-api/swagger-editor/archive/refs/tags/v4.14.1.zip
unzip v4.14.1.zip
```
ブラウザに`./index.html`を放り込む

# 参考
[OpenAPI Generator](https://openapi-generator.tech/docs/plugins/)
[Gradleプラグイン](https://plugins.gradle.org/plugin/org.openapi.generator)

https://qiita.com/shokkaa/items/980fd9b9a3501678090c