├── .github
└── workflows
│ ├── codeql-analysis.yml
│ ├── dotnet.yml
│ └── nuget.yml
├── .gitignore
├── Directory.Build.props
├── LICENSE
├── ManagedCode.OpenAI.Tests
├── Architecture
│ ├── Constants.cs
│ └── IntegrationTestsRuntime.cs
├── Attributes
│ └── ManualTestAttribute.cs
├── Base
│ └── BaseTestClass.cs
├── ChatTests.cs
├── CommonTests.cs
├── CompletionTests.cs
├── EditTests.cs
├── Extensions
│ ├── ConfigurationExtensions.cs
│ ├── GenericTypeExtensions.cs
│ └── MockExtensions.cs
├── ImageTests.cs
├── ManagedCode.OpenAI.Tests.csproj
├── ModelsTests.cs
├── ModerationTests.cs
├── Properties
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ └── dog.png
├── Services
│ └── TestGptClientBuilder.cs
├── Startup.cs
└── testsettings.json
├── ManagedCode.OpenAI.sln
├── ManagedCode.OpenAI.sln.DotSettings
├── ManagedCode.OpenAI
├── API
│ ├── Abstractions
│ │ └── IOpenAiWebClient.cs
│ ├── Base
│ │ └── BaseCompletionsResponseDto.cs
│ ├── Chat
│ │ ├── ChatChoiceDto.cs
│ │ ├── ChatRequestDto.cs
│ │ ├── ChatResponseDto.cs
│ │ ├── MessageDto.cs
│ │ └── UsageDto.cs
│ ├── Completions
│ │ ├── CompletionChoiceDto.cs
│ │ ├── CompletionRequestDto.cs
│ │ └── CompletionResponseDto.cs
│ ├── Edit
│ │ ├── EditChoiceDto.cs
│ │ ├── EditRequestDto.cs
│ │ └── EditResponseDto.cs
│ ├── Errors
│ │ ├── OpenAIError.cs
│ │ ├── OpenAIErrorCode.cs
│ │ └── OpenAIException.cs
│ ├── File
│ │ ├── FileDeleteResponseDto.cs
│ │ ├── FileInfoDto.cs
│ │ └── FilesInfoResponseDto.cs
│ ├── Image
│ │ ├── BaseImageRequestDto.cs
│ │ ├── EditImageRequestDto.cs
│ │ ├── GenerateImageRequestDto.cs
│ │ ├── ImageResponseDataDto.cs
│ │ ├── ImageResponseDto.cs
│ │ └── VariationImageRequestDto.cs
│ ├── Models
│ │ ├── ModelDto.cs
│ │ ├── ModelsResponseDto.cs
│ │ └── PermissionDto.cs
│ ├── Moderation
│ │ ├── CategoryDto.cs
│ │ ├── CategoryResultDto.cs
│ │ ├── ModerationRequestDto.cs
│ │ └── ModerationResponseDto.cs
│ └── OpenAIWebClient.cs
├── Chat
│ ├── Abstractions
│ │ ├── IChatMessage.cs
│ │ ├── IChatMessageParameters.cs
│ │ ├── IChatMessageParametersBuilder.cs
│ │ ├── IChatSession.cs
│ │ ├── IChatSessionLoader.cs
│ │ ├── IChatSessionRecord.cs
│ │ ├── IGptChat.cs
│ │ └── IUsage.cs
│ ├── Extensions
│ │ ├── ChatExtensions.cs
│ │ ├── ClientChatExtensions.cs
│ │ └── MapperChatExtensions.cs
│ ├── GptChat.cs
│ ├── Message
│ │ ├── ChatMessage.cs
│ │ ├── ChatMessageParameters.cs
│ │ ├── ChatMessageParametersBuilder.cs
│ │ └── Usage.cs
│ └── Session
│ │ ├── ChatSession.cs
│ │ ├── ChatSessionLoader.cs
│ │ └── ChatSessionRecord.cs
├── Client
│ ├── Abstractions
│ │ ├── IAnswer.cs
│ │ ├── IGptClient.cs
│ │ ├── IGptClientBuilder.cs
│ │ ├── IGptClientConfiguration.cs
│ │ ├── IGptClientConfigurationBuilder.cs
│ │ ├── IModel.cs
│ │ └── IPermission.cs
│ ├── Configuration
│ │ ├── DefaultGptClientConfiguration.cs
│ │ └── GptClientConfigurationBuilder.cs
│ ├── Extensions
│ │ ├── GptClientExtensions.cs
│ │ └── MapperClientExtensions.cs
│ ├── GptClient.cs
│ ├── GptClientBuilder.cs
│ ├── Models
│ │ ├── Answer.cs
│ │ ├── GptModel.cs
│ │ ├── Model.cs
│ │ ├── Permission.cs
│ │ └── RoleType.cs
│ └── ServiceCollectionExtensions.cs
├── Completions
│ ├── Abstractions
│ │ ├── ICompletionBuilder.cs
│ │ └── ICompletionsMessage.cs
│ ├── CompletionsBuilder.cs
│ ├── CompletionsMessage.cs
│ ├── Extensions
│ │ └── MapperCompletionsExtensions.cs
│ └── ManagedCode.OpenAI.Client.Completions.csproj
├── Edit
│ ├── Abstractions
│ │ ├── IEditBuilder.cs
│ │ └── IEditMessage.cs
│ ├── EditBuilder.cs
│ ├── EditMessage.cs
│ └── Extensions
│ │ └── MapperEditExtensions.cs
├── Extensions
│ ├── EnumExtensions.cs
│ ├── ServiceCollectionExtensions.cs
│ └── ValidationExtensions.cs
├── Image
│ ├── Abstractions
│ │ ├── IBaseImageBuilder.cs
│ │ ├── IEditImageBuilder.cs
│ │ ├── IGenerateImageBuilder.cs
│ │ ├── IGptImage.cs
│ │ ├── IImageClient.cs
│ │ ├── IImageLoader.cs
│ │ └── IVariationImageBuilder.cs
│ ├── Builders
│ │ ├── BaseImageBuilder.cs
│ │ ├── DefaultImageLoader.cs
│ │ ├── EditImageBuilder.cs
│ │ ├── GenerateImageBuilder.cs
│ │ └── VariationImageBuilder.cs
│ ├── Extensions
│ │ ├── ImageClientExtensions.cs
│ │ └── MapperImageExtensions.cs
│ ├── ImageClient.cs
│ └── Models
│ │ ├── GptImage.cs
│ │ ├── ImageFormat.cs
│ │ └── ImageResolution.cs
├── ManagedCode.OpenAI.csproj
├── ManagedCode.OpenAI.csproj.DotSettings
└── Moderation
│ ├── Abstractions
│ ├── ICategory.cs
│ ├── IModeration.cs
│ └── IModerationBuilder.cs
│ ├── Exceptions
│ └── MapperModerationExtensions.cs
│ ├── Model
│ ├── Category.cs
│ └── Moderation.cs
│ └── ModerationBuilder.cs
├── README.md
└── logo.png
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '35 11 * * 4'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 |
28 | strategy:
29 | fail-fast: false
30 | matrix:
31 | language: [ 'csharp' ]
32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
33 | # Learn more:
34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
35 |
36 | steps:
37 | - name: Checkout repository
38 | uses: actions/checkout@v3
39 |
40 | # Initializes the CodeQL tools for scanning.
41 | - name: Initialize CodeQL
42 | uses: github/codeql-action/init@v2
43 | with:
44 | languages: ${{ matrix.language }}
45 | # If you wish to specify custom queries, you can do so here or in a config file.
46 | # By default, queries listed here will override any specified in a config file.
47 | # Prefix the list here with "+" to use these queries and those in the config file.
48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
49 |
50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
51 | # If this step fails, then you should remove it and run the build manually (see below)
52 | - name: Autobuild
53 | uses: github/codeql-action/autobuild@v2
54 |
55 | # ℹ️ Command-line programs to run using the OS shell.
56 | # 📚 https://git.io/JvXDl
57 |
58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
59 | # and modify them (or add more) to build your code if your project
60 | # uses a compiled language
61 |
62 | #- run: |
63 | # make bootstrap
64 | # make release
65 |
66 | - name: Perform CodeQL Analysis
67 | uses: github/codeql-action/analyze@v2
68 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 |
10 | # Allows you to run this workflow manually from the Actions tab
11 | workflow_dispatch:
12 |
13 | jobs:
14 |
15 | build-and-test:
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 |
20 | - uses: actions/checkout@v3
21 | - name: Setup .NET
22 | uses: actions/setup-dotnet@v3
23 | with:
24 | dotnet-version: 7.0.x
25 |
26 | # run build and test
27 | - name: Restore dependencies
28 | run: dotnet restore
29 | - name: Build
30 | run: dotnet build --no-restore
31 | - name: Test and Collect Code Coverage
32 | run: dotnet test -p:CollectCoverage=true --collect:"XPlat Code Coverage" --results-directory ./coverage
33 |
34 |
35 | # - name: coveralls
36 | # uses: coverallsapp/github-action@master
37 | # with:
38 | # github-token: ${{secrets.GITHUB_TOKEN }}
39 | # path-to-lcov: coverage/coverage.info
40 |
--------------------------------------------------------------------------------
/.github/workflows/nuget.yml:
--------------------------------------------------------------------------------
1 | name: nuget
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 |
7 | # Allows you to run this workflow manually from the Actions tab
8 | workflow_dispatch:
9 |
10 | jobs:
11 | nuget-pack:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Setup .NET
18 | uses: actions/setup-dotnet@v3
19 | with:
20 | dotnet-version: 7.0.x
21 |
22 | - name: Restore dependencies
23 | run: dotnet restore
24 | - name: Build
25 | run: dotnet build --configuration Release
26 | - name: Test
27 | run: dotnet test --configuration Release
28 | - name: Pack
29 | run: dotnet pack -p:IncludeSymbols=false -p:SymbolPackageFormat=snupkg --configuration Release
30 |
31 | - name: publish nuget packages
32 | run: |
33 | shopt -s globstar
34 | for file in **/*.nupkg
35 | do
36 | dotnet nuget push "$file" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
37 | done
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudio,visualstudiocode,intellij,intellij+all,rider,angular,dotnetcore,aspnetcore,xamarinstudio
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows,linux,macos,visualstudio,visualstudiocode,intellij,intellij+all,rider,angular,dotnetcore,aspnetcore,xamarinstudio
4 |
5 | ### Angular ###
6 | ## Angular ##
7 | # compiled output
8 | dist/
9 | tmp/
10 | app/**/*.js
11 | app/**/*.js.map
12 |
13 | # dependencies
14 | node_modules/
15 | bower_components/
16 |
17 | # IDEs and editors
18 | .idea/
19 |
20 | # misc
21 | .sass-cache/
22 | connect.lock/
23 | coverage/
24 | libpeerconnection.log/
25 | npm-debug.log
26 | testem.log
27 | typings/
28 | .angular/
29 |
30 | # e2e
31 | e2e/*.js
32 | e2e/*.map
33 |
34 | # System Files
35 | .DS_Store/
36 |
37 | ### ASPNETCore ###
38 | ## Ignore Visual Studio temporary files, build results, and
39 | ## files generated by popular Visual Studio add-ons.
40 |
41 | # User-specific files
42 | *.suo
43 | *.user
44 | *.userosscache
45 | *.sln.docstates
46 |
47 | # User-specific files (MonoDevelop/Xamarin Studio)
48 | *.userprefs
49 |
50 | # Build results
51 | [Dd]ebug/
52 | [Dd]ebugPublic/
53 | [Rr]elease/
54 | [Rr]eleases/
55 | x64/
56 | x86/
57 | bld/
58 | [Bb]in/
59 | [Oo]bj/
60 | [Ll]og/
61 |
62 | # Visual Studio 2015 cache/options directory
63 | .vs/
64 | # Uncomment if you have tasks that create the project's static files in wwwroot
65 | #wwwroot/
66 |
67 | # MSTest test Results
68 | [Tt]est[Rr]esult*/
69 | [Bb]uild[Ll]og.*
70 |
71 | # NUNIT
72 | *.VisualState.xml
73 | TestResult.xml
74 |
75 | # Build Results of an ATL Project
76 | [Dd]ebugPS/
77 | [Rr]eleasePS/
78 | dlldata.c
79 |
80 | # DNX
81 | project.lock.json
82 | project.fragment.lock.json
83 | artifacts/
84 |
85 | *_i.c
86 | *_p.c
87 | *_i.h
88 | *.ilk
89 | *.meta
90 | *.obj
91 | *.pch
92 | *.pdb
93 | *.pgc
94 | *.pgd
95 | *.rsp
96 | *.sbr
97 | *.tlb
98 | *.tli
99 | *.tlh
100 | *.tmp
101 | *.tmp_proj
102 | *.log
103 | *.vspscc
104 | *.vssscc
105 | .builds
106 | *.pidb
107 | *.svclog
108 | *.scc
109 |
110 | # Chutzpah Test files
111 | _Chutzpah*
112 |
113 | # Visual C++ cache files
114 | ipch/
115 | *.aps
116 | *.ncb
117 | *.opendb
118 | *.opensdf
119 | *.sdf
120 | *.cachefile
121 | *.VC.db
122 | *.VC.VC.opendb
123 |
124 | # Visual Studio profiler
125 | *.psess
126 | *.vsp
127 | *.vspx
128 | *.sap
129 |
130 | # TFS 2012 Local Workspace
131 | $tf/
132 |
133 | # Guidance Automation Toolkit
134 | *.gpState
135 |
136 | # ReSharper is a .NET coding add-in
137 | _ReSharper*/
138 | *.[Rr]e[Ss]harper
139 | *.DotSettings.user
140 |
141 | # JustCode is a .NET coding add-in
142 | .JustCode
143 |
144 | # TeamCity is a build add-in
145 | _TeamCity*
146 |
147 | # DotCover is a Code Coverage Tool
148 | *.dotCover
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 |
165 | # Installshield output folder
166 | [Ee]xpress/
167 |
168 | # DocProject is a documentation generator add-in
169 | DocProject/buildhelp/
170 | DocProject/Help/*.HxT
171 | DocProject/Help/*.HxC
172 | DocProject/Help/*.hhc
173 | DocProject/Help/*.hhk
174 | DocProject/Help/*.hhp
175 | DocProject/Help/Html2
176 | DocProject/Help/html
177 |
178 | # Click-Once directory
179 | publish/
180 |
181 | # Publish Web Output
182 | *.[Pp]ublish.xml
183 | *.azurePubxml
184 | # TODO: Comment the next line if you want to checkin your web deploy settings
185 | # but database connection strings (with potential passwords) will be unencrypted
186 | *.pubxml
187 | *.publishproj
188 |
189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
190 | # checkin your Azure Web App publish settings, but sensitive information contained
191 | # in these scripts will be unencrypted
192 | PublishScripts/
193 |
194 | # NuGet Packages
195 | *.nupkg
196 | # The packages folder can be ignored because of Package Restore
197 | **/packages/*
198 | # except build/, which is used as an MSBuild target.
199 | !**/packages/build/
200 | # Uncomment if necessary however generally it will be regenerated when needed
201 | #!**/packages/repositories.config
202 | # NuGet v3's project.json files produces more ignoreable files
203 | *.nuget.props
204 | *.nuget.targets
205 |
206 | # Microsoft Azure Build Output
207 | csx/
208 | *.build.csdef
209 |
210 | # Microsoft Azure Emulator
211 | ecf/
212 | rcf/
213 |
214 | # Windows Store app package directories and files
215 | AppPackages/
216 | BundleArtifacts/
217 | Package.StoreAssociation.xml
218 | _pkginfo.txt
219 |
220 | # Visual Studio cache files
221 | # files ending in .cache can be ignored
222 | *.[Cc]ache
223 | # but keep track of directories ending in .cache
224 | !*.[Cc]ache/
225 |
226 | # Others
227 | ClientBin/
228 | ~$*
229 | *~
230 | *.dbmdl
231 | *.dbproj.schemaview
232 | *.jfm
233 | *.pfx
234 | *.publishsettings
235 | orleans.codegen.cs
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 |
252 | # SQL Server files
253 | *.mdf
254 | *.ldf
255 |
256 | # Business Intelligence projects
257 | *.rdl.data
258 | *.bim.layout
259 | *.bim_*.settings
260 |
261 | # Microsoft Fakes
262 | FakesAssemblies/
263 |
264 | # GhostDoc plugin setting file
265 | *.GhostDoc.xml
266 |
267 | # Node.js Tools for Visual Studio
268 | .ntvs_analysis.dat
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/
303 |
304 | ### DotnetCore ###
305 | # .NET Core build folders
306 | bin/
307 | obj/
308 |
309 | # Common node modules locations
310 | /node_modules
311 | /wwwroot/node_modules
312 |
313 | ### Intellij ###
314 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
315 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
316 |
317 | # User-specific stuff
318 | .idea/**/workspace.xml
319 | .idea/**/tasks.xml
320 | .idea/**/usage.statistics.xml
321 | .idea/**/dictionaries
322 | .idea/**/shelf
323 |
324 | # AWS User-specific
325 | .idea/**/aws.xml
326 |
327 | # Generated files
328 | .idea/**/contentModel.xml
329 |
330 | # Sensitive or high-churn files
331 | .idea/**/dataSources/
332 | .idea/**/dataSources.ids
333 | .idea/**/dataSources.local.xml
334 | .idea/**/sqlDataSources.xml
335 | .idea/**/dynamic.xml
336 | .idea/**/uiDesigner.xml
337 | .idea/**/dbnavigator.xml
338 |
339 | # Gradle
340 | .idea/**/gradle.xml
341 | .idea/**/libraries
342 |
343 | # Gradle and Maven with auto-import
344 | # When using Gradle or Maven with auto-import, you should exclude module files,
345 | # since they will be recreated, and may cause churn. Uncomment if using
346 | # auto-import.
347 | # .idea/artifacts
348 | # .idea/compiler.xml
349 | # .idea/jarRepositories.xml
350 | # .idea/modules.xml
351 | # .idea/*.iml
352 | # .idea/modules
353 | # *.iml
354 | # *.ipr
355 |
356 | # CMake
357 | cmake-build-*/
358 |
359 | # Mongo Explorer plugin
360 | .idea/**/mongoSettings.xml
361 |
362 | # File-based project format
363 | *.iws
364 |
365 | # IntelliJ
366 | out/
367 |
368 | # mpeltonen/sbt-idea plugin
369 | .idea_modules/
370 |
371 | # JIRA plugin
372 | atlassian-ide-plugin.xml
373 |
374 | # Cursive Clojure plugin
375 | .idea/replstate.xml
376 |
377 | # SonarLint plugin
378 | .idea/sonarlint/
379 |
380 | # Crashlytics plugin (for Android Studio and IntelliJ)
381 | com_crashlytics_export_strings.xml
382 | crashlytics.properties
383 | crashlytics-build.properties
384 | fabric.properties
385 |
386 | # Editor-based Rest Client
387 | .idea/httpRequests
388 |
389 | # Android studio 3.1+ serialized cache file
390 | .idea/caches/build_file_checksums.ser
391 |
392 | ### Intellij Patch ###
393 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
394 |
395 | # *.iml
396 | # modules.xml
397 | # .idea/misc.xml
398 | # *.ipr
399 |
400 | # Sonarlint plugin
401 | # https://plugins.jetbrains.com/plugin/7973-sonarlint
402 | .idea/**/sonarlint/
403 |
404 | # SonarQube Plugin
405 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
406 | .idea/**/sonarIssues.xml
407 |
408 | # Markdown Navigator plugin
409 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
410 | .idea/**/markdown-navigator.xml
411 | .idea/**/markdown-navigator-enh.xml
412 | .idea/**/markdown-navigator/
413 |
414 | # Cache file creation bug
415 | # See https://youtrack.jetbrains.com/issue/JBR-2257
416 | .idea/$CACHE_FILE$
417 |
418 | # CodeStream plugin
419 | # https://plugins.jetbrains.com/plugin/12206-codestream
420 | .idea/codestream.xml
421 |
422 | ### Intellij+all ###
423 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
424 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
425 |
426 | # User-specific stuff
427 |
428 | # AWS User-specific
429 |
430 | # Generated files
431 |
432 | # Sensitive or high-churn files
433 |
434 | # Gradle
435 |
436 | # Gradle and Maven with auto-import
437 | # When using Gradle or Maven with auto-import, you should exclude module files,
438 | # since they will be recreated, and may cause churn. Uncomment if using
439 | # auto-import.
440 | # .idea/artifacts
441 | # .idea/compiler.xml
442 | # .idea/jarRepositories.xml
443 | # .idea/modules.xml
444 | # .idea/*.iml
445 | # .idea/modules
446 | # *.iml
447 | # *.ipr
448 |
449 | # CMake
450 |
451 | # Mongo Explorer plugin
452 |
453 | # File-based project format
454 |
455 | # IntelliJ
456 |
457 | # mpeltonen/sbt-idea plugin
458 |
459 | # JIRA plugin
460 |
461 | # Cursive Clojure plugin
462 |
463 | # SonarLint plugin
464 |
465 | # Crashlytics plugin (for Android Studio and IntelliJ)
466 |
467 | # Editor-based Rest Client
468 |
469 | # Android studio 3.1+ serialized cache file
470 |
471 | ### Intellij+all Patch ###
472 | # Ignore everything but code style settings and run configurations
473 | # that are supposed to be shared within teams.
474 |
475 | .idea/*
476 |
477 | !.idea/codeStyles
478 | !.idea/runConfigurations
479 |
480 | ### Linux ###
481 |
482 | # temporary files which can be created if a process still has a handle open of a deleted file
483 | .fuse_hidden*
484 |
485 | # KDE directory preferences
486 | .directory
487 |
488 | # Linux trash folder which might appear on any partition or disk
489 | .Trash-*
490 |
491 | # .nfs files are created when an open file is removed but is still being accessed
492 | .nfs*
493 |
494 | ### macOS ###
495 | # General
496 | .DS_Store
497 | .AppleDouble
498 | .LSOverride
499 |
500 | # Icon must end with two \r
501 | Icon
502 |
503 |
504 | # Thumbnails
505 | ._*
506 |
507 | # Files that might appear in the root of a volume
508 | .DocumentRevisions-V100
509 | .fseventsd
510 | .Spotlight-V100
511 | .TemporaryItems
512 | .Trashes
513 | .VolumeIcon.icns
514 | .com.apple.timemachine.donotpresent
515 |
516 | # Directories potentially created on remote AFP share
517 | .AppleDB
518 | .AppleDesktop
519 | Network Trash Folder
520 | Temporary Items
521 | .apdisk
522 |
523 | ### Rider ###
524 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
525 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
526 |
527 | # User-specific stuff
528 |
529 | # AWS User-specific
530 |
531 | # Generated files
532 |
533 | # Sensitive or high-churn files
534 |
535 | # Gradle
536 |
537 | # Gradle and Maven with auto-import
538 | # When using Gradle or Maven with auto-import, you should exclude module files,
539 | # since they will be recreated, and may cause churn. Uncomment if using
540 | # auto-import.
541 | # .idea/artifacts
542 | # .idea/compiler.xml
543 | # .idea/jarRepositories.xml
544 | # .idea/modules.xml
545 | # .idea/*.iml
546 | # .idea/modules
547 | # *.iml
548 | # *.ipr
549 |
550 | # CMake
551 |
552 | # Mongo Explorer plugin
553 |
554 | # File-based project format
555 |
556 | # IntelliJ
557 |
558 | # mpeltonen/sbt-idea plugin
559 |
560 | # JIRA plugin
561 |
562 | # Cursive Clojure plugin
563 |
564 | # SonarLint plugin
565 |
566 | # Crashlytics plugin (for Android Studio and IntelliJ)
567 |
568 | # Editor-based Rest Client
569 |
570 | # Android studio 3.1+ serialized cache file
571 |
572 | ### VisualStudioCode ###
573 | .vscode/*
574 | !.vscode/settings.json
575 | !.vscode/tasks.json
576 | !.vscode/launch.json
577 | !.vscode/extensions.json
578 | !.vscode/*.code-snippets
579 |
580 | # Local History for Visual Studio Code
581 | .history/
582 |
583 | # Built Visual Studio Code Extensions
584 | *.vsix
585 |
586 | ### VisualStudioCode Patch ###
587 | # Ignore all local history of files
588 | .history
589 | .ionide
590 |
591 | # Support for Project snippet scope
592 |
593 | ### Windows ###
594 | # Windows thumbnail cache files
595 | Thumbs.db
596 | Thumbs.db:encryptable
597 | ehthumbs.db
598 | ehthumbs_vista.db
599 |
600 | # Dump file
601 | *.stackdump
602 |
603 | # Folder config file
604 | [Dd]esktop.ini
605 |
606 | # Recycle Bin used on file shares
607 | $RECYCLE.BIN/
608 |
609 | # Windows Installer files
610 | *.cab
611 | *.msi
612 | *.msix
613 | *.msm
614 | *.msp
615 |
616 | # Windows shortcuts
617 | *.lnk
618 |
619 | ### XamarinStudio ###
620 | .packages
621 |
622 | ### VisualStudio ###
623 | ##
624 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
625 |
626 | # User-specific files
627 | *.rsuser
628 |
629 | # User-specific files (MonoDevelop/Xamarin Studio)
630 |
631 | # Mono auto generated files
632 | mono_crash.*
633 |
634 | # Build results
635 | [Ww][Ii][Nn]32/
636 | [Aa][Rr][Mm]/
637 | [Aa][Rr][Mm]64/
638 | [Ll]ogs/
639 |
640 | # Visual Studio 2015/2017 cache/options directory
641 | # Uncomment if you have tasks that create the project's static files in wwwroot
642 |
643 | # Visual Studio 2017 auto generated files
644 | Generated\ Files/
645 |
646 | # MSTest test Results
647 |
648 | # NUnit
649 | nunit-*.xml
650 |
651 | # Build Results of an ATL Project
652 |
653 | # Benchmark Results
654 | BenchmarkDotNet.Artifacts/
655 |
656 | # .NET Core
657 |
658 | # ASP.NET Scaffolding
659 | ScaffoldingReadMe.txt
660 |
661 | # StyleCop
662 | StyleCopReport.xml
663 |
664 | # Files built by Visual Studio
665 | *_h.h
666 | *.iobj
667 | *.ipdb
668 | *_wpftmp.csproj
669 | *.tlog
670 |
671 | # Chutzpah Test files
672 |
673 | # Visual C++ cache files
674 |
675 | # Visual Studio profiler
676 |
677 | # Visual Studio Trace Files
678 | *.e2e
679 |
680 | # TFS 2012 Local Workspace
681 |
682 | # Guidance Automation Toolkit
683 |
684 | # ReSharper is a .NET coding add-in
685 |
686 | # TeamCity is a build add-in
687 |
688 | # DotCover is a Code Coverage Tool
689 |
690 | # AxoCover is a Code Coverage Tool
691 | .axoCover/*
692 | !.axoCover/settings.json
693 |
694 | # Coverlet is a free, cross platform Code Coverage Tool
695 | coverage*.json
696 | coverage*.xml
697 | coverage*.info
698 |
699 | # Visual Studio code coverage results
700 |
701 | # NCrunch
702 |
703 | # MightyMoose
704 |
705 | # Web workbench (sass)
706 |
707 | # Installshield output folder
708 |
709 | # DocProject is a documentation generator add-in
710 |
711 | # Click-Once directory
712 |
713 | # Publish Web Output
714 | # Note: Comment the next line if you want to checkin your web deploy settings,
715 | # but database connection strings (with potential passwords) will be unencrypted
716 |
717 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
718 | # checkin your Azure Web App publish settings, but sensitive information contained
719 | # in these scripts will be unencrypted
720 |
721 | # NuGet Packages
722 | # NuGet Symbol Packages
723 | *.snupkg
724 | # The packages folder can be ignored because of Package Restore
725 | **/[Pp]ackages/*
726 | # except build/, which is used as an MSBuild target.
727 | !**/[Pp]ackages/build/
728 | # Uncomment if necessary however generally it will be regenerated when needed
729 | #!**/[Pp]ackages/repositories.config
730 | # NuGet v3's project.json files produces more ignorable files
731 |
732 | # Microsoft Azure Build Output
733 |
734 | # Microsoft Azure Emulator
735 |
736 | # Windows Store app package directories and files
737 | *.appx
738 | *.appxbundle
739 | *.appxupload
740 |
741 | # Visual Studio cache files
742 | # files ending in .cache can be ignored
743 | # but keep track of directories ending in .cache
744 | !?*.[Cc]ache/
745 |
746 | # Others
747 |
748 | # Including strong name files can present a security risk
749 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
750 | #*.snk
751 |
752 | # Since there are multiple workflows, uncomment next line to ignore bower_components
753 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
754 |
755 | # RIA/Silverlight projects
756 |
757 | # Backup & report files from converting an old project file
758 | # to a newer Visual Studio version. Backup files are not needed,
759 | # because we have git ;-)
760 | ServiceFabricBackup/
761 | *.rptproj.bak
762 |
763 | # SQL Server files
764 | *.ndf
765 |
766 | # Business Intelligence projects
767 | *.rptproj.rsuser
768 | *- [Bb]ackup.rdl
769 | *- [Bb]ackup ([0-9]).rdl
770 | *- [Bb]ackup ([0-9][0-9]).rdl
771 |
772 | # Microsoft Fakes
773 |
774 | # GhostDoc plugin setting file
775 |
776 | # Node.js Tools for Visual Studio
777 |
778 | # Visual Studio 6 build log
779 |
780 | # Visual Studio 6 workspace options file
781 |
782 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
783 | *.vbw
784 |
785 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
786 | *.vbp
787 |
788 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
789 | *.dsw
790 | *.dsp
791 |
792 | # Visual Studio 6 technical files
793 |
794 | # Visual Studio LightSwitch build output
795 |
796 | # Paket dependency manager
797 |
798 | # FAKE - F# Make
799 |
800 | # CodeRush personal settings
801 | .cr/personal
802 |
803 | # Python Tools for Visual Studio (PTVS)
804 |
805 | # Cake - Uncomment if you are using it
806 | # tools/**
807 | # !tools/packages.config
808 |
809 | # Tabs Studio
810 | *.tss
811 |
812 | # Telerik's JustMock configuration file
813 | *.jmconfig
814 |
815 | # BizTalk build output
816 | *.btp.cs
817 | *.btm.cs
818 | *.odx.cs
819 | *.xsd.cs
820 |
821 | # OpenCover UI analysis results
822 | OpenCover/
823 |
824 | # Azure Stream Analytics local run output
825 | ASALocalRun/
826 |
827 | # MSBuild Binary and Structured Log
828 | *.binlog
829 |
830 | # NVidia Nsight GPU debugger configuration file
831 | *.nvuser
832 |
833 | # MFractors (Xamarin productivity tool) working folder
834 | .mfractor/
835 |
836 | # Local History for Visual Studio
837 | .localhistory/
838 |
839 | # Visual Studio History (VSHistory) files
840 | .vshistory/
841 |
842 | # BeatPulse healthcheck temp database
843 | healthchecksdb
844 |
845 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
846 | MigrationBackup/
847 |
848 | # Ionide (cross platform F# VS Code tools) working folder
849 | .ionide/
850 |
851 | # Fody - auto-generated XML schema
852 | FodyWeavers.xsd
853 |
854 | # VS Code files for those working on multiple tools
855 | *.code-workspace
856 |
857 | # Local History for Visual Studio Code
858 |
859 | # Windows Installer files from build outputs
860 |
861 | # JetBrains Rider
862 |
863 | ### VisualStudio Patch ###
864 | # Additional files built by Visual Studio
865 |
866 | # End of https://www.toptal.com/developers/gitignore/api/windows,linux,macos,visualstudio,visualstudiocode,intellij,intellij+all,rider,angular,dotnetcore,aspnetcore,xamarinstudio
867 |
868 |
869 |
870 | # Ignore fields
871 | ManagedCode.OpenAI.Client.Experiments/
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ManagedCode
5 | Copyright © 2021-$([System.DateTime]::Now.ToString(`yyyy`)) ManagedCode SAS
6 | true
7 | true
8 | true
9 | snupkg
10 | Github
11 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
12 | logo.png
13 | MIT
14 | true
15 | README.md
16 |
17 | https://github.com/managedcode/OpenAI
18 | https://github.com/managedcode/OpenAI
19 | Managed Code - OpenAI
20 | 0.0.5
21 | 0.0.5
22 |
23 |
24 |
25 | true
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | all
34 | runtime; build; native; contentfiles; analyzers; buildtransitive
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Managed-Code
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Architecture/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Tests.Architecture
2 | {
3 | internal static class Constants
4 | {
5 | public const string TestSettingsFilePath = "testsettings.json";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Architecture/IntegrationTestsRuntime.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Tests.Extensions;
2 | using Microsoft.Extensions.Configuration;
3 |
4 | namespace ManagedCode.OpenAI.Tests.Architecture
5 | {
6 | internal class IntegrationTestsRuntime
7 | {
8 | private static IntegrationTestsRuntime? _default;
9 |
10 | private IntegrationTestsRuntime()
11 | {
12 | var builder = new ConfigurationBuilder();
13 | builder.AddJsonFile(Constants.TestSettingsFilePath);
14 | var configuration = builder.Build();
15 | IsManualTestsEnabled = !string.IsNullOrWhiteSpace(configuration.OpenAIApiKey());
16 | }
17 |
18 | public static IntegrationTestsRuntime Default => _default
19 | ??= new IntegrationTestsRuntime();
20 |
21 | public bool IsManualTestsEnabled { get; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Attributes/ManualTestAttribute.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Tests.Architecture;
2 | using Xunit;
3 |
4 | namespace ManagedCode.OpenAI.Tests.Attributes
5 | {
6 | public class ManualTestAttribute : FactAttribute
7 | {
8 | public ManualTestAttribute()
9 | {
10 | if (!IntegrationTestsRuntime.Default.IsManualTestsEnabled)
11 | {
12 | Skip = "Test Disabled";
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Base/BaseTestClass.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Tests.Extensions;
2 | using ManagedCode.OpenAI.Tests.Services;
3 | using Microsoft.Extensions.Configuration;
4 | using Xunit.Abstractions;
5 |
6 | namespace ManagedCode.OpenAI.Tests.Base
7 | {
8 | public class BaseTestClass
9 | {
10 | public BaseTestClass(ITestOutputHelper output, IConfiguration configuration)
11 | {
12 | Output = output;
13 | ClientBuilder = new TestGptClientBuilder(configuration.OpenAIApiKey(),
14 | configuration.IsUseOpenAIWebClientMock());
15 | }
16 |
17 | public ITestOutputHelper Output { get; }
18 | internal ITestGptClientBuilder ClientBuilder { get; }
19 |
20 | protected void Log(string message)
21 | {
22 | Output.WriteLine(message);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/ChatTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Chat;
3 | using ManagedCode.OpenAI.Client;
4 | using ManagedCode.OpenAI.Tests.Attributes;
5 | using ManagedCode.OpenAI.Tests.Base;
6 | using Microsoft.Extensions.Configuration;
7 | using Xunit.Abstractions;
8 |
9 | namespace ManagedCode.OpenAI.Tests;
10 |
11 | public class ChatTests: BaseTestClass
12 | {
13 | public ChatTests(ITestOutputHelper output, IConfiguration configuration)
14 | : base(output, configuration)
15 | {
16 | }
17 |
18 |
19 | [ManualTest]
20 | public async Task AskSingle_Success()
21 | {
22 | var client = ClientBuilder.Build();
23 |
24 | var chat = client.OpenChat();
25 | var question1 = "Distance to the sun?";
26 | var question2 = "Why so far?";
27 |
28 | Log($"Question: '{question1}'");
29 | var answer1 = await chat.AskAsync(question1);
30 | Log($"Answer: '{answer1.Data.Content}'");
31 |
32 | Log($"Question: '{question2}'");
33 | var answer2 = await chat.AskAsync(question2);
34 | Log($"Answer: '{answer2.Data.Content}'");
35 |
36 | answer1.Data.Content.Should().NotBeNullOrWhiteSpace();
37 | answer2.Data.Content.Should().NotBeNullOrWhiteSpace();
38 | }
39 |
40 | [ManualTest]
41 | public async Task AskMultiple_Success()
42 | {
43 | var client = ClientBuilder.Build();
44 | var chat = client.OpenChat();
45 | var question = "Distance to the sun?";
46 |
47 | Log($"Question: '{question}'");
48 | var answer = await chat.AskMultipleAsync(question, 3);
49 |
50 | foreach (var chatMessage in answer.Data)
51 | {
52 | Log($"Answer: '{chatMessage.Content}'");
53 | chatMessage.Content.Should().NotBeNullOrWhiteSpace();
54 | }
55 | }
56 |
57 |
58 | [ManualTest]
59 | public async Task ChatSessionSaveLoad_Success()
60 | {
61 | var client = ClientBuilder.Build();
62 | var chat = client.OpenChat();
63 | var question = "Distance to the sun?";
64 |
65 | await chat.AskAsync(question);
66 | var sessionJson = chat.Session.ToJson();
67 | Log($"Session json: '{sessionJson}'");
68 |
69 | var newChat = client.OpenChat(x => x.FromJson(sessionJson));
70 | var loadedSessionJson = newChat.Session.ToJson();
71 | Log($"Loaded session json: '{loadedSessionJson}'");
72 |
73 | sessionJson.Should().BeEquivalentTo(loadedSessionJson);
74 | }
75 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/CommonTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Client;
3 | using ManagedCode.OpenAI.Extensions;
4 | using Xunit;
5 | using Xunit.Abstractions;
6 |
7 | namespace ManagedCode.OpenAI.Tests;
8 |
9 | public class CommonTests
10 | {
11 | private readonly ITestOutputHelper _output;
12 |
13 |
14 | public CommonTests(ITestOutputHelper output)
15 | {
16 | _output = output;
17 | }
18 |
19 | [Fact]
20 | public async Task UploadFile_Success()
21 | {
22 | var enumValue = GptModel.Gpt40613;
23 | var enumName = enumValue.Name(); // Enum.GetName(enumValue);
24 | enumName.Should().Be("gpt-4-0613");
25 | }
26 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/CompletionTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Tests.Attributes;
3 | using ManagedCode.OpenAI.Tests.Base;
4 | using Microsoft.Extensions.Configuration;
5 | using Xunit.Abstractions;
6 |
7 | namespace ManagedCode.OpenAI.Tests
8 | {
9 | public class CompletionTests : BaseTestClass
10 | {
11 | public CompletionTests(ITestOutputHelper output, IConfiguration configuration)
12 | : base(output, configuration)
13 | {
14 | }
15 |
16 | [ManualTest]
17 | public async Task CreateCompletion_Success()
18 | {
19 | var client = ClientBuilder.Build();
20 | var result = await client
21 | .Completion("Say this is a test")
22 | .ExecuteAsync();
23 |
24 | result.Data.Content.Should().NotBeNullOrWhiteSpace();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/EditTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Tests.Attributes;
3 | using ManagedCode.OpenAI.Tests.Base;
4 | using Microsoft.Extensions.Configuration;
5 | using Xunit.Abstractions;
6 |
7 | namespace ManagedCode.OpenAI.Tests
8 | {
9 | public class EditTests: BaseTestClass
10 | {
11 | public EditTests(ITestOutputHelper output, IConfiguration configuration)
12 | : base(output, configuration)
13 | {
14 | }
15 |
16 | [ManualTest]
17 | public async Task EditMessage_Success()
18 | {
19 | var client = ClientBuilder.Build();
20 | var result = await client.Edit($"AABBAADD",
21 | "Remove all 'A' symbols from string")
22 | .ExecuteAsync();
23 |
24 | result.Data.Content.Trim().Should().BeEquivalentTo("BBDD");
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Extensions/ConfigurationExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace ManagedCode.OpenAI.Tests.Extensions
4 | {
5 | public static class ConfigurationExtensions
6 | {
7 | public static bool IsUseOpenAIWebClientMock(this IConfiguration configuration)
8 | {
9 | return configuration.GetValue("IsUseOpenAIWebClientMock");
10 | }
11 |
12 | public static string OpenAIApiKey(this IConfiguration configuration)
13 | {
14 | return configuration.GetValue("OpenAIKey");
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Extensions/GenericTypeExtensions.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace ManagedCode.OpenAI.Tests.Extensions
4 | {
5 | public static class GenericTypeExtensions
6 | {
7 | public static bool Is(this T val1, T val2)
8 | where T: IEquatable
9 | {
10 | return EqualityComparer.Default.Equals(val1, val2);
11 | }
12 |
13 | public static string ToJson(this TModel model)
14 | where TModel:class
15 | {
16 | return JsonConvert.SerializeObject(model, Formatting.Indented);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Extensions/MockExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Client;
3 | using Moq;
4 |
5 | namespace ManagedCode.OpenAI.Tests.Extensions
6 | {
7 | internal static class MockExtensions
8 | {
9 | public static IGptClient Client(this Mock webClient)
10 | {
11 | throw new NullReferenceException();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/ImageTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Image;
3 | using ManagedCode.OpenAI.Tests.Attributes;
4 | using ManagedCode.OpenAI.Tests.Base;
5 | using ManagedCode.OpenAI.Tests.Properties;
6 | using Microsoft.Extensions.Configuration;
7 | using Xunit.Abstractions;
8 |
9 | namespace ManagedCode.OpenAI.Tests;
10 |
11 | public class ImageTests: BaseTestClass
12 | {
13 | public ImageTests(ITestOutputHelper output, IConfiguration configuration)
14 | : base(output, configuration)
15 | {
16 | }
17 |
18 |
19 | [ManualTest]
20 | public async Task GenerateImage_Success()
21 | {
22 | var client = ClientBuilder.Build();
23 | var image = await client.ImageClient.GenerateImage("Red dragon")
24 | .SetImageResolution(ImageResolution._512x512).ExecuteAsync();
25 |
26 | Log($"Image url: {image.Content}");
27 | image.Content.Should().NotBeNullOrWhiteSpace();
28 | }
29 |
30 | [ManualTest]
31 | public async Task GenerateImageMultiple_Success()
32 | {
33 | var client = ClientBuilder.Build();
34 | var result = await client.ImageClient
35 | .GenerateImage("Red dragon")
36 | .SetImageResolution(ImageResolution._512x512)
37 | .ExecuteMultipleAsync(2);
38 |
39 | result.Content.Should().HaveCount(2);
40 | foreach (var image in result.Content)
41 | {
42 | Log($"Image url: {image}");
43 | image.Should().NotBeNullOrWhiteSpace();
44 | }
45 | }
46 |
47 |
48 | [ManualTest]
49 | public async Task EditImage_Success()
50 | {
51 | var client = ClientBuilder.Build();
52 | var edited = await client
53 | .ImageClient.EditImage("change color to blue",
54 | x => x.FromBytes(Resources.Dog))
55 | .AsUrl()
56 | .ExecuteAsync();
57 |
58 | Log($"Edited image url: {edited.Content}");
59 | edited.Content.Should().NotBeNullOrWhiteSpace();
60 | }
61 |
62 | [ManualTest]
63 | public async Task EditImageMultiple_Success()
64 | {
65 | var client = ClientBuilder.Build();
66 | var edited = await client
67 | .ImageClient.EditImage("change color to blue",
68 | x => x.FromBytes(Resources.Dog))
69 | .AsUrl()
70 | .ExecuteMultipleAsync(2);
71 |
72 | edited.Content.Should().HaveCount(2);
73 | foreach (var image in edited.Content)
74 | {
75 | Log($"Edited image url: {image}");
76 | image.Should().NotBeNullOrWhiteSpace();
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/ManagedCode.OpenAI.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 |
20 |
21 |
22 | all
23 | runtime; build; native; contentfiles; analyzers; buildtransitive
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | all
34 | runtime; build; native; contentfiles; analyzers; buildtransitive
35 |
36 |
37 | all
38 | runtime; build; native; contentfiles; analyzers; buildtransitive
39 |
40 |
41 | all
42 | runtime; build; native; contentfiles; analyzers; buildtransitive
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | True
53 | True
54 | Resources.resx
55 |
56 |
57 |
58 |
59 |
60 | ResXFileCodeGenerator
61 | Resources.Designer.cs
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/ModelsTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.API.Errors;
3 | using ManagedCode.OpenAI.Extensions;
4 | using ManagedCode.OpenAI.Tests.Attributes;
5 | using ManagedCode.OpenAI.Tests.Base;
6 | using ManagedCode.OpenAI.Tests.Extensions;
7 | using Microsoft.Extensions.Configuration;
8 | using Xunit.Abstractions;
9 |
10 | namespace ManagedCode.OpenAI.Tests
11 | {
12 | public class ModelsTests : BaseTestClass
13 | {
14 | public ModelsTests(ITestOutputHelper output, IConfiguration configuration)
15 | : base(output, configuration)
16 | {
17 |
18 | }
19 |
20 | [ManualTest]
21 | public async Task GetModel_ModelNotFoundException()
22 | {
23 | var modelName = "WRONG_MODEL_NAME";
24 | var client = ClientBuilder.Build();
25 |
26 | await client.Invoking(async x => await x.GetModelAsync(modelName))
27 | .Should().ThrowAsync()
28 | .Where(x => x.ErrorCode
29 | .Is(OpenAIErrorCode.ModelNotFound.Name()));
30 | }
31 |
32 | [ManualTest]
33 | public async Task GetModel_Success()
34 | {
35 | var modelName = "babbage";
36 | var client = ClientBuilder.Build();
37 | var model = await client.GetModelAsync(modelName);
38 | model.Id.Should().Be(modelName);
39 | }
40 |
41 | [ManualTest]
42 | public async Task GetModels_Success()
43 | {
44 | var expectedModels = new[] { "babbage", "davinci", "text-davinci-edit-001" };
45 | var client = ClientBuilder.Build();
46 |
47 | var models = await client.GetModelsAsync();
48 | models.Select(x => x.Id).ToList().Should()
49 | .Contain(expectedModels);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/ModerationTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using ManagedCode.OpenAI.Tests.Attributes;
3 | using ManagedCode.OpenAI.Tests.Base;
4 | using ManagedCode.OpenAI.Tests.Extensions;
5 | using Microsoft.Extensions.Configuration;
6 | using Xunit.Abstractions;
7 |
8 | namespace ManagedCode.OpenAI.Tests;
9 |
10 | public class ModerationTests : BaseTestClass
11 | {
12 |
13 | public ModerationTests(ITestOutputHelper output, IConfiguration configuration)
14 | : base(output, configuration)
15 | {
16 | }
17 |
18 | [ManualTest]
19 | public async Task CreateModeration_Success()
20 | {
21 | var client = ClientBuilder.Build();
22 |
23 | var moderation = await client.Moderation().ExecuteAsync("I kill you");
24 |
25 | //assert
26 | moderation.Categories.Violence.Should().BeTrue();
27 | moderation.Should().NotBeNull();
28 | moderation.Categories.Should().NotBeNull();
29 | moderation.CategoryScores.Should().NotBeNull();
30 |
31 | Log($"Moderation content: {Environment.NewLine}{moderation.ToJson()}");
32 | }
33 |
34 | [ManualTest]
35 | public async Task CreateMultipleModeration_Success()
36 | {
37 | var client = ClientBuilder.Build();
38 |
39 | var moderationItems = await client.Moderation()
40 | .ExecuteMultipleAsync("I kill you", "You must die");
41 |
42 |
43 | //assert
44 | moderationItems.Should().NotBeNull().And.HaveCount(2);
45 | foreach (var moderation in moderationItems)
46 | moderation.Categories.Violence.Should().BeTrue();
47 |
48 | Log($"Moderation content: {Environment.NewLine}{moderationItems.ToJson()}");
49 | }
50 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | namespace ManagedCode.OpenAI.Tests.Properties {
11 | using System;
12 |
13 |
14 | [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
15 | [System.Diagnostics.DebuggerNonUserCodeAttribute()]
16 | [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
17 | internal class Resources {
18 |
19 | private static System.Resources.ResourceManager resourceMan;
20 |
21 | private static System.Globalization.CultureInfo resourceCulture;
22 |
23 | [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
24 | internal Resources() {
25 | }
26 |
27 | [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
28 | internal static System.Resources.ResourceManager ResourceManager {
29 | get {
30 | if (object.Equals(null, resourceMan)) {
31 | System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ManagedCode.OpenAI.Tests.Properties.Resources", typeof(Resources).Assembly);
32 | resourceMan = temp;
33 | }
34 | return resourceMan;
35 | }
36 | }
37 |
38 | [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static System.Globalization.CultureInfo Culture {
40 | get {
41 | return resourceCulture;
42 | }
43 | set {
44 | resourceCulture = value;
45 | }
46 | }
47 |
48 | internal static byte[] Dog {
49 | get {
50 | object obj = ResourceManager.GetObject("Dog", resourceCulture);
51 | return ((byte[])(obj));
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | text/microsoft-resx
112 |
113 |
114 | 2.0
115 |
116 |
117 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
118 | PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
123 | PublicKeyToken=b77a5c561934e089
124 |
125 |
126 |
128 |
129 | ..\Resources\dog.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral,
130 | PublicKeyToken=b77a5c561934e089
131 |
132 |
133 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Resources/dog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcode/OpenAI/1418997288050139d499bc1f36b24575227b8f24/ManagedCode.OpenAI.Tests/Resources/dog.png
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Services/TestGptClientBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Client;
3 | using Moq;
4 |
5 | namespace ManagedCode.OpenAI.Tests.Services
6 | {
7 | internal interface ITestGptClientBuilder : IGptClientBuilder
8 | {
9 | public ITestGptClientBuilder ConfigureMockWebClient(Action> mock);
10 | }
11 |
12 | internal class TestGptClientBuilder : GptClientBuilder, ITestGptClientBuilder
13 | {
14 | private Action>? _mockConfiguration;
15 |
16 | public TestGptClientBuilder(string apiKey, bool useWebMockClient) : base(apiKey)
17 | {
18 | IsUseWebMockClient = useWebMockClient;
19 | }
20 |
21 | protected bool IsUseWebMockClient { get; }
22 |
23 | public ITestGptClientBuilder ConfigureMockWebClient(Action> mock)
24 | {
25 | _mockConfiguration = mock;
26 | return this;
27 | }
28 |
29 | public override GptClient Build()
30 | {
31 | if (IsUseWebMockClient && _mockConfiguration != null)
32 | {
33 | var mock = new Mock();
34 | _mockConfiguration.Invoke(mock);
35 | return new GptClient(Configuration, mock.Object);
36 | }
37 |
38 | return base.Build();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Configuration;
3 | using ManagedCode.OpenAI.Tests.Architecture;
4 | using ManagedCode.OpenAI.Tests.Services;
5 |
6 | namespace ManagedCode.OpenAI.Tests
7 | {
8 | public class Startup
9 | {
10 | public void ConfigureServices(IServiceCollection services)
11 | {
12 | AddConfiguration(services);
13 | services.AddScoped();
14 | }
15 |
16 | private void AddConfiguration(IServiceCollection services)
17 | {
18 | var builder = new ConfigurationBuilder();
19 | builder.AddJsonFile(Constants.TestSettingsFilePath);
20 | var configuration = builder.Build();
21 |
22 | services.AddSingleton(x => configuration);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.Tests/testsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "OpenAIKey": "",
3 | "IsUseOpenAIWebClientMock": "false"
4 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedCode.OpenAI", "ManagedCode.OpenAI\ManagedCode.OpenAI.csproj", "{8A870C9E-7641-4546-B7B2-9FEE0445A76C}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedCode.OpenAI.Tests", "ManagedCode.OpenAI.Tests\ManagedCode.OpenAI.Tests.csproj", "{A9F57AEF-9EBA-405A-8B74-1B1BD2BEC70B}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {8A870C9E-7641-4546-B7B2-9FEE0445A76C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {8A870C9E-7641-4546-B7B2-9FEE0445A76C}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {8A870C9E-7641-4546-B7B2-9FEE0445A76C}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {8A870C9E-7641-4546-B7B2-9FEE0445A76C}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {A9F57AEF-9EBA-405A-8B74-1B1BD2BEC70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {A9F57AEF-9EBA-405A-8B74-1B1BD2BEC70B}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {A9F57AEF-9EBA-405A-8B74-1B1BD2BEC70B}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {A9F57AEF-9EBA-405A-8B74-1B1BD2BEC70B}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | AI
3 | True
4 | True
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Abstractions/IOpenAiWebClient.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API.Edit;
2 | using ManagedCode.OpenAI.API.File;
3 | using ManagedCode.OpenAI.API.Image;
4 | using ManagedCode.OpenAI.API.Moderation;
5 |
6 | namespace ManagedCode.OpenAI.API;
7 |
8 | internal interface IOpenAiWebClient : IDisposable
9 | {
10 | public Task ModelsAsync();
11 |
12 | public Task ModelAsync(string modelId);
13 |
14 | Task ChatAsync(ChatRequestDto request);
15 |
16 | Task CompletionsAsync(CompletionRequestDto request);
17 |
18 | Task EditAsync(EditRequestDto request);
19 |
20 | Task GenerateImageAsync(GenerateImageRequestDto request);
21 | Task EditImageAsync(EditImageRequestDto request);
22 | Task VariationImageAsync(VariationImageRequestDto request);
23 |
24 | #region Moderations
25 |
26 | Task ModerationAsync(ModerationRequestDto request);
27 |
28 | #endregion
29 |
30 | #region Files
31 |
32 | Task FilesInfoAsync();
33 | Task CreateFileAsync(string content, string fileName, string purpose = "fine-tune");
34 | Task CreateFileAsync(Stream content, string fileName, string purpose = "fine-tune");
35 | Task CreateFileAsync(byte[] content, string fileName, string purpose = "fine-tune");
36 | Task CreateFileAsync(ReadOnlyMemory content, string fileName, string purpose = "fine-tune");
37 | Task DeleteFileAsync(string fileId);
38 | Task FileInfoAsync(string fileId);
39 |
40 | // TODO: This may be a stream
41 | // I don't know what response type is returned here
42 | Task GetContentFromFileAsync(string fileId);
43 |
44 | #endregion
45 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Base/BaseCompletionsResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal abstract class BaseCompletionsResponseDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 |
13 | [JsonPropertyName("created")]
14 | public int Created { get; set; }
15 |
16 | [JsonPropertyName("model")]
17 | public string Model { get; set; }
18 |
19 | [JsonPropertyName("choices")]
20 | public List Choices { get; set; }
21 |
22 | [JsonPropertyName("usage")]
23 | public UsageDto Usage { get; set; }
24 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Chat/ChatChoiceDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class ChatChoiceDto
6 | {
7 | [JsonPropertyName("index")]
8 | public int Index { get; set; }
9 |
10 | [JsonPropertyName("message")]
11 | public MessageDto Message { get; set; }
12 |
13 | [JsonPropertyName("finish_reason")]
14 | public string FinishReason { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Chat/ChatRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class ChatRequestDto
6 | {
7 | [JsonPropertyName("model")]
8 | public required string Model { get; set; }
9 |
10 | [JsonPropertyName("messages")]
11 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
12 | public required List Messages { get; set; } = new();
13 |
14 | [JsonPropertyName("temperature")]
15 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
16 | public required float? Temperature { get; set; }
17 |
18 | [JsonPropertyName("top_p")]
19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
20 | public required float? TopP { get; set; }
21 |
22 | [JsonPropertyName("n")]
23 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
24 | public required int? N { get; set; }
25 |
26 | [JsonPropertyName("stream")]
27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
28 | public required bool? Stream { get; set; }
29 |
30 | [JsonPropertyName("max_tokens")]
31 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
32 | public required int? MaxTokens { get; set; }
33 |
34 | [JsonPropertyName("presence_penalty")]
35 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
36 | public required float? PresencePenalty { get; set; }
37 |
38 | [JsonPropertyName("frequency_penalty")]
39 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
40 | public required float? FrequencyPenalty { get; set; }
41 |
42 | [JsonPropertyName("logit_biat")]
43 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
44 | public Dictionary? LogitBias { get; set; }
45 |
46 | [JsonPropertyName("user")]
47 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
48 | public required string? User { get; set; }
49 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Chat/ChatResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.API;
2 |
3 | internal class ChatResponseDto : BaseCompletionsResponseDto
4 | {
5 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Chat/MessageDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class MessageDto
6 | {
7 | [JsonPropertyName("role")]
8 | public string Role { get; set; }
9 |
10 | [JsonPropertyName("content")]
11 | public string Content { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Chat/UsageDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class UsageDto
6 | {
7 | [JsonPropertyName("prompt_tokens")]
8 | public int PromptTokens { get; set; }
9 |
10 | [JsonPropertyName("completion_tokens")]
11 | public int CompletionTokens { get; set; }
12 |
13 | [JsonPropertyName("total_tokens")]
14 | public int TotalTokens { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Completions/CompletionChoiceDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class CompletionChoiceDto
6 | {
7 | [JsonPropertyName("text")]
8 | public string Text { get; set; }
9 |
10 | [JsonPropertyName("index")]
11 | public int Index { get; set; }
12 |
13 | [JsonPropertyName("logprobs")]
14 | public int? Logprobs { get; set; }
15 |
16 | [JsonPropertyName("finish_reason")]
17 | public string FinishReason { get; set; }
18 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Completions/CompletionRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.API;
5 |
6 | internal class CompletionRequestDto
7 | {
8 | [JsonPropertyName("model")]
9 | public string Model { get; set; }
10 |
11 | [JsonPropertyName("prompt")]
12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
13 | public List Prompt { get; set; } = new();
14 |
15 |
16 | [JsonPropertyName("suffix")]
17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
18 | public string? Suffix { get; set; }
19 |
20 | [Range(0, 2024)]
21 | [JsonPropertyName("max_tokens")]
22 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
23 | public int? MaxTokens { get; set; }
24 |
25 | [Range(0, 2f)]
26 | [JsonPropertyName("temperature")]
27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
28 | public float? Temperature { get; set; }
29 |
30 | [JsonPropertyName("top_p")]
31 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
32 | public int? TopP { get; set; }
33 |
34 | [Range(0, 10)]
35 | [JsonPropertyName("n")]
36 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
37 | public int? N { get; set; }
38 |
39 | [JsonPropertyName("stream")]
40 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
41 | public bool? Stream { get; set; }
42 |
43 | [Range(1, int.MaxValue)]
44 | [JsonPropertyName("logprobs")]
45 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
46 | public int? Logprobs { get; set; }
47 |
48 | [JsonPropertyName("echo")]
49 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
50 | public bool? Echo { get; set; }
51 |
52 | [MaxLength(4)]
53 | [JsonPropertyName("stop")]
54 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
55 | public string[]? Stop { get; set; }
56 |
57 | [Range(0, 2f)]
58 | [JsonPropertyName("presence_penalty")]
59 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
60 | public float? PresencePenalty { get; set; }
61 |
62 | [Range(-2f, 2f)]
63 | [JsonPropertyName("frequency_penalty")]
64 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
65 | public float? FrequencyPenalty { get; set; }
66 |
67 | [Range(1, int.MaxValue)]
68 | [JsonPropertyName("best_of")]
69 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
70 | public int? BestOf { get; set; }
71 |
72 | [JsonPropertyName("logit_biat")]
73 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
74 | public Dictionary? LogitBias { get; set; }
75 |
76 | [JsonPropertyName("user")]
77 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
78 | public string? User { get; set; }
79 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Completions/CompletionResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.API;
2 |
3 | internal class CompletionResponseDto : BaseCompletionsResponseDto
4 | {
5 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Edit/EditChoiceDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Edit;
4 |
5 | internal class EditChoiceDto
6 | {
7 | [JsonPropertyName("text")]
8 | public string Text { get; set; }
9 |
10 | [JsonPropertyName("index")]
11 | public int Index { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Edit/EditRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.API.Edit;
5 |
6 | internal class EditRequestDto
7 | {
8 | [JsonPropertyName("model")]
9 | public string Model { get; set; }
10 |
11 | [JsonPropertyName("input")]
12 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
13 | public string Input { get; set; }
14 |
15 | [JsonPropertyName("instruction")]
16 | public string Instruction { get; set; }
17 |
18 | [JsonPropertyName("n")]
19 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
20 | public int? Count { get; set; }
21 |
22 | [Range(0, 2f)]
23 | [JsonPropertyName("temperature")]
24 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
25 | public float? Temperature { get; set; }
26 |
27 | [JsonPropertyName("top_p")]
28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
29 | public float? TopP { get; set; }
30 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Edit/EditResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.API.Edit;
2 |
3 | internal class EditResponseDto : BaseCompletionsResponseDto
4 | {
5 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Errors/OpenAIError.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Errors;
4 |
5 | internal class OpenAIErrorResponse
6 | {
7 | [JsonPropertyName("error")]
8 | public OpenAIError Error { get; set; }
9 |
10 | }
11 |
12 | internal class OpenAIError
13 | {
14 | [JsonPropertyName("message")]
15 | public string Message { get; set; }
16 |
17 | [JsonPropertyName("type")]
18 | public string Type { get; set; }
19 |
20 | [JsonPropertyName("model")]
21 | public string Model { get; set; }
22 |
23 | [JsonPropertyName("code")]
24 | public string Code { get; set; }
25 | }
26 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Errors/OpenAIErrorCode.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Errors;
4 |
5 | public enum OpenAIErrorCode
6 | {
7 | [EnumMember(Value = "model_not_found")]
8 | ModelNotFound,
9 | }
10 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Errors/OpenAIException.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using ManagedCode.OpenAI.Extensions;
3 |
4 | namespace ManagedCode.OpenAI.API.Errors;
5 |
6 | public class OpenAIException : HttpRequestException
7 | {
8 | public OpenAIException(string message, string code, HttpStatusCode statusCode
9 | ) :
10 | base(message, null, statusCode)
11 | {
12 | ErrorCode = code;
13 | }
14 |
15 | public OpenAIException(OpenAIErrorCode errorCode)
16 | {
17 | ErrorCode = errorCode.Name();
18 | }
19 |
20 | public string ErrorCode { get; }
21 | }
22 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/File/FileDeleteResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.File;
4 |
5 | internal class FileDeleteResponseDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 |
13 | [JsonPropertyName("deleted")]
14 | public bool Deleted { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/File/FileInfoDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.File;
4 |
5 | internal class FileInfoDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 |
13 | [JsonPropertyName("bytes")]
14 | public int Bytes { get; set; }
15 |
16 | [JsonPropertyName("created_at")]
17 | public int CreatedAt { get; set; }
18 |
19 | [JsonPropertyName("filename")]
20 | public string Filename { get; set; }
21 |
22 | [JsonPropertyName("purpose")]
23 | public string Purpose { get; set; }
24 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/File/FilesInfoResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.File;
4 |
5 | internal class FilesInfoResponseDto
6 | {
7 | [JsonPropertyName("data")]
8 | public FileInfoDto[] Data { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/BaseImageRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.API.Image;
5 |
6 | internal class BaseImageRequestDto
7 | {
8 | [Range(0, 10)]
9 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
10 | [JsonPropertyName("n")]
11 | public int? N { get; set; }
12 |
13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
14 | [JsonPropertyName("size")]
15 | public string? Size { get; set; }
16 |
17 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
18 | [JsonPropertyName("response_format")]
19 | public string? ResponseFormat { get; set; }
20 |
21 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
22 | [JsonPropertyName("user")]
23 | public string? User { get; set; }
24 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/EditImageRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Image;
4 |
5 | internal class EditImageRequestDto : BaseImageRequestDto
6 | {
7 | [JsonPropertyName("prompt")]
8 | public string Description { get; set; }
9 |
10 | [JsonPropertyName("image")]
11 | public string ImageBase64 { get; set; }
12 |
13 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
14 | [JsonPropertyName("mask")]
15 | public string? MaskBase64 { get; set; }
16 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/GenerateImageRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Image;
4 |
5 | internal class GenerateImageRequestDto : BaseImageRequestDto
6 | {
7 | [JsonPropertyName("prompt")]
8 | public string Description { get; set; }
9 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/ImageResponseDataDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Image;
4 |
5 | internal class ImageResponseDataDto
6 | {
7 | [JsonPropertyName("url")]
8 | public string Url { get; set; }
9 |
10 | [JsonPropertyName("b64_json")]
11 | public string B64Json { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/ImageResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Image;
4 |
5 | internal class ImageResponseDto
6 | {
7 | [JsonPropertyName("created")]
8 | public int Created { get; set; }
9 |
10 | [JsonPropertyName("data")]
11 | public List Data { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Image/VariationImageRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Image;
4 |
5 | internal class VariationImageRequestDto : BaseImageRequestDto
6 | {
7 | [JsonPropertyName("image")]
8 | public string ImageBase64 { get; set; }
9 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Models/ModelDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class ModelDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 |
13 | [JsonPropertyName("owned_by")]
14 | public string OwnedBy { get; set; }
15 |
16 | [JsonPropertyName("permission")]
17 | public PermissionDto[] Permission { get; set; }
18 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Models/ModelsResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class ModelsResponseDto
6 | {
7 | [JsonPropertyName("data")]
8 | public ModelDto[] Models { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Models/PermissionDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API;
4 |
5 | internal class PermissionDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("object")]
11 | public string Object { get; set; }
12 |
13 | [JsonPropertyName("created")]
14 | public int Created { get; set; }
15 |
16 | [JsonPropertyName("allow_create_engine")]
17 | public bool AllowCreateEngine { get; set; }
18 |
19 | [JsonPropertyName("allow_sampling")]
20 | public bool AllowSampling { get; set; }
21 |
22 | [JsonPropertyName("allow_logprobs")]
23 | public bool AllowLogprobs { get; set; }
24 |
25 | [JsonPropertyName("allow_search_indices")]
26 | public bool AllowSearchIndices { get; set; }
27 |
28 | [JsonPropertyName("allow_view")]
29 | public bool AllowView { get; set; }
30 |
31 | [JsonPropertyName("allow_fine_tuning")]
32 | public bool AllowFineTuning { get; set; }
33 |
34 | [JsonPropertyName("organization")]
35 | public string Organization { get; set; }
36 |
37 | [JsonPropertyName("group")]
38 | public object Group { get; set; }
39 |
40 | [JsonPropertyName("is_blocking")]
41 | public bool IsBlocking { get; set; }
42 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Moderation/CategoryDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Moderation;
4 |
5 | internal class CategoryDto where TResult : struct
6 | {
7 | [JsonPropertyName("hate")]
8 | public TResult Hate { get; set; }
9 |
10 | [JsonPropertyName("hate/threatening")]
11 | public TResult HateThreatening { get; set; }
12 |
13 | [JsonPropertyName("self-harm")]
14 | public TResult SelfHarm { get; set; }
15 |
16 | [JsonPropertyName("sexual")]
17 | public TResult Sexual { get; set; }
18 |
19 | [JsonPropertyName("sexual/minors")]
20 | public TResult SexualMinors { get; set; }
21 |
22 | [JsonPropertyName("violence")]
23 | public TResult Violence { get; set; }
24 |
25 | [JsonPropertyName("violence/graphic")]
26 | public TResult ViolenceGraphic { get; set; }
27 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Moderation/CategoryResultDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Moderation;
4 |
5 | internal class CategoryResultDto
6 | {
7 | [JsonPropertyName("categories")]
8 | public CategoryDto Categories { get; set; }
9 |
10 | [JsonPropertyName("category_scores")]
11 | public CategoryDto CategoryScores { get; set; }
12 |
13 | [JsonPropertyName("flagged")]
14 | public bool Flagged { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Moderation/ModerationRequestDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Moderation;
4 |
5 | internal class ModerationRequestDto
6 | {
7 | [JsonPropertyName("input")]
8 | public List Input { get; set; } = new();
9 |
10 | [JsonPropertyName("model")]
11 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
12 | public string Model { get; set; }
13 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/Moderation/ModerationResponseDto.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.API.Moderation;
4 |
5 | internal class ModerationResponseDto
6 | {
7 | [JsonPropertyName("id")]
8 | public string Id { get; set; }
9 |
10 | [JsonPropertyName("model")]
11 | public string Model { get; set; }
12 |
13 | [JsonPropertyName("results")]
14 | public CategoryResultDto[] Results { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/API/OpenAIWebClient.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Http.Json;
2 | using System.Text.Json;
3 | using ManagedCode.OpenAI.API.Edit;
4 | using ManagedCode.OpenAI.API.Errors;
5 | using ManagedCode.OpenAI.API.File;
6 | using ManagedCode.OpenAI.API.Image;
7 | using ManagedCode.OpenAI.API.Moderation;
8 |
9 | namespace ManagedCode.OpenAI.API;
10 |
11 | internal class OpenAiWebClient : IOpenAiWebClient
12 | {
13 | private const string AUTHORIZATION = "Authorization";
14 | private const string AUTHORIZATION_FORMAT = "Bearer {0}";
15 | private const string ORGANIZATION = "OpenAI-Organization";
16 | private const string URL_BASE = "https://api.openai.com/v1/";
17 | private const string URL_LIST_MODELS = "models";
18 | private const string URL_MODEL = "models/{0}";
19 | private const string URL_CHAT_COMPLETIONS = "chat/completions";
20 | private const string URL_COMPLETIONS = "completions";
21 | private const string URL_EDITS = "edits";
22 | private const string URL_IMAGE_GENERATION = "images/generations";
23 | private const string URL_IMAGE_EDIT = "images/edits";
24 | private const string URL_IMAGE_VARIATION = "images/variations";
25 | private const string URL_FILES = "files";
26 | private const string URL_FILE = "files/{0}";
27 | private const string URL_FILE_CONTEXT = "files/{0}/content";
28 |
29 | private const string URL_MODERATION = "moderations";
30 |
31 |
32 | private readonly HttpClient _httpClient;
33 |
34 | public OpenAiWebClient(string apiKey)
35 | {
36 | _httpClient = new HttpClient();
37 | _httpClient.DefaultRequestHeaders.Add(AUTHORIZATION,
38 | string.Format(AUTHORIZATION_FORMAT, apiKey));
39 |
40 | _httpClient.BaseAddress = new Uri(URL_BASE);
41 | }
42 |
43 | public OpenAiWebClient(string apiKey, string organization)
44 | {
45 | _httpClient = new HttpClient();
46 | _httpClient.DefaultRequestHeaders.Add(AUTHORIZATION,
47 | string.Format(AUTHORIZATION_FORMAT, apiKey));
48 |
49 | _httpClient.DefaultRequestHeaders.Add(ORGANIZATION, organization);
50 | _httpClient.BaseAddress = new Uri(URL_BASE);
51 | }
52 |
53 |
54 | public async Task ModelsAsync()
55 | {
56 | var httpResponseMessage = await _httpClient.GetAsync(URL_LIST_MODELS);
57 | return await ReadAsync(httpResponseMessage);
58 | }
59 |
60 | public async Task ModelAsync(string modelId)
61 | {
62 | var httpResponseMessage = await _httpClient.GetAsync(
63 | string.Format(URL_MODEL, modelId.Trim()));
64 | return await ReadAsync(httpResponseMessage);
65 | }
66 |
67 | public async Task ChatAsync(ChatRequestDto request)
68 | {
69 | var response = await _httpClient.PostAsJsonAsync(URL_CHAT_COMPLETIONS, request);
70 | return await ReadAsync(response);
71 | }
72 |
73 | public async Task CompletionsAsync(CompletionRequestDto request)
74 | {
75 | var response = await _httpClient.PostAsJsonAsync(URL_COMPLETIONS, request);
76 | return await ReadAsync(response);
77 | }
78 |
79 | public async Task EditAsync(EditRequestDto request)
80 | {
81 | var response = await _httpClient.PostAsJsonAsync(URL_EDITS, request);
82 | return await ReadAsync(response);
83 | }
84 |
85 | public async Task GenerateImageAsync(GenerateImageRequestDto request)
86 | {
87 | var response = await _httpClient.PostAsJsonAsync(URL_IMAGE_GENERATION, request);
88 | return await ReadAsync(response);
89 | }
90 |
91 | public async Task EditImageAsync(EditImageRequestDto request)
92 | {
93 | var imageBytes = Convert.FromBase64String(request.ImageBase64);
94 | var parameters = ToImageRequestParameters(request);
95 | using var form = new MultipartFormDataContent();
96 |
97 | foreach (var parameter in parameters)
98 | form.Add(parameter.Key, parameter.Value);
99 |
100 | form.Add(new StreamContent(new MemoryStream(imageBytes)), "image", "image.png");
101 |
102 | if (!string.IsNullOrWhiteSpace(request.MaskBase64))
103 | {
104 | var maskBytes = Convert.FromBase64String(request.MaskBase64);
105 | form.Add(new StreamContent(new MemoryStream(maskBytes)), "mask", "mask.png");
106 | }
107 |
108 | form.Add(new StringContent(request.Description), "prompt");
109 |
110 | var response = await _httpClient.PostAsync(URL_IMAGE_EDIT, form);
111 | return await ReadAsync(response);
112 | }
113 |
114 | public async Task VariationImageAsync(VariationImageRequestDto request)
115 | {
116 | var imageBytes = Convert.FromBase64String(request.ImageBase64);
117 |
118 | var parameters = ToImageRequestParameters(request);
119 | using var form = new MultipartFormDataContent();
120 |
121 | foreach (var parameter in parameters)
122 | form.Add(parameter.Key, parameter.Value);
123 |
124 | form.Add(new ByteArrayContent(imageBytes), "image", "image.png");
125 |
126 | var response = await _httpClient.PostAsync(URL_IMAGE_VARIATION, form);
127 | return await ReadAsync(response);
128 | }
129 |
130 | public void Dispose()
131 | {
132 | _httpClient.Dispose();
133 | }
134 |
135 | #region Moderations
136 |
137 | public async Task ModerationAsync(ModerationRequestDto request)
138 | {
139 | var httpResponseMessage = await _httpClient.PostAsJsonAsync(URL_MODERATION, request);
140 |
141 | return await ReadAsync(httpResponseMessage);
142 | }
143 |
144 | #endregion
145 |
146 | private async Task ReadAsync(HttpResponseMessage response)
147 | {
148 | if (!response.IsSuccessStatusCode)
149 | {
150 | var responseContent = await response.Content.ReadAsStringAsync();
151 | var error = JsonDeserialize(responseContent).Error;
152 | throw new OpenAIException(error.Message, error.Code, response.StatusCode);
153 | }
154 |
155 | var responseBody = await response.Content.ReadAsStringAsync();
156 | return JsonDeserialize(responseBody);
157 | }
158 |
159 | private async Task ReadAsStringAsync(HttpResponseMessage response)
160 | {
161 | if (!response.IsSuccessStatusCode)
162 | {
163 | var responseContent = await response.Content.ReadAsStringAsync();
164 | var error = JsonDeserialize(responseContent).Error;
165 | throw new OpenAIException(error.Message, error.Code, response.StatusCode);
166 | }
167 |
168 | return await response.Content.ReadAsStringAsync();
169 | }
170 |
171 | private TModel JsonDeserialize(string jsonStr)
172 | {
173 | return JsonSerializer.Deserialize(jsonStr)
174 | ?? throw new NullReferenceException();
175 | }
176 |
177 | private Dictionary ToImageRequestParameters(BaseImageRequestDto request)
178 | {
179 | var result = new Dictionary();
180 |
181 | if (!string.IsNullOrWhiteSpace(request.Size))
182 | result.Add(new StringContent(request.Size), "size");
183 |
184 | if (!string.IsNullOrWhiteSpace(request.ResponseFormat))
185 | result.Add(new StringContent(request.ResponseFormat), "response_format");
186 |
187 | if (!string.IsNullOrWhiteSpace(request.User))
188 | result.Add(new StringContent(request.User), "user");
189 |
190 | if (request.N.HasValue)
191 | result.Add(new StringContent(request.N.Value.ToString()), "n");
192 | return result;
193 | }
194 |
195 | #region Files
196 |
197 | public async Task FilesInfoAsync()
198 | {
199 | var httpResponseMessage = await _httpClient.GetAsync(URL_FILES);
200 | return await ReadAsync(httpResponseMessage);
201 | }
202 |
203 | private async Task CreateFileAsync(HttpContent content, string fileName, string purpose = "fine-tune")
204 | {
205 | MultipartFormDataContent multipartFormDataContent = new();
206 | multipartFormDataContent.Add(new StringContent(purpose), "purpose");
207 | multipartFormDataContent.Add(content, "file", fileName);
208 |
209 | var httpResponseMessage = await _httpClient.PostAsync(URL_FILES, multipartFormDataContent);
210 |
211 | return await ReadAsync(httpResponseMessage);
212 | }
213 |
214 | public async Task CreateFileAsync(Stream content, string fileName, string purpose = "fine-tune")
215 | {
216 | StreamContent streamContent = new(content);
217 | return await CreateFileAsync(streamContent, fileName, purpose);
218 | }
219 |
220 | public async Task CreateFileAsync(string content, string fileName, string purpose = "fine-tune")
221 | {
222 | StringContent stringContent = new(content);
223 | return await CreateFileAsync(stringContent, fileName, purpose);
224 | }
225 |
226 | public async Task CreateFileAsync(byte[] content, string fileName, string purpose = "fine-tune")
227 | {
228 | ByteArrayContent byteArrayContent = new(content);
229 | return await CreateFileAsync(byteArrayContent, fileName, purpose);
230 | }
231 |
232 | public async Task CreateFileAsync(ReadOnlyMemory content, string fileName, string purpose =
233 | "fine-tune")
234 | {
235 | ReadOnlyMemoryContent readOnlyMemoryContent = new(content);
236 | return await CreateFileAsync(readOnlyMemoryContent, fileName, purpose);
237 | }
238 |
239 |
240 | public async Task DeleteFileAsync(string fileId)
241 | {
242 | var resultUrl = string.Format(URL_FILE, fileId);
243 | var httpResponseMessage = await _httpClient.DeleteAsync(resultUrl);
244 |
245 | return await ReadAsync(httpResponseMessage);
246 | }
247 |
248 | public async Task FileInfoAsync(string fileId)
249 | {
250 | var resultUrl = string.Format(URL_FILE, fileId);
251 |
252 | var httpResponseMessage = await _httpClient.GetAsync(resultUrl);
253 |
254 | return await ReadAsync(httpResponseMessage);
255 | }
256 |
257 | // TODO: It is not known what the result of the query returns
258 | public async Task GetContentFromFileAsync(string fileId)
259 | {
260 | var resultUrl = string.Format(URL_FILE_CONTEXT, fileId);
261 | var httpResponseMessage = await _httpClient.GetAsync(resultUrl);
262 |
263 | return await ReadAsStringAsync(httpResponseMessage);
264 | }
265 |
266 | #endregion
267 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IChatMessage
4 | {
5 | public string Content { get; }
6 | public string Role { get; }
7 | public string FinishReason { get; set; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatMessageParameters.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IChatMessageParameters
4 | {
5 | public string? Role { get; }
6 |
7 | public string? ModelId { get; }
8 |
9 | public float? Temperature { get; }
10 |
11 | public float? TopP { get; }
12 |
13 | public bool? Stream { get; }
14 |
15 | public int? MaxTokens { get; }
16 |
17 | public float? PresencePenalty { get; }
18 |
19 | public float? FrequencyPenalty { get; }
20 |
21 | public Dictionary? LogitBias { get; }
22 |
23 | public string? User { get; }
24 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatMessageParametersBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public interface IChatMessageParametersBuilder
6 | {
7 | public IChatMessageParametersBuilder SetModel(string modelId);
8 | public IChatMessageParametersBuilder SetModel(GptModel model);
9 | public IChatMessageParametersBuilder SetRole(string role);
10 | public IChatMessageParametersBuilder SetRole(RoleType role);
11 | public IChatMessageParametersBuilder SetMaxTokens(int maxTokens);
12 | public IChatMessageParametersBuilder SetTemperature(float temperature);
13 | public IChatMessageParametersBuilder SetNucleus(float value);
14 | public IChatMessageParametersBuilder SetStream();
15 | public IChatMessageParametersBuilder SetPresencePenalty(float number);
16 | public IChatMessageParametersBuilder SetFrequencyPenalty(float number);
17 | public IChatMessageParametersBuilder SetLogitBias(Dictionary dictionary);
18 | public IChatMessageParametersBuilder SetLogitBias(string key, int value);
19 | public IChatMessageParametersBuilder SetUser(string user);
20 |
21 | public IChatMessageParameters Build();
22 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatSession.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IChatSession
4 | {
5 | public string ToJson();
6 |
7 | public IChatSessionRecord[] Records();
8 |
9 | public void AddRecord(IChatSessionRecord record);
10 |
11 | public void AddRecords(IChatSessionRecord[] records);
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatSessionLoader.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IChatSessionLoader
4 | {
5 | IChatSession FromJson(string json);
6 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IChatSessionRecord.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IChatSessionRecord
4 | {
5 | string Role { get; }
6 | string Content { get; }
7 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IGptChat.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public interface IGptChat
6 | {
7 | public IChatSession Session { get; }
8 |
9 | public Task> AskAsync(string message);
10 |
11 | public Task> AskAsync(string message, IChatMessageParameters parameters);
12 |
13 | public Task> AskMultipleAsync(string message, int countOfAnswers);
14 |
15 | public Task> AskMultipleAsync(string message, int countOfAnswers,
16 | IChatMessageParameters parameters);
17 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Abstractions/IUsage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | public interface IUsage
4 | {
5 | public int PromptTokens { get; }
6 |
7 | public int CompletionTokens { get; }
8 |
9 | public int TotalTokens { get; }
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Extensions/ChatExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public static class ChatExtensions
6 | {
7 | public static Task> AskAsync(this IGptChat chat, string message,
8 | Func parameters)
9 | {
10 | var builder = new ChatMessageParametersBuilder();
11 | return chat.AskAsync(message, parameters.Invoke(builder));
12 | }
13 |
14 | public static Task> AskMultipleAsync(this IGptChat chat,
15 | string message, int countOfAnswers,
16 | Func parameters)
17 | {
18 | var builder = new ChatMessageParametersBuilder();
19 | return chat.AskMultipleAsync(message, countOfAnswers, parameters.Invoke(builder));
20 | }
21 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Extensions/ClientChatExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public static class ClientChatExtensions
6 | {
7 | public static IGptChat OpenChat(this IGptClient client)
8 | {
9 | return client.OpenChat(new ChatSession());
10 | }
11 |
12 | public static IGptChat OpenChat(this IGptClient client, IChatSession session)
13 | {
14 | var builder = new ChatMessageParametersBuilder();
15 | builder.SetModel(client.Configuration.ModelId);
16 | return client.OpenChat(builder.Build(), session);
17 | }
18 |
19 | public static IGptChat OpenChat(this IGptClient client, IChatMessageParameters defaultMessageParameters)
20 | {
21 | return client.OpenChat(defaultMessageParameters, new ChatSession());
22 | }
23 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Extensions/MapperChatExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Client;
3 |
4 | namespace ManagedCode.OpenAI.Chat;
5 |
6 | internal static class MapperChatExtensions
7 | {
8 | public static IPermission ToPermission(this PermissionDto dto)
9 | {
10 | return new Permission
11 | {
12 | AllowCreateEngine = dto.AllowCreateEngine,
13 | AllowFineTuning = dto.AllowFineTuning,
14 | AllowLogProbs = dto.AllowLogprobs,
15 | AllowSampling = dto.AllowSampling,
16 | AllowSearchIndices = dto.AllowSearchIndices,
17 | AllowView = dto.AllowView,
18 | Created = dto.Created,
19 | Id = dto.Id,
20 | IsBlocking = dto.IsBlocking,
21 | Organization = dto.Organization
22 | };
23 | }
24 |
25 | public static IAnswer ToChatAnswer(this ChatResponseDto dto)
26 | {
27 | return new Answer
28 | {
29 | Id = dto.Id,
30 | ModelId = dto.Model,
31 | Usage = dto.Usage.ToUsage(),
32 | Data = dto.Choices.First().ToChatMessage(),
33 | Created = dto.Created
34 | };
35 | }
36 |
37 | public static IAnswer ToChatAnswerCollection(this ChatResponseDto dto)
38 | {
39 | return new Answer
40 | {
41 | Id = dto.Id,
42 | ModelId = dto.Model,
43 | Usage = dto.Usage.ToUsage(),
44 | Data = dto.Choices.Select(x => x.ToChatMessage()).ToArray(),
45 | Created = dto.Created
46 | };
47 | }
48 |
49 | public static IChatMessage ToChatMessage(this ChatChoiceDto dto)
50 | {
51 | return new ChatMessage
52 | {
53 | Content = dto.Message.Content,
54 | Role = dto.Message.Role,
55 | FinishReason = dto.FinishReason
56 | };
57 | }
58 |
59 | public static IUsage ToUsage(this UsageDto dto)
60 | {
61 | return new Usage
62 | {
63 | CompletionTokens = dto.CompletionTokens,
64 | PromptTokens = dto.PromptTokens,
65 | TotalTokens = dto.TotalTokens
66 | };
67 | }
68 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/GptChat.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Client;
3 | using ManagedCode.OpenAI.Extensions;
4 |
5 | namespace ManagedCode.OpenAI.Chat;
6 |
7 | internal class GptChat : IGptChat
8 | {
9 | private const RoleType DEFAULT_ROLE = RoleType.User;
10 | private const GptModel DEFAULT_MODEL = GptModel.Gpt35Turbo;
11 | private readonly IChatMessageParameters _defaultMessageParameters;
12 |
13 | private readonly IOpenAiWebClient _webClient;
14 |
15 | public GptChat(IOpenAiWebClient webClient, IChatSession session,
16 | IChatMessageParameters defaultMessageParameters)
17 | {
18 | _webClient = webClient;
19 | _defaultMessageParameters = defaultMessageParameters;
20 | Session = session;
21 | }
22 |
23 | public IChatSession Session { get; }
24 |
25 | public async Task> AskAsync(string message)
26 | {
27 | return await AskAsync(message, _defaultMessageParameters);
28 | }
29 |
30 | public async Task> AskAsync(string message, IChatMessageParameters parameters)
31 | {
32 | var askMessage = CreateAskMessage(message, parameters);
33 | var request = ToChatRequest(askMessage, 1, parameters);
34 |
35 | var response = await _webClient.ChatAsync(request);
36 | UpdateSession(response, askMessage);
37 | return response.ToChatAnswer();
38 | }
39 |
40 | public async Task> AskMultipleAsync(string message, int countOfAnswers)
41 | {
42 | return await AskMultipleAsync(message, countOfAnswers, _defaultMessageParameters);
43 | }
44 |
45 | public async Task> AskMultipleAsync(string message, int countOfAnswers,
46 | IChatMessageParameters parameters)
47 | {
48 | var askMessage = CreateAskMessage(message, parameters);
49 | var request = ToChatRequest(askMessage, countOfAnswers, parameters);
50 | var response = await _webClient.ChatAsync(request);
51 |
52 | UpdateSession(response, askMessage);
53 | return response.ToChatAnswerCollection();
54 | }
55 |
56 | private void UpdateSession(ChatResponseDto response, MessageDto askMessage)
57 | {
58 | Session.AddRecord(new ChatSessionRecord
59 | {
60 | Content = askMessage.Content,
61 | Role = askMessage.Role
62 | });
63 |
64 | var responseRecords =
65 | response.Choices.Select(x => (IChatSessionRecord)new ChatSessionRecord
66 | {
67 | Content = x.Message.Content,
68 | Role = x.Message.Role
69 | }).ToArray();
70 |
71 |
72 | Session.AddRecords(responseRecords);
73 | }
74 |
75 | private MessageDto CreateAskMessage(string message, IChatMessageParameters parameters)
76 | {
77 | return new MessageDto
78 | {
79 | Content = message,
80 | Role = (parameters.Role ?? _defaultMessageParameters.Role) ?? DEFAULT_ROLE.Name()
81 | };
82 | }
83 |
84 | private ChatRequestDto ToChatRequest(MessageDto askMessage,
85 | int countOfAnswers, IChatMessageParameters parameters)
86 | {
87 | var messages = Session.Records().Select(x => new MessageDto
88 | {
89 | Content = x.Content,
90 | Role = x.Role
91 | }).ToList();
92 |
93 | messages.Add(askMessage);
94 |
95 | return new ChatRequestDto
96 | {
97 | FrequencyPenalty = parameters.FrequencyPenalty ?? _defaultMessageParameters.FrequencyPenalty,
98 | LogitBias = parameters.LogitBias ?? _defaultMessageParameters.LogitBias,
99 | MaxTokens = parameters.MaxTokens ?? _defaultMessageParameters.MaxTokens,
100 | Model = (parameters.ModelId ?? _defaultMessageParameters.ModelId) ?? DEFAULT_MODEL.Name(),
101 | N = countOfAnswers,
102 | PresencePenalty = parameters.PresencePenalty ?? _defaultMessageParameters.PresencePenalty,
103 | Stream = parameters.Stream ?? _defaultMessageParameters.Stream,
104 | Temperature = parameters.Temperature ?? _defaultMessageParameters.Temperature,
105 | TopP = parameters.TopP ?? _defaultMessageParameters.TopP,
106 | User = parameters.User ?? _defaultMessageParameters.User,
107 | Messages = messages
108 | };
109 | }
110 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Message/ChatMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | internal class ChatMessage : IChatMessage
4 | {
5 | public required string Content { get; set; }
6 | public required string Role { get; set; }
7 |
8 | public required string FinishReason { get; set; }
9 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Message/ChatMessageParameters.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public class ChatMessageParameters : IChatMessageParameters
6 | {
7 | public string? Role { get; set; }
8 | public string? ModelId { get; set; }
9 |
10 | [Range(0, 2f)]
11 | public float? Temperature { get; set; }
12 |
13 | public float? TopP { get; set; }
14 | public bool? Stream { get; set; }
15 |
16 | [Range(0, 2048)]
17 | public int? MaxTokens { get; set; }
18 |
19 | [Range(-2f, 2f)]
20 | public float? PresencePenalty { get; set; }
21 |
22 | [Range(-2f, 2f)]
23 | public float? FrequencyPenalty { get; set; }
24 |
25 | public Dictionary? LogitBias { get; set; }
26 | public string? User { get; set; }
27 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Message/ChatMessageParametersBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 | using ManagedCode.OpenAI.Extensions;
3 |
4 | namespace ManagedCode.OpenAI.Chat;
5 |
6 | public class ChatMessageParametersBuilder : IChatMessageParametersBuilder
7 | {
8 | private readonly ChatMessageParameters _parameters;
9 |
10 | public ChatMessageParametersBuilder()
11 | {
12 | _parameters = new ChatMessageParameters();
13 | }
14 |
15 | public IChatMessageParametersBuilder SetModel(string modelId)
16 | {
17 | _parameters.ModelId = modelId;
18 | return this;
19 | }
20 |
21 | public IChatMessageParametersBuilder SetModel(GptModel model)
22 | {
23 | _parameters.ModelId = model.Name();
24 | return this;
25 | }
26 |
27 | public IChatMessageParametersBuilder SetRole(string role)
28 | {
29 | _parameters.Role = role;
30 | return this;
31 | }
32 |
33 | public IChatMessageParametersBuilder SetRole(RoleType role)
34 | {
35 | _parameters.Role = role.Name();
36 | return this;
37 | }
38 |
39 | public IChatMessageParametersBuilder SetMaxTokens(int maxTokens)
40 | {
41 | _parameters.MaxTokens = maxTokens;
42 | return this;
43 | }
44 |
45 | public IChatMessageParametersBuilder SetTemperature(float temperature)
46 | {
47 | _parameters.Temperature = temperature;
48 | return this;
49 | }
50 |
51 | public IChatMessageParametersBuilder SetNucleus(float value)
52 | {
53 | _parameters.TopP = value;
54 | return this;
55 | }
56 |
57 | public IChatMessageParametersBuilder SetStream()
58 | {
59 | _parameters.Stream = true;
60 | return this;
61 | }
62 |
63 | public IChatMessageParametersBuilder SetPresencePenalty(float number)
64 | {
65 | _parameters.PresencePenalty = number;
66 | return this;
67 | }
68 |
69 | public IChatMessageParametersBuilder SetFrequencyPenalty(float number)
70 | {
71 | _parameters.FrequencyPenalty = number;
72 | return this;
73 | }
74 |
75 | public IChatMessageParametersBuilder SetLogitBias(Dictionary dictionary)
76 | {
77 | _parameters.LogitBias = dictionary;
78 | return this;
79 | }
80 |
81 | public IChatMessageParametersBuilder SetLogitBias(string key, int value)
82 | {
83 | var dict = _parameters.LogitBias ??= new Dictionary();
84 | dict.Add(key, value);
85 | return this;
86 | }
87 |
88 | public IChatMessageParametersBuilder SetUser(string user)
89 | {
90 | _parameters.User = user;
91 | return this;
92 | }
93 |
94 | public IChatMessageParameters Build()
95 | {
96 | _parameters.Validate();
97 | return _parameters;
98 | }
99 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Message/Usage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | internal class Usage : IUsage
4 | {
5 | public required int PromptTokens { get; set; }
6 | public required int CompletionTokens { get; set; }
7 | public required int TotalTokens { get; set; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Session/ChatSession.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | internal class ChatSession : IChatSession
6 | {
7 | public List ListRecords { get; } = new();
8 |
9 | public string ToJson()
10 | {
11 | return JsonSerializer.Serialize(ListRecords);
12 | }
13 |
14 | IChatSessionRecord[] IChatSession.Records()
15 | {
16 | return ListRecords.ToArray();
17 | }
18 |
19 | public void AddRecord(IChatSessionRecord record)
20 | {
21 | ListRecords.Add(record);
22 | }
23 |
24 | public void AddRecords(IChatSessionRecord[] records)
25 | {
26 | ListRecords.AddRange(records);
27 | }
28 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Session/ChatSessionLoader.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace ManagedCode.OpenAI.Chat;
4 |
5 | public class ChatSessionLoader : IChatSessionLoader
6 | {
7 | public IChatSession FromJson(string json)
8 | {
9 | var records = JsonSerializer.Deserialize(json)
10 | ?? throw new ArgumentException($"Wrong session format: {json}");
11 |
12 | var session = new ChatSession();
13 | session.AddRecords(records.Cast().ToArray());
14 | return session;
15 | }
16 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Chat/Session/ChatSessionRecord.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Chat;
2 |
3 | internal class ChatSessionRecord : IChatSessionRecord
4 | {
5 | public required string Role { get; set; }
6 | public required string Content { get; set; }
7 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IAnswer.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Chat;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | public interface IAnswer
6 | {
7 | public TModel Data { get; }
8 |
9 | public IUsage Usage { get; }
10 |
11 | public int Created { get; }
12 |
13 | public string ModelId { get; }
14 |
15 | public string Id { get; }
16 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IGptClient.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Chat;
2 | using ManagedCode.OpenAI.Completions;
3 | using ManagedCode.OpenAI.Edit;
4 | using ManagedCode.OpenAI.Image;
5 | using ManagedCode.OpenAI.Moderation;
6 |
7 | namespace ManagedCode.OpenAI.Client;
8 |
9 | public interface IGptClient
10 | {
11 | public IGptClientConfiguration Configuration { get; }
12 |
13 | public IImageClient ImageClient { get; }
14 |
15 | void Configure(IGptClientConfiguration configuration);
16 | void Configure(Func configuration);
17 |
18 | public Task GetModelsAsync();
19 | public Task GetModelAsync(string modelId);
20 |
21 | IGptChat OpenChat(IChatMessageParameters defaultMessageParameters, IChatSession session);
22 | ICompletionBuilder Completion(string prompt);
23 | IEditBuilder Edit(string input, string instruction);
24 | IModerationBuilder Moderation();
25 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IGptClientBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public interface IGptClientBuilder
4 | {
5 | public IGptClientBuilder WithOrganization(string organization);
6 |
7 | public IGptClientBuilder Configure(Action configuration);
8 |
9 | public GptClient Build();
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IGptClientConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public interface IGptClientConfiguration
4 | {
5 | public string ModelId { get; }
6 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IGptClientConfigurationBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public interface IGptClientConfigurationBuilder
4 | {
5 | IGptClientConfigurationBuilder SetDefaultModel(string modelId);
6 | IGptClientConfigurationBuilder SetDefaultModel(GptModel model);
7 |
8 | IGptClientConfiguration Build();
9 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IModel.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public interface IModel
4 | {
5 | public string Id { get; }
6 |
7 | public string OwnedBy { get; }
8 |
9 | public IPermission[] Permission { get; }
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Abstractions/IPermission.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public interface IPermission
4 | {
5 | public string Id { get; }
6 |
7 | public int Created { get; }
8 |
9 | public bool AllowCreateEngine { get; }
10 |
11 | public bool AllowSampling { get; }
12 |
13 | public bool AllowLogProbs { get; }
14 |
15 | public bool AllowSearchIndices { get; }
16 |
17 | public bool AllowView { get; }
18 |
19 | public bool AllowFineTuning { get; }
20 |
21 | public string Organization { get; }
22 |
23 | public bool IsBlocking { get; }
24 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Configuration/DefaultGptClientConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Extensions;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | public class DefaultGptClientConfiguration : IGptClientConfiguration
6 | {
7 | private const GptModel DEFAULT_MODEL = GptModel.Gpt35Turbo;
8 |
9 | public DefaultGptClientConfiguration()
10 | {
11 | ModelId = DEFAULT_MODEL.Name();
12 | }
13 |
14 | public string ModelId { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Configuration/GptClientConfigurationBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Extensions;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | public class GptClientConfigurationBuilder : IGptClientConfigurationBuilder
6 | {
7 | private readonly DefaultGptClientConfiguration _configuration;
8 |
9 | public GptClientConfigurationBuilder()
10 | {
11 | _configuration = new DefaultGptClientConfiguration();
12 | }
13 |
14 | public IGptClientConfigurationBuilder SetDefaultModel(string modelId)
15 | {
16 | _configuration.ModelId = modelId;
17 | return this;
18 | }
19 |
20 | public IGptClientConfigurationBuilder SetDefaultModel(GptModel model)
21 | {
22 | _configuration.ModelId = model.Name();
23 | return this;
24 | }
25 |
26 | public IGptClientConfiguration Build()
27 | {
28 | return _configuration;
29 | }
30 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Extensions/GptClientExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Chat;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | public static class GptClientExtensions
6 | {
7 | public static IGptChat OpenChat(this IGptClient client,
8 | IChatMessageParameters defaultMessageParameters, string json)
9 | {
10 | return client.OpenChat(defaultMessageParameters, x => x.FromJson(json));
11 | }
12 |
13 | public static IGptChat OpenChat(this IGptClient client, Func session)
14 | {
15 | var sessionLoader = DefaultSessionLoader();
16 | return client.OpenChat(session.Invoke(sessionLoader));
17 | }
18 |
19 | public static IGptChat OpenChat(this IGptClient client, IChatMessageParameters defaultMessageParameters,
20 | Func session)
21 | {
22 | var sessionLoader = DefaultSessionLoader();
23 | return client.OpenChat(defaultMessageParameters, session.Invoke(sessionLoader));
24 | }
25 |
26 | private static IChatSessionLoader DefaultSessionLoader()
27 | {
28 | return new ChatSessionLoader();
29 | }
30 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Extensions/MapperClientExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Chat;
3 |
4 | namespace ManagedCode.OpenAI.Client;
5 |
6 | internal static class MapperClientExtensions
7 | {
8 | public static IModel ToModel(this ModelDto dto)
9 | {
10 | return new Model
11 | {
12 | Id = dto.Id,
13 | OwnedBy = dto.OwnedBy,
14 | Permission = dto.Permission.Select(x => x.ToPermission()).ToArray()
15 | };
16 | }
17 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/GptClient.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Chat;
3 | using ManagedCode.OpenAI.Completions;
4 | using ManagedCode.OpenAI.Edit;
5 | using ManagedCode.OpenAI.Image;
6 | using ManagedCode.OpenAI.Moderation;
7 |
8 | namespace ManagedCode.OpenAI.Client;
9 |
10 | public class GptClient : IGptClient
11 | {
12 | private IOpenAiWebClient _webClient = null!;
13 |
14 | public GptClient(string apiKey)
15 | {
16 | Init(apiKey, default, new DefaultGptClientConfiguration());
17 | }
18 |
19 | public GptClient(string apiKey, IGptClientConfiguration configuration)
20 | {
21 | Init(apiKey, default, configuration);
22 | }
23 |
24 | public GptClient(string apiKey, string organization)
25 | {
26 | Init(apiKey, organization, new DefaultGptClientConfiguration());
27 | }
28 |
29 | public GptClient(string apiKey, string organization, IGptClientConfiguration configuration)
30 | {
31 | Init(apiKey, organization, configuration);
32 | }
33 |
34 |
35 | internal GptClient(string apiKey, IGptClientConfiguration configuration, string? organization)
36 | {
37 | Init(apiKey, organization, configuration);
38 | }
39 |
40 | internal GptClient(IGptClientConfiguration configuration, IOpenAiWebClient webClient)
41 | {
42 | _webClient = webClient;
43 | Configuration = new DefaultGptClientConfiguration();
44 | ImageClient = new ImageClient(_webClient);
45 | Configuration = configuration;
46 | }
47 |
48 | private GptClient()
49 | {
50 | }
51 |
52 |
53 | public IGptClientConfiguration Configuration { get; private set; } = null!;
54 | public IImageClient ImageClient { get; private set; } = null!;
55 |
56 | public void Configure(IGptClientConfiguration configuration)
57 | {
58 | Configuration = configuration;
59 | }
60 |
61 | public void Configure(Func configuration)
62 | {
63 | var builder = new GptClientConfigurationBuilder();
64 | Configure(configuration.Invoke(builder));
65 | }
66 |
67 | public async Task GetModelsAsync()
68 | {
69 | var models = await _webClient.ModelsAsync();
70 | return models.Models.Select(x => x.ToModel()).ToArray();
71 | }
72 |
73 | public async Task GetModelAsync(string modelId)
74 | {
75 | var model = await _webClient.ModelAsync(modelId);
76 | return model.ToModel();
77 | }
78 |
79 | public IGptChat OpenChat(IChatMessageParameters defaultMessageParameters, IChatSession session)
80 | {
81 | return new GptChat(_webClient, session, defaultMessageParameters);
82 | }
83 |
84 | public ICompletionBuilder Completion(string prompt)
85 | {
86 | return new CompletionsBuilder(_webClient, prompt);
87 | }
88 |
89 | public IEditBuilder Edit(string input, string instruction)
90 | {
91 | return new EditBuilder(_webClient, input, instruction);
92 | }
93 |
94 | public IModerationBuilder Moderation()
95 | {
96 | return new ModerationBuilder(_webClient);
97 | }
98 |
99 | public static IGptClientBuilder Builder(string apiKey)
100 | {
101 | return new GptClientBuilder(apiKey);
102 | }
103 |
104 | private void Init(string apiKey, string? organization, IGptClientConfiguration configuration)
105 | {
106 | var webClient = string.IsNullOrWhiteSpace(organization)
107 | ? new OpenAiWebClient(apiKey)
108 | : new OpenAiWebClient(apiKey, organization);
109 |
110 | _webClient = webClient;
111 | Configuration = configuration;
112 | ImageClient = new ImageClient(_webClient);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/GptClientBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | public class GptClientBuilder : IGptClientBuilder
4 | {
5 |
6 | public GptClientBuilder(string apiKey)
7 | {
8 | ApiKey = apiKey;
9 | Configuration = new DefaultGptClientConfiguration();
10 | }
11 |
12 | protected string ApiKey { get; set; }
13 | protected IGptClientConfiguration Configuration { get; set; }
14 | protected string? Organization { get; set; }
15 |
16 | public IGptClientBuilder WithOrganization(string organization)
17 | {
18 | Organization = organization;
19 | return this;
20 | }
21 |
22 | public IGptClientBuilder Configure(Action configuration)
23 | {
24 | var builder = new GptClientConfigurationBuilder();
25 | configuration.Invoke(builder);
26 | Configuration = builder.Build();
27 | return this;
28 | }
29 |
30 | public virtual GptClient Build()
31 | {
32 | var client = new GptClient(ApiKey, Configuration, Organization);
33 | return client;
34 | }
35 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Models/Answer.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Chat;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | internal class Answer : IAnswer
6 | {
7 | public required TModel Data { get; set; }
8 | public required IUsage Usage { get; set; }
9 | public required int Created { get; set; }
10 | public required string ModelId { get; set; }
11 | public required string Id { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Models/GptModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Runtime.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.Client;
5 |
6 | public enum GptModel
7 | {
8 |
9 | [EnumMember(Value = "gpt-4")]
10 | [Description("gpt-4")]
11 | Gpt4,
12 |
13 | [EnumMember(Value = "gpt-4-0613")]
14 | [Description("gpt-4-0613")]
15 | Gpt40613,
16 |
17 | [EnumMember(Value = "gpt-4-32k")]
18 | [Description("gpt-4-32k")]
19 | Gpt432k,
20 |
21 | [EnumMember(Value = "gpt-4-32k-0613")]
22 | [Description("gpt-4-32k-0613")]
23 | Gpt432k0613,
24 |
25 | [EnumMember(Value = "gpt-3.5-turbo")]
26 | [Description("gpt-3.5-turbo")]
27 | Gpt35Turbo,
28 |
29 | [EnumMember(Value = "gpt-3.5-turbo-16k")]
30 | [Description("gpt-3.5-turbo-16k")]
31 | Gpt35Turbo16k,
32 |
33 | [EnumMember(Value = "gpt-3.5-turbo-0613")]
34 | [Description("gpt-3.5-turbo-0613")]
35 | Gpt35Turbo0613,
36 |
37 | [EnumMember(Value = "gpt-3.5-turbo-16k-0613")]
38 | [Description("gpt-3.5-turbo-16k-0613")]
39 | Gpt35Turbo16k0613,
40 |
41 | [EnumMember(Value = "text-davinci-003")]
42 | [Description("text-davinci-003")]
43 | TextDavinci003,
44 |
45 | [EnumMember(Value = "text-curie-001")]
46 | [Description("text-curie-001")]
47 | TextCurie001,
48 |
49 | [EnumMember(Value = "text-babbage-001")]
50 | [Description("text-babbage-001")]
51 | TextBabbage001,
52 |
53 | [EnumMember(Value = "text-ada-001")]
54 | [Description("text-ada-001")]
55 | TextAda001,
56 |
57 | [EnumMember(Value = "text-davinci-002")]
58 | [Description("text-davinci-002")]
59 | TextDavinci002,
60 |
61 | [EnumMember(Value = "text-davinci-001")]
62 | [Description("text-davinci-001")]
63 | TextDavinci001,
64 |
65 | [EnumMember(Value = "davinci-instruct-beta")]
66 | [Description("davinci-instruct-beta")]
67 | DavinciInstructBeta,
68 |
69 | [EnumMember(Value = "davinci")]
70 | [Description("davinci")]
71 | Davinci,
72 |
73 | [EnumMember(Value = "curie-instruct-beta")]
74 | [Description("curie-instruct-beta")]
75 | CurieInstructBeta,
76 |
77 | [EnumMember(Value = "curie")]
78 | [Description("curie")]
79 | Curie,
80 |
81 | [EnumMember(Value = "babbage")]
82 | [Description("babbage")]
83 | Babbage,
84 |
85 | [EnumMember(Value = "ada")]
86 | [Description("ada")]
87 | Ada,
88 |
89 | [EnumMember(Value = "code-davinci-002")]
90 | [Description("code-davinci-002")]
91 | CodeDavinci002,
92 |
93 | [EnumMember(Value = "code-cushman-001")]
94 | [Description("code-cushman-001")]
95 | CodeCushman001,
96 |
97 |
98 | [EnumMember(Value = "text-moderation-stable")]
99 | [Description("text-moderation-stable")]
100 | TextModerationStable,
101 |
102 | [EnumMember(Value = "text-moderation-latest")]
103 | [Description("text-moderation-latest")]
104 | TextModerationLatest,
105 |
106 | [EnumMember(Value = "text-davinci-edit-001")]
107 | [Description("text-davinci-edit-001")]
108 | TextDavinciEdit001,
109 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Models/Model.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | internal class Model : IModel
4 | {
5 | public required string Id { get; set; }
6 | public required string OwnedBy { get; set; }
7 | public required IPermission[] Permission { get; set; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Models/Permission.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Client;
2 |
3 | internal class Permission : IPermission
4 | {
5 | public required string Id { get; set; }
6 | public required int Created { get; set; }
7 | public required bool AllowCreateEngine { get; set; }
8 | public required bool AllowSampling { get; set; }
9 | public required bool AllowLogProbs { get; set; }
10 | public required bool AllowSearchIndices { get; set; }
11 | public required bool AllowView { get; set; }
12 | public required bool AllowFineTuning { get; set; }
13 | public required string Organization { get; set; }
14 | public required bool IsBlocking { get; set; }
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/Models/RoleType.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.Client;
4 |
5 | public enum RoleType
6 | {
7 | [EnumMember(Value = "user")] User,
8 |
9 | [EnumMember(Value = "Assistant")] Assistant
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Client/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using Microsoft.Extensions.DependencyInjection;
3 |
4 | [assembly: InternalsVisibleTo("ManagedCode.OpenAI.Tests", AllInternalsVisible = true)]
5 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
6 |
7 | namespace ManagedCode.OpenAI.Client;
8 |
9 | public static class ServiceCollectionExtensions
10 | {
11 | public static void AddOpenAI(this IServiceCollection collection, string apiKey)
12 | {
13 | collection.AddSingleton(s => new GptClient(apiKey));
14 | }
15 |
16 | public static void AddOpenAI(this IServiceCollection collection, string apiKey,
17 | Action build)
18 | {
19 | var builder = new GptClientBuilder(apiKey);
20 | build.Invoke(builder);
21 | collection.AddSingleton(s => builder.Build());
22 | }
23 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/Abstractions/ICompletionBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Completions;
4 |
5 | public interface ICompletionBuilder
6 | {
7 | public ICompletionBuilder AddPrompt(string prompt);
8 | public ICompletionBuilder AddPrompt(params string[] prompts);
9 | public ICompletionBuilder SetSuffix(string suffix);
10 | public ICompletionBuilder SetMaxTokens(int maxTokens);
11 | public ICompletionBuilder SetTemperature(float temperature);
12 | public ICompletionBuilder SetStream();
13 | public ICompletionBuilder SetLogProbs(int count);
14 | public ICompletionBuilder SetEcho();
15 | public ICompletionBuilder SetStop(string stop);
16 | public ICompletionBuilder SetStop(string[] stop);
17 | public ICompletionBuilder SetPresencePenalty(float number);
18 | public ICompletionBuilder SetFrequencyPenalty(float number);
19 | public ICompletionBuilder SetBestOf(int integer);
20 | public ICompletionBuilder SetLogitBias(Dictionary dictionary);
21 | public ICompletionBuilder AddLogitBias(string key, int value);
22 | public ICompletionBuilder SetUsername(string user);
23 | public ICompletionBuilder SetModel(string modelId);
24 | public ICompletionBuilder SetModel(GptModel model);
25 |
26 |
27 | public Task> ExecuteAsync();
28 |
29 | public Task> ExecuteMultipleAsync(int count);
30 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/Abstractions/ICompletionsMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Completions;
2 |
3 | public interface ICompletionsMessage
4 | {
5 | public string Content { get; }
6 | public string FinishReason { get; }
7 | public int? LogProbs { get; set; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/CompletionsBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Client;
3 | using ManagedCode.OpenAI.Extensions;
4 |
5 | namespace ManagedCode.OpenAI.Completions;
6 |
7 | internal class CompletionsBuilder : ICompletionBuilder
8 | {
9 | private const GptModel DEFAULT_MODEL = GptModel.TextDavinci003;
10 | private readonly CompletionRequestDto _request;
11 | private readonly IOpenAiWebClient _webClient;
12 |
13 | public CompletionsBuilder(IOpenAiWebClient webClient, string prompt)
14 | {
15 | _request = new CompletionRequestDto();
16 | _webClient = webClient;
17 |
18 | AddPrompt(prompt);
19 | SetModel(DEFAULT_MODEL);
20 | }
21 |
22 | public ICompletionBuilder AddPrompt(string prompt)
23 | {
24 | if (prompt.Length > 1024)
25 | throw new ArgumentException();
26 |
27 | _request.Prompt.Add(prompt);
28 | return this;
29 | }
30 |
31 | public ICompletionBuilder AddPrompt(params string[] prompts)
32 | {
33 | _request.Prompt.AddRange(prompts);
34 | return this;
35 | }
36 |
37 | public ICompletionBuilder SetSuffix(string suffix)
38 | {
39 | _request.Suffix = suffix;
40 | return this;
41 | }
42 |
43 | public ICompletionBuilder SetMaxTokens(int maxTokens)
44 | {
45 | _request.MaxTokens = maxTokens;
46 | return this;
47 | }
48 |
49 | public ICompletionBuilder SetTemperature(float temperature)
50 | {
51 | _request.Temperature = temperature;
52 | return this;
53 | }
54 |
55 | // TODO: How to work, when stream is true?
56 | public ICompletionBuilder SetStream()
57 | {
58 | _request.Stream = true;
59 | return this;
60 | }
61 |
62 | public ICompletionBuilder SetLogProbs(int count)
63 | {
64 | _request.Logprobs = count;
65 | return this;
66 | }
67 |
68 | public ICompletionBuilder SetEcho()
69 | {
70 | _request.Echo = true;
71 | return this;
72 | }
73 |
74 | public ICompletionBuilder SetStop(string stop)
75 | {
76 | _request.Stop = new[] { stop };
77 | return this;
78 | }
79 |
80 | public ICompletionBuilder SetStop(string[] stop)
81 | {
82 | _request.Stop = stop;
83 | return this;
84 | }
85 |
86 | public ICompletionBuilder SetPresencePenalty(float number)
87 | {
88 | _request.PresencePenalty = number;
89 | return this;
90 | }
91 |
92 | public ICompletionBuilder SetFrequencyPenalty(float number)
93 | {
94 | _request.FrequencyPenalty = number;
95 | return this;
96 | }
97 |
98 | public ICompletionBuilder SetBestOf(int integer)
99 | {
100 | if (_request.Stream == true) throw new NotSupportedException("Results cannot be streamed.");
101 |
102 | _request.BestOf = integer;
103 | return this;
104 | }
105 |
106 | public ICompletionBuilder SetLogitBias(Dictionary dictionary)
107 | {
108 | _request.LogitBias = dictionary;
109 | return this;
110 | }
111 |
112 | public ICompletionBuilder AddLogitBias(string key, int value)
113 | {
114 | var dict = _request.LogitBias ??= new Dictionary();
115 | dict.Add(key, value);
116 | return this;
117 | }
118 |
119 | public ICompletionBuilder SetUsername(string user)
120 | {
121 | _request.User = user;
122 | return this;
123 | }
124 |
125 | public ICompletionBuilder SetModel(string modelId)
126 | {
127 | _request.Model = modelId;
128 | return this;
129 | }
130 |
131 | public ICompletionBuilder SetModel(GptModel model)
132 | {
133 | _request.Model = model.Name();
134 | return this;
135 | }
136 |
137 | public async Task> ExecuteAsync()
138 | {
139 | _request.Validate();
140 | var response = await _webClient.CompletionsAsync(_request);
141 | return response.ToCompletionsAnswer();
142 | }
143 |
144 | public async Task> ExecuteMultipleAsync(int count)
145 | {
146 | _request.N = count;
147 | _request.Validate();
148 | var response = await _webClient.CompletionsAsync(_request);
149 | return response.ToCompletionsAnswerCollection();
150 | }
151 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/CompletionsMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Completions;
2 |
3 | internal class CompletionsMessage : ICompletionsMessage
4 | {
5 | public required string Content { get; set; }
6 | public required string FinishReason { get; set; }
7 | public required int? LogProbs { get; set; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/Extensions/MapperCompletionsExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.Chat;
3 | using ManagedCode.OpenAI.Client;
4 |
5 | namespace ManagedCode.OpenAI.Completions;
6 |
7 | internal static class MapperCompletionsExtensions
8 | {
9 | public static ICompletionsMessage ToCompletionsMessage(this CompletionChoiceDto dto)
10 | {
11 | return new CompletionsMessage
12 | {
13 | Content = dto.Text,
14 | LogProbs = dto.Logprobs,
15 | FinishReason = dto.FinishReason
16 | };
17 | }
18 |
19 | public static IAnswer ToCompletionsAnswer(this CompletionResponseDto dto)
20 | {
21 | return new Answer
22 | {
23 | Id = dto.Id,
24 | ModelId = dto.Model,
25 | Usage = dto.Usage.ToUsage(),
26 | Data = dto.Choices.First().ToCompletionsMessage(),
27 | Created = dto.Created
28 | };
29 | }
30 |
31 | public static IAnswer ToCompletionsAnswerCollection(this CompletionResponseDto dto)
32 | {
33 | return new Answer
34 | {
35 | Id = dto.Id,
36 | ModelId = dto.Model,
37 | Usage = dto.Usage.ToUsage(),
38 | Data = dto.Choices.Select(x => x.ToCompletionsMessage()).ToArray(),
39 | Created = dto.Created
40 | };
41 | }
42 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Completions/ManagedCode.OpenAI.Client.Completions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 | ..\..\..\.nuget\packages\newtonsoft.json\13.0.3\lib\net6.0\Newtonsoft.Json.dll
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Edit/Abstractions/IEditBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Edit;
4 |
5 | public interface IEditBuilder
6 | {
7 | public IEditBuilder SetModel(string modelId);
8 |
9 | public IEditBuilder SetModel(GptModel model);
10 |
11 | public IEditBuilder SetTemperature(float temperature);
12 |
13 | public IEditBuilder SetTopP(float topP);
14 |
15 |
16 | public Task> ExecuteAsync();
17 |
18 | public Task> ExecuteMultipleAsync(int count);
19 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Edit/Abstractions/IEditMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Edit;
2 |
3 | public interface IEditMessage
4 | {
5 | public string Content { get; }
6 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Edit/EditBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.API.Edit;
3 | using ManagedCode.OpenAI.Client;
4 | using ManagedCode.OpenAI.Extensions;
5 |
6 | namespace ManagedCode.OpenAI.Edit;
7 |
8 | internal class EditBuilder : IEditBuilder
9 | {
10 | private const GptModel DEFAULT_MODEL = GptModel.TextDavinciEdit001;
11 | private readonly IOpenAiWebClient _client;
12 | private readonly EditRequestDto _request;
13 |
14 | public EditBuilder(IOpenAiWebClient client,string input, string instruction)
15 | {
16 | _client = client;
17 | _request = new EditRequestDto
18 | {
19 | Model = DEFAULT_MODEL.Name(),
20 | Input = input,
21 | Instruction = instruction
22 | };
23 | }
24 |
25 | public IEditBuilder SetModel(string modelId)
26 | {
27 | _request.Model = modelId;
28 | return this;
29 | }
30 |
31 | public IEditBuilder SetModel(GptModel model)
32 | {
33 | _request.Model = model.Name();
34 | return this;
35 | }
36 |
37 | public IEditBuilder SetTemperature(float temperature)
38 | {
39 | _request.Temperature = temperature;
40 | return this;
41 | }
42 |
43 | public IEditBuilder SetTopP(float topP)
44 | {
45 | _request.TopP = topP;
46 | return this;
47 | }
48 |
49 |
50 | public async Task> ExecuteAsync()
51 | {
52 | _request.Validate();
53 | var response = await _client.EditAsync(_request);
54 | return response.ToEditAnswer();
55 | }
56 |
57 | public async Task> ExecuteMultipleAsync(int count)
58 | {
59 | _request.Validate();
60 | var response = await _client.EditAsync(_request);
61 | return response.ToEditAnswerCollection();
62 | }
63 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Edit/EditMessage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Edit;
2 |
3 | internal class EditMessage : IEditMessage
4 | {
5 | public required string Content { get; set; }
6 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Edit/Extensions/MapperEditExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API.Edit;
2 | using ManagedCode.OpenAI.Chat;
3 | using ManagedCode.OpenAI.Client;
4 |
5 | namespace ManagedCode.OpenAI.Edit;
6 |
7 | internal static class MapperEditExtensions
8 | {
9 | public static IAnswer ToEditAnswer(this EditResponseDto dto)
10 | {
11 | return new Answer
12 | {
13 | Id = dto.Id,
14 | ModelId = dto.Model,
15 | Usage = dto.Usage.ToUsage(),
16 | Data = dto.Choices.First().ToEditMessage(),
17 | Created = dto.Created
18 | };
19 | }
20 |
21 | public static IAnswer ToEditAnswerCollection(this EditResponseDto dto)
22 | {
23 | return new Answer
24 | {
25 | Id = dto.Id,
26 | ModelId = dto.Model,
27 | Usage = dto.Usage.ToUsage(),
28 | Data = dto.Choices.Select(x => x.ToEditMessage()).ToArray(),
29 | Created = dto.Created
30 | };
31 | }
32 |
33 | public static IEditMessage ToEditMessage(this EditChoiceDto dto)
34 | {
35 | return new EditMessage
36 | {
37 | Content = dto.Text
38 | };
39 | }
40 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Extensions/EnumExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace ManagedCode.OpenAI.Extensions;
4 |
5 | internal static class EnumExtensions
6 | {
7 | public static string Name(this Enum value)
8 | {
9 | var field = value.GetType().GetField(value.ToString());
10 |
11 | var attributes = (EnumMemberAttribute[])field!.GetCustomAttributes(
12 | typeof(EnumMemberAttribute), false);
13 |
14 | if (attributes.Length == 0)
15 | return value.ToString();
16 |
17 | return attributes.First().Value
18 | ?? throw new Exception($"{value} value property not specified in attribute");
19 | }
20 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Extensions/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 | using Microsoft.Extensions.DependencyInjection;
3 |
4 | namespace ManagedCode.OpenAI.Extensions;
5 |
6 | public static class ServiceCollectionExtensions
7 | {
8 | public static void AddOpenAI(this IServiceCollection collection, string apiKey)
9 | {
10 | collection.AddSingleton(s => new GptClient(apiKey));
11 | }
12 |
13 | public static void AddOpenAI(this IServiceCollection collection, string apiKey, string organization)
14 | {
15 | collection.AddSingleton(s => new GptClient(apiKey, organization));
16 | }
17 |
18 | public static void AddOpenAI(this IServiceCollection collection, string apiKey,
19 | IGptClientConfiguration configuration)
20 | {
21 | collection.AddSingleton(s => new GptClient(apiKey, configuration));
22 | }
23 |
24 | public static void AddOpenAI(this IServiceCollection collection, string apiKey,
25 | Action configuration)
26 | {
27 | var config = new DefaultGptClientConfiguration();
28 | configuration.Invoke(config);
29 | collection.AddSingleton(s => new GptClient(apiKey, config));
30 | }
31 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Extensions/ValidationExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace ManagedCode.OpenAI.Extensions;
4 |
5 | internal static class ValidationExtensions
6 | {
7 | public static void Validate(this object obj)
8 | {
9 | Validator.ValidateObject(obj, new ValidationContext(obj), true);
10 | }
11 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IBaseImageBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IBaseImageBuilder
4 | {
5 | public TBuilder SetImageResolution(string resolution);
6 | public TBuilder SetImageResolution(ImageResolution resolution);
7 |
8 | public TBuilder AsBase64String();
9 |
10 | public TBuilder AsUrl();
11 |
12 | public TBuilder SetUser(string user);
13 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IEditImageBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IEditImageBuilder : IBaseImageBuilder
4 | {
5 | public IEditImageBuilder SetImageMask(string base64);
6 |
7 | public Task> ExecuteAsync();
8 |
9 | public Task> ExecuteMultipleAsync(int count);
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IGenerateImageBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IGenerateImageBuilder : IBaseImageBuilder
4 | {
5 | public Task> ExecuteAsync();
6 |
7 | public Task> ExecuteMultipleAsync(int count);
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IGptImage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IGptImage
4 | {
5 | TData Content { get; }
6 |
7 | int Created { get; }
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IImageClient.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IImageClient
4 | {
5 | public IGenerateImageBuilder GenerateImage(string description);
6 |
7 | public IEditImageBuilder EditImage(string description, string imageBase64);
8 |
9 | public IVariationImageBuilder VariationImage(string imageBase64);
10 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IImageLoader.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IImageLoader
4 | {
5 | public string FromBytes(byte[] bytes);
6 |
7 | public string FromBase64(string base64);
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Abstractions/IVariationImageBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public interface IVariationImageBuilder : IBaseImageBuilder
4 | {
5 | public Task> ExecuteAsync();
6 |
7 | public Task> ExecuteMultipleAsync(int count);
8 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Builders/BaseImageBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API.Image;
2 | using ManagedCode.OpenAI.Extensions;
3 |
4 | namespace ManagedCode.OpenAI.Image;
5 |
6 | internal abstract class BaseImageBuilder : IBaseImageBuilder
7 | where TRequest : BaseImageRequestDto, new()
8 | where TBuilder : IBaseImageBuilder
9 | {
10 | protected BaseImageBuilder()
11 | {
12 | Request = new TRequest();
13 | }
14 |
15 | protected TRequest Request { get; }
16 |
17 | public TBuilder SetImageResolution(string resolution)
18 | {
19 | Request.Size = resolution;
20 | return Builder();
21 | }
22 |
23 | public TBuilder SetImageResolution(ImageResolution resolution)
24 | {
25 | Request.Size = resolution.Name();
26 | return Builder();
27 | }
28 |
29 | public TBuilder AsBase64String()
30 | {
31 | Request.ResponseFormat = ImageFormat.Base64Json.Name();
32 | return Builder();
33 | }
34 |
35 | public TBuilder AsUrl()
36 | {
37 | Request.ResponseFormat = ImageFormat.Url.Name();
38 | return Builder();
39 | }
40 |
41 | public TBuilder SetUser(string user)
42 | {
43 | Request.User = user;
44 | return Builder();
45 | }
46 |
47 | protected abstract TBuilder Builder();
48 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Builders/DefaultImageLoader.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | internal class DefaultImageLoader : IImageLoader
4 | {
5 | public string FromBytes(byte[] bytes)
6 | {
7 | return Convert.ToBase64String(bytes);
8 | }
9 |
10 | public string FromBase64(string base64)
11 | {
12 | return base64;
13 | }
14 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Builders/EditImageBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.API.Image;
3 | using ManagedCode.OpenAI.Extensions;
4 |
5 | namespace ManagedCode.OpenAI.Image;
6 |
7 | internal class EditImageBuilder : BaseImageBuilder,
8 | IEditImageBuilder
9 | {
10 | private readonly IOpenAiWebClient _webClient;
11 |
12 | public EditImageBuilder(IOpenAiWebClient webClient, string instruction, string imageB64)
13 | {
14 | _webClient = webClient;
15 | Request.Description = instruction;
16 | Request.ImageBase64 = imageB64;
17 | }
18 |
19 | public IEditImageBuilder SetImageMask(string base64)
20 | {
21 | Request.MaskBase64 = base64;
22 | return this;
23 | }
24 |
25 | public async Task> ExecuteAsync()
26 | {
27 | Request.Validate();
28 | var response = await _webClient.EditImageAsync(Request);
29 | return response.AsSingle();
30 | }
31 |
32 | public async Task> ExecuteMultipleAsync(int count)
33 | {
34 | Request.N = count;
35 | Request.Validate();
36 | var response = await _webClient.EditImageAsync(Request);
37 | return response.AsMultiple();
38 | }
39 |
40 | protected override IEditImageBuilder Builder()
41 | {
42 | return this;
43 | }
44 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Builders/GenerateImageBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.API.Image;
3 | using ManagedCode.OpenAI.Extensions;
4 |
5 | namespace ManagedCode.OpenAI.Image;
6 |
7 | internal class GenerateImageBuilder :
8 | BaseImageBuilder,
9 | IGenerateImageBuilder
10 | {
11 | private readonly IOpenAiWebClient _webClient;
12 |
13 | public GenerateImageBuilder(IOpenAiWebClient webClient, string description)
14 | {
15 | _webClient = webClient;
16 | Request.Description = description;
17 | }
18 |
19 | public async Task> ExecuteAsync()
20 | {
21 | Request.Validate();
22 | var response = await _webClient.GenerateImageAsync(Request);
23 | return response.AsSingle();
24 | }
25 |
26 | public async Task> ExecuteMultipleAsync(int count)
27 | {
28 | Request.N = count;
29 | Request.Validate();
30 | var response = await _webClient.GenerateImageAsync(Request);
31 | return response.AsMultiple();
32 | }
33 |
34 | protected override IGenerateImageBuilder Builder()
35 | {
36 | return this;
37 | }
38 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Builders/VariationImageBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.API.Image;
3 | using ManagedCode.OpenAI.Extensions;
4 |
5 | namespace ManagedCode.OpenAI.Image;
6 |
7 | internal class VariationImageBuilder : BaseImageBuilder,
8 | IVariationImageBuilder
9 | {
10 | private readonly IOpenAiWebClient _client;
11 |
12 | public VariationImageBuilder(IOpenAiWebClient client, string imageBase64)
13 | {
14 | _client = client;
15 | Request.ImageBase64 = imageBase64;
16 | }
17 |
18 |
19 | public async Task> ExecuteAsync()
20 | {
21 | Request.Validate();
22 | var response = await _client.VariationImageAsync(Request);
23 | return response.AsSingle();
24 | }
25 |
26 | public async Task> ExecuteMultipleAsync(int count)
27 | {
28 | Request.Validate();
29 | var response = await _client.VariationImageAsync(Request);
30 | return response.AsMultiple();
31 | }
32 |
33 | protected override IVariationImageBuilder Builder()
34 | {
35 | return this;
36 | }
37 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Extensions/ImageClientExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | public static class ImageClientExtensions
4 | {
5 | public static IEditImageBuilder EditImage(this IImageClient client,
6 | string instruction, Func image)
7 | {
8 | var loader = new DefaultImageLoader();
9 | return client.EditImage(instruction, image.Invoke(loader));
10 | }
11 |
12 | public static IVariationImageBuilder VariationImage(this IImageClient client,
13 | Func image)
14 | {
15 | var loader = new DefaultImageLoader();
16 | return client.VariationImage(image.Invoke(loader));
17 | }
18 |
19 | public static IEditImageBuilder SetImageMask(this IEditImageBuilder builder,
20 | Func image)
21 | {
22 | var loader = new DefaultImageLoader();
23 | builder.SetImageMask(image.Invoke(loader));
24 | return builder;
25 | }
26 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Extensions/MapperImageExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API.Image;
2 |
3 | namespace ManagedCode.OpenAI.Image;
4 |
5 | internal static class MapperImageExtensions
6 | {
7 | public static IGptImage AsSingle(this ImageResponseDto response)
8 | {
9 | return new GptImage
10 | {
11 | Content = ExtractContents(response).First(),
12 | Created = response.Created
13 | };
14 | }
15 |
16 | public static IGptImage AsMultiple(this ImageResponseDto response)
17 | {
18 | return new GptImage
19 | {
20 | Content = ExtractContents(response),
21 | Created = response.Created
22 | };
23 | }
24 |
25 | private static string[] ExtractContents(ImageResponseDto response)
26 | {
27 | if (!string.IsNullOrWhiteSpace(response.Data.First().Url))
28 | return response.Data.Select(x => x.Url).ToArray();
29 |
30 | if (!string.IsNullOrWhiteSpace(response.Data.First().B64Json))
31 | return response.Data.Select(x => x.B64Json).ToArray();
32 |
33 | throw new ArgumentNullException("Failed to get image content");
34 | }
35 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/ImageClient.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 |
3 | namespace ManagedCode.OpenAI.Image;
4 |
5 | internal class ImageClient : IImageClient
6 | {
7 | private readonly IOpenAiWebClient _webClient;
8 |
9 | public ImageClient(IOpenAiWebClient webClient)
10 | {
11 | _webClient = webClient;
12 | }
13 |
14 | public IGenerateImageBuilder GenerateImage(string description)
15 | {
16 | return new GenerateImageBuilder(_webClient, description);
17 | }
18 |
19 | public IEditImageBuilder EditImage(string description, string imageBase64)
20 | {
21 | return new EditImageBuilder(_webClient, description, imageBase64);
22 | }
23 |
24 | public IVariationImageBuilder VariationImage(string imageBase64)
25 | {
26 | return new VariationImageBuilder(_webClient, imageBase64);
27 | }
28 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Models/GptImage.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Image;
2 |
3 | internal class GptImage : IGptImage
4 | {
5 | public required TData Content { get; set; }
6 | public required int Created { get; set; }
7 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Models/ImageFormat.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Runtime.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.Image;
5 |
6 | public enum ImageFormat
7 | {
8 | [EnumMember(Value = "url")]
9 | [Description("url")]
10 | Url,
11 |
12 | [EnumMember(Value = "b64_json")]
13 | [Description("b64_json")]
14 | Base64Json
15 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Image/Models/ImageResolution.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Runtime.Serialization;
3 |
4 | namespace ManagedCode.OpenAI.Image;
5 |
6 | public enum ImageResolution
7 | {
8 | [EnumMember(Value = "256x256")]
9 | [Description("256x256")]
10 | _256x256,
11 |
12 | [EnumMember(Value = "512x512")]
13 | [Description("512x512")]
14 | _512x512,
15 |
16 | [EnumMember(Value = "1024x1024")]
17 | [Description("1024x1024")]
18 | _1024x1024
19 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/ManagedCode.OpenAI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 | true
8 | 11
9 |
10 |
11 |
12 |
13 | ManagedCode.OpenAI
14 | ManagedCode.OpenAI
15 | OpenAI
16 | managedcode, OpenAI, ChatGPT, API
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/ManagedCode.OpenAI.csproj.DotSettings:
--------------------------------------------------------------------------------
1 |
5 | True
7 | True
9 | True
11 | True
13 | True
15 | True
17 | True
19 | True
21 | True
23 | True
25 | True
27 | True
29 | True
31 | True
33 | True
35 | True
37 | True
39 | True
41 | True
43 | True
45 | True
47 | True
49 | True
51 | True
53 | True
55 | True
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Abstractions/ICategory.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Moderation;
2 |
3 | public interface ICategory where TResult : struct
4 | {
5 | public TResult Hate { get; }
6 | public TResult HateThreatening { get; }
7 | public TResult SelfHarm { get; }
8 | public TResult Sexual { get; }
9 | public TResult SexualMinors { get; }
10 | public TResult Violence { get; }
11 | public TResult ViolenceGraphic { get; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Abstractions/IModeration.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Moderation;
2 |
3 | public interface IModeration
4 | {
5 | ICategory Categories { get; }
6 | ICategory CategoryScores { get; }
7 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Abstractions/IModerationBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.Client;
2 |
3 | namespace ManagedCode.OpenAI.Moderation;
4 |
5 | public interface IModerationBuilder
6 | {
7 | public IModerationBuilder SetModel(string model);
8 | public IModerationBuilder SetModel(GptModel model);
9 |
10 | public Task ExecuteAsync(string input);
11 | public Task ExecuteMultipleAsync(params string[] inputs);
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Exceptions/MapperModerationExtensions.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API.Moderation;
2 |
3 | namespace ManagedCode.OpenAI.Moderation;
4 |
5 | internal static class MapperModerationExtensions
6 | {
7 | public static ICategory ToCategory(this CategoryDto dto) where TResult : struct
8 | {
9 | return new Category
10 | {
11 | Hate = dto.Hate,
12 | HateThreatening = dto.HateThreatening,
13 | SelfHarm = dto.SelfHarm,
14 | Sexual = dto.Sexual,
15 | SexualMinors = dto.SexualMinors,
16 | Violence = dto.Violence,
17 | ViolenceGraphic = dto.ViolenceGraphic
18 | };
19 | }
20 |
21 | private static IModeration ToModeration(this CategoryResultDto dto)
22 | {
23 | return new Moderation
24 | {
25 | Categories = dto.Categories.ToCategory(),
26 | CategoryScores = dto.CategoryScores.ToCategory()
27 | };
28 | }
29 |
30 |
31 | public static IModeration ToModeration(this ModerationResponseDto dto)
32 | {
33 | return dto.Results.First().ToModeration();
34 | }
35 |
36 | public static IModeration[] ToModerationCollection(this ModerationResponseDto dto)
37 | {
38 | return dto.Results.Select(e => e.ToModeration()).ToArray();
39 | }
40 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Model/Category.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Moderation;
2 |
3 | internal class Category : ICategory where TResult : struct
4 | {
5 | public required TResult Hate { get; set; }
6 | public required TResult HateThreatening { get; set; }
7 | public required TResult SelfHarm { get; set; }
8 | public required TResult Sexual { get; set; }
9 | public required TResult SexualMinors { get; set; }
10 | public required TResult Violence { get; set; }
11 | public required TResult ViolenceGraphic { get; set; }
12 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/Model/Moderation.cs:
--------------------------------------------------------------------------------
1 | namespace ManagedCode.OpenAI.Moderation;
2 |
3 | public class Moderation : IModeration
4 | {
5 | public required ICategory Categories { get; set; }
6 | public required ICategory CategoryScores { get; set; }
7 | }
--------------------------------------------------------------------------------
/ManagedCode.OpenAI/Moderation/ModerationBuilder.cs:
--------------------------------------------------------------------------------
1 | using ManagedCode.OpenAI.API;
2 | using ManagedCode.OpenAI.API.Moderation;
3 | using ManagedCode.OpenAI.Client;
4 | using ManagedCode.OpenAI.Extensions;
5 |
6 | namespace ManagedCode.OpenAI.Moderation;
7 |
8 | internal class ModerationBuilder : IModerationBuilder
9 | {
10 | private const GptModel DEFAULT_MODEL = GptModel.TextModerationStable;
11 | private readonly IOpenAiWebClient _client;
12 | private readonly ModerationRequestDto _requestDto;
13 |
14 | public ModerationBuilder(IOpenAiWebClient client)
15 | {
16 | _client = client;
17 | _requestDto = new ModerationRequestDto
18 | {
19 | Model = DEFAULT_MODEL.Name()
20 | };
21 | }
22 |
23 | public IModerationBuilder SetModel(string model)
24 | {
25 | _requestDto.Model = model;
26 | return this;
27 | }
28 |
29 | public IModerationBuilder SetModel(GptModel model)
30 | {
31 | return SetModel(model.Name());
32 | }
33 |
34 | public async Task ExecuteAsync(string input)
35 | {
36 | _requestDto.Input = new List { input };
37 | var moderationResponseDto = await _client.ModerationAsync(_requestDto);
38 | return moderationResponseDto.ToModeration();
39 | }
40 |
41 | public async Task ExecuteMultipleAsync(params string[] inputs)
42 | {
43 | _requestDto.Input = inputs.ToList();
44 | var moderationResponseDto = await _client.ModerationAsync(_requestDto);
45 | return moderationResponseDto.ToModerationCollection();
46 | }
47 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenAI
2 |
3 | This is an unofficial C# library for the OpenAI API. As there are no official libraries available, we have created our
4 | own to help C# developers interact with the API easily.
5 |
6 | [](https://github.com/managedcode/OpenAI/actions/workflows/dotnet.yml)
7 | [](https://coveralls.io/github/managedcode/OpenAI?branch=main)
8 | [](https://github.com/managedcode/Communication/actions/workflows/nuget.yml)
9 | [](https://github.com/managedcode/OpenAI/actions/workflows/codeql-analysis.yml)
10 | [](https://www.nuget.org/packages/ManagedCode.OpenAI)
11 |
12 | ## Installation
13 |
14 | To install the ManagedCode.OpenAI library from NuGet, you can use the following methods:
15 |
16 | ### Package Manager
17 |
18 | Open the Package Manager Console in Visual Studio and run the following command:
19 |
20 | ```
21 | Install-Package ManagedCode.OpenAI
22 | ```
23 |
24 | ### .NET CLI
25 |
26 | You can also use the .NET CLI to install the package. Open a terminal/command prompt and run the following command:
27 |
28 | ```
29 | dotnet add package ManagedCode.OpenAI
30 | ```
31 |
32 | ## Usage
33 |
34 | Initializing the client
35 | You can initialize the client in two ways:
36 |
37 | ``` cs
38 | var client1 = GptClient.Builder("#API_KEY#")
39 | .WithOrganization("#ORGANIZATION#")
40 | .Build();
41 | ```
42 |
43 | ```cs
44 | var client2 = GptClient.Builder("#API_KEY#")
45 | .WithOrganization("#ORGANIZATION#")
46 | .Configure(x => x.SetDefaultModel(GptModel.Ada))
47 | .Build();
48 | ```
49 |
50 | or using DI
51 |
52 | ```cs
53 | builder.Services.AddOpenAI("#API_KEY#");
54 |
55 | public class MyClass
56 | {
57 | public MyClass(IGptClient client)
58 | {
59 | var chat = client.OpenChat();
60 | }
61 | }
62 | ```
63 |
64 | ## Ask chat gpt
65 |
66 | ``` cs
67 | var client = GptClient.Builder("#API_KEY#")
68 | .WithOrganization("#ORGANIZATION#")
69 | .Build();
70 | var chat = client.OpenChat();
71 | var answer = await chat.AskAsync("2+2?");
72 | Console.WriteLine($"Answer: {answer.Data.Content}");
73 | ```
74 |
75 | ## Generating an image URL
76 |
77 | ```cs
78 | var client = new GptClient("#API_KEY#");
79 | var img = await client.ImageClient
80 | .GenerateImage("Big man")
81 | .AsUrl().ExecuteAsync();
82 |
83 | var url = img.Content;
84 | Console.WriteLine(url);
85 | ```
86 |
87 | ### Generating an image URL with editing
88 |
89 | ```cs
90 | var client = new GptClient("#API_KEY#");
91 | var imgBytes = new byte[] { };
92 | var maskBase64 = "#CONTENT#";
93 |
94 | var img = await client.ImageClient
95 | .EditImage("Change color to red", x => x.FromBytes(imgBytes))
96 | .SetImageMask(x => x.FromBase64(maskBase64))
97 | .AsUrl().ExecuteAsync();
98 |
99 | // Edited img URL
100 | Console.WriteLine(img.Content);
101 | ```
102 |
103 | ### Editing an image using a mask
104 |
105 | ```cs
106 | var client = new GptClient("#API_KEY#");
107 | var imgBytes = new byte[] { };
108 | var imgCollection = await client.ImageClient
109 | .VariationImage(x => x.FromBytes(imgBytes))
110 | .AsBase64String()
111 | .ExecuteMultipleAsync(5);
112 |
113 | foreach (var imageBase64 in imgCollection.Content)
114 | Console.WriteLine(imageBase64);
115 | ```
116 |
117 | ## Generating multiple image variations as base64 strings
118 |
119 | Create multiple variations of an image in base64 string format with 5 results:
120 |
121 | ```cs
122 | var client = new GptClient("#API_KEY#");
123 | var imgBytes = new byte[] { };
124 | var imgCollection = await client.ImageClient
125 | .VariationImage(x => x.FromBytes(imgBytes))
126 | .AsBase64String()
127 | .ExecuteMultipleAsync(5);
128 |
129 | foreach (var imageBase64 in imgCollection.Content)
130 | Console.WriteLine(imageBase64);
131 | ```
132 |
133 | ## Contributing
134 |
135 | We welcome contributions to this project. Please submit a pull request or create an issue if you'd like to help improve
136 | this library.
137 |
138 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/managedcode/OpenAI/1418997288050139d499bc1f36b24575227b8f24/logo.png
--------------------------------------------------------------------------------