├── .gitignore
├── .idea
└── .idea.ChatGPT-API-unity
│ └── .idea
│ ├── .gitignore
│ ├── indexLayout.xml
│ └── vcs.xml
├── Assets
├── Mochineko.meta
└── Mochineko
│ ├── ChatGPT_API.Memory.Tests.meta
│ ├── ChatGPT_API.Memory.Tests
│ ├── ChatMemoryExtensions.cs
│ ├── ChatMemoryExtensions.cs.meta
│ ├── FiniteQueueChatMemoryTest.cs
│ ├── FiniteQueueChatMemoryTest.cs.meta
│ ├── FiniteQueueWithFixedPromptsChatMemoryTest.cs
│ ├── FiniteQueueWithFixedPromptsChatMemoryTest.cs.meta
│ ├── FiniteTokenLengthChatMemoryTest.cs
│ ├── FiniteTokenLengthChatMemoryTest.cs.meta
│ ├── FiniteTokenLengthWithFixedPromptsChatMemoryTest.cs
│ ├── FiniteTokenLengthWithFixedPromptsChatMemoryTest.cs.meta
│ ├── Mochineko.ChatGPT_API.Memory.Tests.asmdef
│ └── Mochineko.ChatGPT_API.Memory.Tests.asmdef.meta
│ ├── ChatGPT_API.Relent.Samples.meta
│ ├── ChatGPT_API.Relent.Samples
│ ├── Mochineko.ChatGPT_API.Relent.Samples.asmdef
│ ├── Mochineko.ChatGPT_API.Relent.Samples.asmdef.meta
│ ├── RelentChatCompletionSample.cs
│ ├── RelentChatCompletionSample.cs.meta
│ ├── RelentChatCompletionStreamSample.cs
│ └── RelentChatCompletionStreamSample.cs.meta
│ ├── ChatGPT_API.Relent.Tests.meta
│ ├── ChatGPT_API.Relent.Tests
│ ├── Mochineko.ChatGPT_API.Relent.Tests.asmdef
│ ├── Mochineko.ChatGPT_API.Relent.Tests.asmdef.meta
│ ├── RelentChatCompletionAPIConnectionTest.cs
│ └── RelentChatCompletionAPIConnectionTest.cs.meta
│ ├── ChatGPT_API.Relent.meta
│ ├── ChatGPT_API.Relent
│ ├── JsonSerializer.cs
│ ├── JsonSerializer.cs.meta
│ ├── LICENSE
│ ├── LICENSE.meta
│ ├── Mochineko.ChatGPT_API.Relent.asmdef
│ ├── Mochineko.ChatGPT_API.Relent.asmdef.meta
│ ├── RelentChatCompletionAPIConnection.cs
│ ├── RelentChatCompletionAPIConnection.cs.meta
│ ├── package.json
│ └── package.json.meta
│ ├── ChatGPT_API.Samples.meta
│ ├── ChatGPT_API.Samples
│ ├── ChatCompletionAsStreamSample.cs
│ ├── ChatCompletionAsStreamSample.cs.meta
│ ├── ChatCompletionSample.cs
│ ├── ChatCompletionSample.cs.meta
│ ├── ChatCompletionSample.unity
│ ├── ChatCompletionSample.unity.meta
│ ├── ChatCompletionStreamSample.unity
│ ├── ChatCompletionStreamSample.unity.meta
│ ├── Mochineko.ChatGPT_API.Samples.asmdef
│ └── Mochineko.ChatGPT_API.Samples.asmdef.meta
│ ├── ChatGPT_API.Tests.meta
│ ├── ChatGPT_API.Tests
│ ├── ChatCompletionAPIConnectionTest.cs
│ ├── ChatCompletionAPIConnectionTest.cs.meta
│ ├── Mochineko.ChatGPT_API.Tests.asmdef
│ ├── Mochineko.ChatGPT_API.Tests.asmdef.meta
│ ├── ModelTest.cs
│ ├── ModelTest.cs.meta
│ ├── RoleTest.cs
│ └── RoleTest.cs.meta
│ ├── ChatGPT_API.meta
│ ├── ChatGPT_API
│ ├── APIErrorException.cs
│ ├── APIErrorException.cs.meta
│ ├── AssemblyInfo.cs
│ ├── AssemblyInfo.cs.meta
│ ├── ChatCompletionAPIConnection.cs
│ ├── ChatCompletionAPIConnection.cs.meta
│ ├── ChatCompletionRequestBody.cs
│ ├── ChatCompletionRequestBody.cs.meta
│ ├── ChatCompletionResponseBody.cs
│ ├── ChatCompletionResponseBody.cs.meta
│ ├── ChatCompletionStreamResponseChunk.cs
│ ├── ChatCompletionStreamResponseChunk.cs.meta
│ ├── Choice.cs
│ ├── Choice.cs.meta
│ ├── ChoiceChunk.cs
│ ├── ChoiceChunk.cs.meta
│ ├── Delta.cs
│ ├── Delta.cs.meta
│ ├── Function.cs
│ ├── Function.cs.meta
│ ├── FunctionCall.cs
│ ├── FunctionCall.cs.meta
│ ├── FunctionCallSpecifying.cs
│ ├── FunctionCallSpecifying.cs.meta
│ ├── HttpClientPool.cs
│ ├── HttpClientPool.cs.meta
│ ├── IChatMemory.cs
│ ├── IChatMemory.cs.meta
│ ├── InverseDictionaryExtension.cs
│ ├── InverseDictionaryExtension.cs.meta
│ ├── LICENSE
│ ├── LICENSE.meta
│ ├── Memory.meta
│ ├── Memory
│ │ ├── FiniteQueueChatMemory.cs
│ │ ├── FiniteQueueChatMemory.cs.meta
│ │ ├── FiniteQueueWithFixedPromptsChatMemory.cs
│ │ ├── FiniteQueueWithFixedPromptsChatMemory.cs.meta
│ │ ├── FiniteTokenLengthQueueChatMemory.cs
│ │ ├── FiniteTokenLengthQueueChatMemory.cs.meta
│ │ ├── FiniteTokenLengthQueueWithFixedPromptsChatMemory.cs
│ │ ├── FiniteTokenLengthQueueWithFixedPromptsChatMemory.cs.meta
│ │ ├── Mochineko.ChatGPT_API.Memory.asmdef
│ │ ├── Mochineko.ChatGPT_API.Memory.asmdef.meta
│ │ ├── TokenizerExtensions.cs
│ │ └── TokenizerExtensions.cs.meta
│ ├── Message.cs
│ ├── Message.cs.meta
│ ├── Mochineko.ChatGPT_API.asmdef
│ ├── Mochineko.ChatGPT_API.asmdef.meta
│ ├── Model.cs
│ ├── Model.cs.meta
│ ├── ModelResolver.cs
│ ├── ModelResolver.cs.meta
│ ├── Role.cs
│ ├── Role.cs.meta
│ ├── RoleResolver.cs
│ ├── RoleResolver.cs.meta
│ ├── SimpleChatMemory.cs
│ ├── SimpleChatMemory.cs.meta
│ ├── TiktokenSharp.meta
│ ├── TiktokenSharp
│ │ ├── CoreBPE.cs
│ │ ├── CoreBPE.cs.meta
│ │ ├── Editor.meta
│ │ ├── Editor
│ │ │ ├── Mochineko.TiktokenSharp.Editor.asmdef
│ │ │ ├── Mochineko.TiktokenSharp.Editor.asmdef.meta
│ │ │ ├── TiktokenEditor.cs
│ │ │ └── TiktokenEditor.cs.meta
│ │ ├── LICENSE.txt
│ │ ├── LICENSE.txt.meta
│ │ ├── Mochineko.TiktokenSharp.asmdef
│ │ ├── Mochineko.TiktokenSharp.asmdef.meta
│ │ ├── Model.meta
│ │ ├── Model
│ │ │ ├── EncodingSettingModel.cs
│ │ │ └── EncodingSettingModel.cs.meta
│ │ ├── Services.meta
│ │ ├── Services
│ │ │ ├── EncodingManager.cs
│ │ │ └── EncodingManager.cs.meta
│ │ ├── TikToken.cs
│ │ ├── TikToken.cs.meta
│ │ ├── Utils.meta
│ │ └── Utils
│ │ │ ├── ByteArrayComparer.cs
│ │ │ ├── ByteArrayComparer.cs.meta
│ │ │ ├── BytePairEncoding.cs
│ │ │ └── BytePairEncoding.cs.meta
│ ├── ToolCalling.cs
│ ├── ToolCalling.cs.meta
│ ├── ToolFunction.cs
│ ├── ToolFunction.cs.meta
│ ├── Usage.cs
│ ├── Usage.cs.meta
│ ├── package.json
│ └── package.json.meta
│ ├── TiktokenSharp.Tests.meta
│ └── TiktokenSharp.Tests
│ ├── Mochineko.TiktokenSharp.Tests.asmdef
│ ├── Mochineko.TiktokenSharp.Tests.asmdef.meta
│ ├── TiktokenTest.cs
│ └── TiktokenTest.cs.meta
├── CHANGELOG.md
├── LICENSE
├── NOTICE.md
├── Packages
├── manifest.json
└── packages-lock.json
├── ProjectSettings
├── AudioManager.asset
├── ClusterInputManager.asset
├── DynamicsManager.asset
├── EditorBuildSettings.asset
├── EditorSettings.asset
├── GraphicsSettings.asset
├── InputManager.asset
├── MemorySettings.asset
├── NavMeshAreas.asset
├── PackageManagerSettings.asset
├── Packages
│ └── com.unity.testtools.codecoverage
│ │ └── Settings.json
├── Physics2DSettings.asset
├── PresetManager.asset
├── ProjectSettings.asset
├── ProjectVersion.txt
├── QualitySettings.asset
├── RiderScriptEditorPersistedState.asset
├── TagManager.asset
├── TimeManager.asset
├── UnityConnectSettings.asset
├── VFXManager.asset
├── VersionControlSettings.asset
├── XRSettings.asset
└── boot.config
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Uu]ser[Ss]ettings/
12 |
13 | # MemoryCaptures can get excessive in size.
14 | # They also could contain extremely sensitive data
15 | /[Mm]emoryCaptures/
16 |
17 | # Recordings can get excessive in size
18 | /[Rr]ecordings/
19 |
20 | # Uncomment this line if you wish to ignore the asset store tools plugin
21 | # /[Aa]ssets/AssetStoreTools*
22 |
23 | # Autogenerated Jetbrains Rider plugin
24 | /[Aa]ssets/Plugins/Editor/JetBrains*
25 |
26 | # Visual Studio cache directory
27 | .vs/
28 |
29 | # Gradle cache directory
30 | .gradle/
31 |
32 | # Autogenerated VS/MD/Consulo solution and project files
33 | ExportedObj/
34 | .consulo/
35 | *.csproj
36 | *.unityproj
37 | *.sln
38 | *.suo
39 | *.tmp
40 | *.user
41 | *.userprefs
42 | *.pidb
43 | *.booproj
44 | *.svd
45 | *.pdb
46 | *.mdb
47 | *.opendb
48 | *.VC.db
49 |
50 | # Unity3D generated meta files
51 | *.pidb.meta
52 | *.pdb.meta
53 | *.mdb.meta
54 |
55 | # Unity3D generated file on crash reports
56 | sysinfo.txt
57 |
58 | # Builds
59 | *.apk
60 | *.aab
61 | *.unitypackage
62 | *.app
63 |
64 | # Crashlytics generated file
65 | crashlytics-build.properties
66 |
67 | # Packed Addressables
68 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
69 |
70 | # Temporary auto-generated Android Assets
71 | /[Aa]ssets/[Ss]treamingAssets/aa.meta
72 | /[Aa]ssets/[Ss]treamingAssets/aa/*
73 |
74 | # macOS
75 | .DS_Store
76 |
77 | # OpenAI API Key
78 | /[Aa]ssets/Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt
79 | /[Aa]ssets/Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt.meta
--------------------------------------------------------------------------------
/.idea/.idea.ChatGPT-API-unity/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /projectSettingsUpdater.xml
6 | /contentModel.xml
7 | /.idea.ChatGPT-API-unity.iml
8 | /modules.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/.idea/.idea.ChatGPT-API-unity/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/.idea.ChatGPT-API-unity/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Assets/Mochineko.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c7e92bf186aba43b4823a7846d177b84
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0f488dc2d4cd45fea84b3ffd604d9d2
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/ChatMemoryExtensions.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using FluentAssertions;
4 |
5 | namespace Mochineko.ChatGPT_API.Memory.Tests
6 | {
7 | internal static class ChatMemoryExtensions
8 | {
9 | internal static void ShouldBeSameContentsAs(this IChatMemory memory, IReadOnlyList expected)
10 | {
11 | var messages = memory.Messages;
12 |
13 | messages.Count.Should().Be(expected.Count);
14 |
15 | for (var i = 0; i < messages.Count; i++)
16 | {
17 | var message = messages[i];
18 | var contentMessage = expected[i];
19 |
20 | message.Role.Should().Be(contentMessage.Role);
21 | message.RoleString.Should().Be(contentMessage.RoleString);
22 | message.Content.Should().Be(contentMessage.Content);
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/ChatMemoryExtensions.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 34aa070631dd54cb8bf51b1a66dd7ef6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteQueueChatMemoryTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using NUnit.Framework;
6 | using UnityEngine.TestTools;
7 |
8 | namespace Mochineko.ChatGPT_API.Memory.Tests
9 | {
10 | [TestFixture]
11 | internal sealed class FiniteQueueChatMemoryTest
12 | {
13 | [Test]
14 | [RequiresPlayMode(false)]
15 | public async Task MemoriesShouldBeUpToCapacity()
16 | {
17 | var memory = new FiniteQueueChatMemory(3);
18 | memory.ShouldBeSameContentsAs(new List());
19 |
20 | await memory.AddMessageAsync(new Message(Role.User, "a"), CancellationToken.None);
21 | memory.ShouldBeSameContentsAs(new[]
22 | {
23 | new Message(Role.User, "a"),
24 | });
25 |
26 | await memory.AddMessageAsync(new Message(Role.Assistant, "b"), CancellationToken.None);
27 | memory.ShouldBeSameContentsAs(new[]
28 | {
29 | new Message(Role.User, "a"),
30 | new Message(Role.Assistant, "b"),
31 | });
32 |
33 | await memory.AddMessageAsync(new Message(Role.User, "c"), CancellationToken.None);
34 | memory.ShouldBeSameContentsAs(new[]
35 | {
36 | new Message(Role.User, "a"),
37 | new Message(Role.Assistant, "b"),
38 | new Message(Role.User, "c"),
39 | });
40 |
41 | // Up to capacity
42 | await memory.AddMessageAsync(new Message(Role.Assistant, "d"), CancellationToken.None);
43 | memory.ShouldBeSameContentsAs(new[]
44 | {
45 | new Message(Role.Assistant, "b"),
46 | new Message(Role.User, "c"),
47 | new Message(Role.Assistant, "d"),
48 | });
49 |
50 | await memory.AddMessageAsync(new Message(Role.User, "e"), CancellationToken.None);
51 | memory.ShouldBeSameContentsAs(new[]
52 | {
53 | new Message(Role.User, "c"),
54 | new Message(Role.Assistant, "d"),
55 | new Message(Role.User, "e"),
56 | });
57 |
58 | memory.ClearAllMessages();
59 | memory.ShouldBeSameContentsAs(new List());
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteQueueChatMemoryTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7e2f61e5c6cc24cbb8c21067b58c023c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteQueueWithFixedPromptsChatMemoryTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using NUnit.Framework;
6 | using UnityEngine.TestTools;
7 |
8 | namespace Mochineko.ChatGPT_API.Memory.Tests
9 | {
10 | [TestFixture]
11 | internal sealed class FiniteQueueWithFixedPromptsChatMemoryTest
12 | {
13 | [Test]
14 | [RequiresPlayMode(false)]
15 | public async Task MemoriesShouldBeUpToCapacityWithFixedPrompts()
16 | {
17 | var memory = new FiniteQueueWithFixedPromptsChatMemory(3);
18 | memory.ShouldBeSameContentsAs(new List());
19 |
20 | await memory.AddMessageAsync(new Message(Role.System, "prompt"), CancellationToken.None);
21 | memory.ShouldBeSameContentsAs(new[]
22 | {
23 | new Message(Role.System, "prompt"),
24 | });
25 |
26 | await memory.AddMessageAsync(new Message(Role.User, "a"), CancellationToken.None);
27 | memory.ShouldBeSameContentsAs(new[]
28 | {
29 | new Message(Role.System, "prompt"),
30 | new Message(Role.User, "a"),
31 | });
32 |
33 | await memory.AddMessageAsync(new Message(Role.Assistant, "b"), CancellationToken.None);
34 | memory.ShouldBeSameContentsAs(new[]
35 | {
36 | new Message(Role.System, "prompt"),
37 | new Message(Role.User, "a"),
38 | new Message(Role.Assistant, "b"),
39 | });
40 |
41 | // System messages are not counted as capacity
42 | await memory.AddMessageAsync(new Message(Role.User, "c"), CancellationToken.None);
43 | memory.ShouldBeSameContentsAs(new[]
44 | {
45 | new Message(Role.System, "prompt"),
46 | new Message(Role.User, "a"),
47 | new Message(Role.Assistant, "b"),
48 | new Message(Role.User, "c"),
49 | });
50 |
51 | await memory.AddMessageAsync(new Message(Role.Assistant, "d"), CancellationToken.None);
52 | memory.ShouldBeSameContentsAs(new[]
53 | {
54 | new Message(Role.System, "prompt"),
55 | new Message(Role.Assistant, "b"),
56 | new Message(Role.User, "c"),
57 | new Message(Role.Assistant, "d"),
58 | });
59 |
60 | await memory.AddMessageAsync(new Message(Role.User, "e"), CancellationToken.None);
61 | memory.ShouldBeSameContentsAs(new[]
62 | {
63 | new Message(Role.System, "prompt"),
64 | new Message(Role.User, "c"),
65 | new Message(Role.Assistant, "d"),
66 | new Message(Role.User, "e"),
67 | });
68 |
69 | memory.ClearMessagesWithoutPrompts();
70 | memory.ShouldBeSameContentsAs(new[]
71 | {
72 | new Message(Role.System, "prompt"),
73 | });
74 |
75 | await memory.AddMessageAsync(new Message(Role.User, "f"), CancellationToken.None);
76 | memory.ShouldBeSameContentsAs(new[]
77 | {
78 | new Message(Role.System, "prompt"),
79 | new Message(Role.User, "f"),
80 | });
81 |
82 | await memory.AddMessageAsync(new Message(Role.System, "second prompt"), CancellationToken.None);
83 | memory.ShouldBeSameContentsAs(new[]
84 | {
85 | new Message(Role.System, "prompt"),
86 | new Message(Role.System, "second prompt"),
87 | new Message(Role.User, "f"),
88 | });
89 |
90 | await memory.AddMessageAsync(new Message(Role.Assistant, "g"), CancellationToken.None);
91 | memory.ShouldBeSameContentsAs(new[]
92 | {
93 | new Message(Role.System, "prompt"),
94 | new Message(Role.System, "second prompt"),
95 | new Message(Role.User, "f"),
96 | new Message(Role.Assistant, "g"),
97 | });
98 |
99 | memory.ClearAllMessages();
100 | memory.ShouldBeSameContentsAs(new List());
101 | }
102 |
103 | [Test]
104 | [RequiresPlayMode(false)]
105 | public async Task ShouldBeSameBehaviourWhenHasNoPrompts()
106 | {
107 | var memory = new FiniteQueueWithFixedPromptsChatMemory(3);
108 | memory.ShouldBeSameContentsAs(new List());
109 |
110 | await memory.AddMessageAsync(new Message(Role.User, "a"), CancellationToken.None);
111 | memory.ShouldBeSameContentsAs(new[]
112 | {
113 | new Message(Role.User, "a"),
114 | });
115 |
116 | await memory.AddMessageAsync(new Message(Role.Assistant, "b"), CancellationToken.None);
117 | memory.ShouldBeSameContentsAs(new[]
118 | {
119 | new Message(Role.User, "a"),
120 | new Message(Role.Assistant, "b"),
121 | });
122 |
123 | await memory.AddMessageAsync(new Message(Role.User, "c"), CancellationToken.None);
124 | memory.ShouldBeSameContentsAs(new[]
125 | {
126 | new Message(Role.User, "a"),
127 | new Message(Role.Assistant, "b"),
128 | new Message(Role.User, "c"),
129 | });
130 |
131 | // Up to capacity
132 | await memory.AddMessageAsync(new Message(Role.Assistant, "d"), CancellationToken.None);
133 | memory.ShouldBeSameContentsAs(new[]
134 | {
135 | new Message(Role.Assistant, "b"),
136 | new Message(Role.User, "c"),
137 | new Message(Role.Assistant, "d"),
138 | });
139 |
140 | await memory.AddMessageAsync(new Message(Role.User, "e"), CancellationToken.None);
141 | memory.ShouldBeSameContentsAs(new[]
142 | {
143 | new Message(Role.User, "c"),
144 | new Message(Role.Assistant, "d"),
145 | new Message(Role.User, "e"),
146 | });
147 |
148 | memory.ClearAllMessages();
149 | memory.ShouldBeSameContentsAs(new List());
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteQueueWithFixedPromptsChatMemoryTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 923750e718e0c46babeca4654df11983
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteTokenLengthChatMemoryTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using FluentAssertions;
6 | using NUnit.Framework;
7 | using UnityEngine.TestTools;
8 |
9 | namespace Mochineko.ChatGPT_API.Memory.Tests
10 | {
11 | [TestFixture]
12 | internal sealed class FiniteTokenLengthChatMemoryTest
13 | {
14 | [Test]
15 | [RequiresPlayMode(false)]
16 | public async Task MemoriesTokenLengthShouldBeUpToCapacity()
17 | {
18 | var memory = new FiniteTokenLengthQueueChatMemory(10, Model.Turbo);
19 | memory.TokenLength.Should().Be(0);
20 | memory.ShouldBeSameContentsAs(new List());
21 |
22 | await memory.AddMessageAsync(new Message(Role.User, "a"), CancellationToken.None);
23 | memory.TokenLength.Should().Be(1);
24 | memory.ShouldBeSameContentsAs(new[]
25 | {
26 | new Message(Role.User, "a"),
27 | });
28 |
29 | await memory.AddMessageAsync(new Message(Role.User, "b"), CancellationToken.None);
30 | memory.TokenLength.Should().Be(2);
31 | memory.ShouldBeSameContentsAs(new[]
32 | {
33 | new Message(Role.User, "a"),
34 | new Message(Role.User, "b"),
35 | });
36 |
37 | await memory.AddMessageAsync(new Message(Role.User, "c d e f g h i j"), CancellationToken.None);
38 | memory.TokenLength.Should().Be(10);
39 | memory.ShouldBeSameContentsAs(new[]
40 | {
41 | new Message(Role.User, "a"),
42 | new Message(Role.User, "b"),
43 | new Message(Role.User, "c d e f g h i j"),
44 | });
45 |
46 | await memory.AddMessageAsync(new Message(Role.User, "k"), CancellationToken.None);
47 | memory.TokenLength.Should().Be(10);
48 | memory.ShouldBeSameContentsAs(new[]
49 | {
50 | new Message(Role.User, "b"),
51 | new Message(Role.User, "c d e f g h i j"),
52 | new Message(Role.User, "k"),
53 | });
54 |
55 | await memory.AddMessageAsync(new Message(Role.User, "l m n o p"), CancellationToken.None);
56 | memory.TokenLength.Should().Be(6);
57 | memory.ShouldBeSameContentsAs(new[]
58 | {
59 | new Message(Role.User, "k"),
60 | new Message(Role.User, "l m n o p"),
61 | });
62 |
63 | await memory.AddMessageAsync(new Message(Role.User, "q"), CancellationToken.None);
64 | memory.TokenLength.Should().Be(7);
65 | memory.ShouldBeSameContentsAs(new[]
66 | {
67 | new Message(Role.User, "k"),
68 | new Message(Role.User, "l m n o p"),
69 | new Message(Role.User, "q"),
70 | });
71 |
72 | await memory.AddMessageAsync(new Message(Role.User, "r"), CancellationToken.None);
73 | memory.TokenLength.Should().Be(8);
74 | memory.ShouldBeSameContentsAs(new[]
75 | {
76 | new Message(Role.User, "k"),
77 | new Message(Role.User, "l m n o p"),
78 | new Message(Role.User, "q"),
79 | new Message(Role.User, "r"),
80 | });
81 |
82 | await memory.AddMessageAsync(new Message(Role.User, "1 2 3 4 5 "), CancellationToken.None);
83 | memory.TokenLength.Should().Be(10);
84 | memory.ShouldBeSameContentsAs(new[]
85 | {
86 | new Message(Role.User, "1 2 3 4 5 "),
87 | });
88 |
89 | memory.ClearAllMessages();
90 | memory.TokenLength.Should().Be(0);
91 | memory.ShouldBeSameContentsAs(new List());
92 | }
93 | }
94 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteTokenLengthChatMemoryTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 94ecd6dbb26ff439d9c30b796c2d662d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/FiniteTokenLengthWithFixedPromptsChatMemoryTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19f518e1afc5744bca328e9fbfa2e418
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/Mochineko.ChatGPT_API.Memory.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Memory.Tests",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:27619889b8ba8c24980f49ee34dbb44a",
6 | "GUID:0acc523941302664db1f4e527237feb3",
7 | "GUID:e372c541aba5148868e12aa078ca7c20",
8 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
9 | "GUID:5ec8620e0ca6d4d9fb24dbcad8869bd5"
10 | ],
11 | "includePlatforms": [],
12 | "excludePlatforms": [],
13 | "allowUnsafeCode": false,
14 | "overrideReferences": true,
15 | "precompiledReferences": [
16 | "nunit.framework.dll"
17 | ],
18 | "autoReferenced": false,
19 | "defineConstraints": [
20 | "UNITY_INCLUDE_TESTS"
21 | ],
22 | "versionDefines": [],
23 | "noEngineReferences": false
24 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Memory.Tests/Mochineko.ChatGPT_API.Memory.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ed699fb99255d4d929e6fcc676e2fbe8
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 72c8c5b6952d14d099dda927c1dbb7cc
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/Mochineko.ChatGPT_API.Relent.Samples.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Relent.Samples",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
6 | "GUID:5ec8620e0ca6d4d9fb24dbcad8869bd5",
7 | "GUID:5c67e8a6c5956403bb150154fc83ee6f",
8 | "GUID:2620e54ab6edb48f48d55966fd5662fb",
9 | "GUID:51d11816546934d4a937e4a420478ce5",
10 | "GUID:f51ebe6a0ceec4240a699833d6309b23"
11 | ],
12 | "includePlatforms": [],
13 | "excludePlatforms": [],
14 | "allowUnsafeCode": false,
15 | "overrideReferences": false,
16 | "precompiledReferences": [],
17 | "autoReferenced": false,
18 | "defineConstraints": [],
19 | "versionDefines": [],
20 | "noEngineReferences": false
21 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/Mochineko.ChatGPT_API.Relent.Samples.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6208e05189e454bbeb04628c96b93d20
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/RelentChatCompletionSample.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Threading;
4 | using Cysharp.Threading.Tasks;
5 | using Mochineko.ChatGPT_API.Memory;
6 | using Mochineko.Relent.Resilience;
7 | using Mochineko.Relent.Resilience.Bulkhead;
8 | using Mochineko.Relent.Resilience.Retry;
9 | using Mochineko.Relent.Resilience.Timeout;
10 | using Mochineko.Relent.Resilience.Wrap;
11 | using Mochineko.Relent.UncertainResult;
12 | using UnityEngine;
13 | using UnityEngine.Serialization;
14 | using Debug = UnityEngine.Debug;
15 |
16 | namespace Mochineko.ChatGPT_API.Relent.Samples
17 | {
18 | ///
19 | /// A sample component to complete chat by ChatGPT API on Unity.
20 | ///
21 | public sealed class RelentChatCompletionSample : MonoBehaviour
22 | {
23 | ///
24 | /// API key generated by OpenAPI.
25 | ///
26 | [SerializeField] private string apiKey = string.Empty;
27 |
28 | ///
29 | /// System message to instruct assistant.
30 | ///
31 | [SerializeField, TextArea] private string systemMessage = string.Empty;
32 |
33 | ///
34 | /// Message sent to ChatGPT API.
35 | ///
36 | [SerializeField, TextArea] private string message = string.Empty;
37 |
38 | ///
39 | /// Max number of chat memory of queue.
40 | ///
41 | [SerializeField] private int maxMemoryCount = 20;
42 |
43 | ///
44 | /// Total timeout seconds of API calling.
45 | ///
46 | [SerializeField] private float totalTimeoutSeconds = 30f;
47 |
48 | ///
49 | /// Each retry timeout seconds of API calling.
50 | ///
51 | [SerializeField] private float eachTimeoutSeconds = 10f;
52 |
53 | ///
54 | /// Max retry count of API calling.
55 | ///
56 | [SerializeField] private int maxRetryCount = 5;
57 |
58 | ///
59 | /// Retry interval seconds of API calling.
60 | ///
61 | [SerializeField] private float retryIntervalSeconds = 1f;
62 |
63 | ///
64 | /// Max parallelization of API calling.
65 | ///
66 | [SerializeField] private int maxParallelization = 1;
67 |
68 | private RelentChatCompletionAPIConnection? connection;
69 | private FiniteQueueChatMemory? memory;
70 | private IPolicy? policy;
71 |
72 | private void Start()
73 | {
74 | // API Key must be set.
75 | if (string.IsNullOrEmpty(apiKey))
76 | {
77 | Debug.LogError("OpenAI API key must be set.");
78 | return;
79 | }
80 |
81 | memory = new FiniteQueueChatMemory(maxMemoryCount);
82 |
83 | // Create instance of ChatGPTConnection with specifying chat model.
84 | connection = new RelentChatCompletionAPIConnection(
85 | apiKey,
86 | memory,
87 | systemMessage);
88 |
89 | policy = BuildPolicy();
90 | }
91 |
92 | private IPolicy BuildPolicy()
93 | {
94 | var totalTimeoutPolicy = TimeoutFactory.Timeout(
95 | timeout: TimeSpan.FromSeconds(totalTimeoutSeconds));
96 |
97 | var retryPolicy = RetryFactory.RetryWithInterval(
98 | maxRetryCount,
99 | interval: TimeSpan.FromSeconds(retryIntervalSeconds));
100 |
101 | var eachTimeoutPolicy = TimeoutFactory.Timeout(
102 | timeout: TimeSpan.FromSeconds(eachTimeoutSeconds));
103 |
104 | var bulkheadPolicy = BulkheadFactory.Bulkhead(
105 | maxParallelization);
106 |
107 | return totalTimeoutPolicy
108 | .Wrap(retryPolicy)
109 | .Wrap(eachTimeoutPolicy)
110 | .Wrap(bulkheadPolicy);
111 | }
112 |
113 | [ContextMenu(nameof(SendChat))]
114 | public void SendChat()
115 | {
116 | SendChatAsync(this.GetCancellationTokenOnDestroy()).Forget();
117 | }
118 |
119 | [ContextMenu(nameof(ClearChatMemory))]
120 | public void ClearChatMemory()
121 | {
122 | memory?.ClearAllMessages();
123 | }
124 |
125 | private async UniTask SendChatAsync(CancellationToken cancellationToken)
126 | {
127 | // Validations
128 | if (connection == null)
129 | {
130 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Connection is null.");
131 | return;
132 | }
133 |
134 | if (policy == null)
135 | {
136 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Policy is null.");
137 | return;
138 | }
139 |
140 | if (string.IsNullOrEmpty(message))
141 | {
142 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Chat content is empty.");
143 | return;
144 | }
145 |
146 | await UniTask.SwitchToThreadPool();
147 |
148 | var result = await policy.ExecuteAsync(
149 | async innerCancellationToken
150 | => await connection.CompleteChatAsync(message, innerCancellationToken),
151 | cancellationToken);
152 |
153 | await UniTask.SwitchToMainThread(cancellationToken);
154 |
155 | if (result is IUncertainSuccessResult success)
156 | {
157 | Debug.Log($"[ChatGPT_API.Relent.Samples] Result:\n{success.Result.ResultMessage}");
158 | }
159 | else if (result is IUncertainRetryableResult retryable)
160 | {
161 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Failed to complete chat -> {retryable.Message}");
162 | }
163 | else if (result is IUncertainFailureResult failure)
164 | {
165 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Failed to complete chat -> {failure.Message}");
166 | }
167 | else
168 | {
169 | throw new UncertainResultPatternMatchException(nameof(result));
170 | }
171 | }
172 | }
173 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/RelentChatCompletionSample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9afcd790ca2a4e6e84925f628e8ab42f
3 | timeCreated: 1679276942
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/RelentChatCompletionStreamSample.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Cysharp.Threading.Tasks;
8 | using Mochineko.ChatGPT_API.Memory;
9 | using Mochineko.Relent.Resilience;
10 | using Mochineko.Relent.Resilience.Bulkhead;
11 | using Mochineko.Relent.Resilience.Retry;
12 | using Mochineko.Relent.Resilience.Timeout;
13 | using Mochineko.Relent.Resilience.Wrap;
14 | using Mochineko.Relent.UncertainResult;
15 | using UnityEngine;
16 |
17 | namespace Mochineko.ChatGPT_API.Relent.Samples
18 | {
19 | ///
20 | /// A sample component to complete chat as stream by ChatGPT API on Unity.
21 | ///
22 | public sealed class RelentChatCompletionStreamSample : MonoBehaviour
23 | {
24 | ///
25 | /// System message to instruct assistant.
26 | ///
27 | [SerializeField, TextArea] private string prompt = string.Empty;
28 |
29 | ///
30 | /// Message sent to ChatGPT API.
31 | ///
32 | [SerializeField, TextArea] private string message = string.Empty;
33 |
34 | ///
35 | /// Max number of chat memory of queue.
36 | ///
37 | [SerializeField] private int maxMemoryCount = 20;
38 |
39 | ///
40 | /// Total timeout seconds of API calling.
41 | ///
42 | [SerializeField] private float totalTimeoutSeconds = 30f;
43 |
44 | ///
45 | /// Each retry timeout seconds of API calling.
46 | ///
47 | [SerializeField] private float eachTimeoutSeconds = 10f;
48 |
49 | ///
50 | /// Max retry count of API calling.
51 | ///
52 | [SerializeField] private int maxRetryCount = 5;
53 |
54 | ///
55 | /// Retry interval seconds of API calling.
56 | ///
57 | [SerializeField] private float retryIntervalSeconds = 1f;
58 |
59 | ///
60 | /// Max parallelization of API calling.
61 | ///
62 | [SerializeField] private int maxParallelization = 1;
63 |
64 | private RelentChatCompletionAPIConnection? connection;
65 | private FiniteQueueChatMemory? memory;
66 | private IPolicy>? policy;
67 |
68 | private void Start()
69 | {
70 | // API Key must be set.
71 | var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
72 | if (string.IsNullOrEmpty(apiKey))
73 | {
74 | throw new NullReferenceException(nameof(apiKey));
75 | }
76 | memory = new FiniteQueueChatMemory(maxMemoryCount);
77 |
78 | // Create instance of ChatGPTConnection with specifying chat model.
79 | connection = new RelentChatCompletionAPIConnection(
80 | apiKey,
81 | memory,
82 | prompt);
83 |
84 | policy = BuildPolicy();
85 | }
86 |
87 | private IPolicy> BuildPolicy()
88 | {
89 | var totalTimeoutPolicy = TimeoutFactory.Timeout>(
90 | timeout: TimeSpan.FromSeconds(totalTimeoutSeconds));
91 |
92 | var retryPolicy = RetryFactory.RetryWithInterval>(
93 | maxRetryCount,
94 | interval: TimeSpan.FromSeconds(retryIntervalSeconds));
95 |
96 | var eachTimeoutPolicy = TimeoutFactory.Timeout>(
97 | timeout: TimeSpan.FromSeconds(eachTimeoutSeconds));
98 |
99 | var bulkheadPolicy = BulkheadFactory.Bulkhead>(
100 | maxParallelization);
101 |
102 | return totalTimeoutPolicy
103 | .Wrap(retryPolicy)
104 | .Wrap(eachTimeoutPolicy)
105 | .Wrap(bulkheadPolicy);
106 | }
107 |
108 | [ContextMenu(nameof(SendChat))]
109 | public void SendChat()
110 | {
111 | SendChatAsync(this.GetCancellationTokenOnDestroy()).Forget();
112 | }
113 |
114 | [ContextMenu(nameof(ClearChatMemory))]
115 | public void ClearChatMemory()
116 | {
117 | memory?.ClearAllMessages();
118 | }
119 |
120 | private async UniTask SendChatAsync(CancellationToken cancellationToken)
121 | {
122 | // Validations
123 | if (connection == null)
124 | {
125 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Connection is null.");
126 | return;
127 | }
128 |
129 | if (policy == null)
130 | {
131 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Policy is null.");
132 | return;
133 | }
134 |
135 | if (string.IsNullOrEmpty(message))
136 | {
137 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Chat content is empty.");
138 | return;
139 | }
140 |
141 | await UniTask.SwitchToThreadPool();
142 |
143 | var result = await policy.ExecuteAsync(
144 | async innerCancellationToken
145 | => await connection.CompleteChatAsStreamAsync(message, innerCancellationToken),
146 | cancellationToken);
147 |
148 | await UniTask.SwitchToMainThread(cancellationToken);
149 |
150 | var builder = new StringBuilder();
151 |
152 | switch (result)
153 | {
154 | case IUncertainSuccessResult> success:
155 | await foreach (var chunk in success.Result.WithCancellation(cancellationToken))
156 | {
157 | var delta = chunk.Choices[0].Delta.Content;
158 | if (delta == null)
159 | {
160 | // First chunk has only "role" element.
161 | Debug.Log($"[ChatGPT_API.Relent.Samples] Role: {chunk.Choices[0].Delta.Role}.");
162 | continue;
163 | }
164 |
165 | builder.Append(delta);
166 | Debug.Log($"[ChatGPT_API.Relent.Samples] Delta: {delta}, Current: {builder}");
167 | }
168 | Debug.Log($"[ChatGPT_API.Relent.Samples] Completed chat -> {builder}");
169 | break;
170 |
171 | case IUncertainRetryableResult> retryable:
172 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Failed to complete chat -> {retryable.Message}");
173 | break;
174 |
175 | case IUncertainFailureResult> failure:
176 | Debug.LogError($"[ChatGPT_API.Relent.Samples] Failed to complete chat -> {failure.Message}");
177 | break;
178 |
179 | default:
180 | throw new UncertainResultPatternMatchException(nameof(result));
181 | }
182 | }
183 | }
184 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Samples/RelentChatCompletionStreamSample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: df4481f8f6a143da9c11e23b244f7f9d
3 | timeCreated: 1688537322
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a669844e2523e46f4925e693f490bb79
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Tests/Mochineko.ChatGPT_API.Relent.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Relent.Tests",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:27619889b8ba8c24980f49ee34dbb44a",
6 | "GUID:0acc523941302664db1f4e527237feb3",
7 | "GUID:e372c541aba5148868e12aa078ca7c20",
8 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
9 | "GUID:5c67e8a6c5956403bb150154fc83ee6f",
10 | "GUID:2620e54ab6edb48f48d55966fd5662fb",
11 | "GUID:51d11816546934d4a937e4a420478ce5",
12 | "GUID:f51ebe6a0ceec4240a699833d6309b23"
13 | ],
14 | "includePlatforms": [],
15 | "excludePlatforms": [],
16 | "allowUnsafeCode": false,
17 | "overrideReferences": true,
18 | "precompiledReferences": [
19 | "nunit.framework.dll"
20 | ],
21 | "autoReferenced": false,
22 | "defineConstraints": [
23 | "UNITY_INCLUDE_TESTS"
24 | ],
25 | "versionDefines": [],
26 | "noEngineReferences": false
27 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Tests/Mochineko.ChatGPT_API.Relent.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bb0242bf08bee42b9a4ac56e56ebbb84
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Tests/RelentChatCompletionAPIConnectionTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Mochineko.Relent.Resilience;
7 | using Mochineko.Relent.Resilience.Bulkhead;
8 | using Mochineko.Relent.Resilience.CircuitBreaker;
9 | using Mochineko.Relent.Resilience.Retry;
10 | using Mochineko.Relent.Resilience.Timeout;
11 | using Mochineko.Relent.Resilience.Wrap;
12 | using Mochineko.Relent.UncertainResult;
13 | using NUnit.Framework;
14 | using UnityEngine;
15 | using UnityEngine.TestTools;
16 | using Debug = UnityEngine.Debug;
17 |
18 | namespace Mochineko.ChatGPT_API.Relent.Tests
19 | {
20 | [TestFixture]
21 | internal sealed class ChatCompletionAPIConnectionTest
22 | {
23 | [TestCase("あなたのことを教えて")]
24 | [RequiresPlayMode(false)]
25 | public async Task SendMessage(string message)
26 | {
27 | // This file is a target of .gitignore.
28 | var apiKeyPath = Path.Combine(
29 | Application.dataPath,
30 | "Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt");
31 |
32 | var apiKey = await File.ReadAllTextAsync(apiKeyPath);
33 |
34 | var connection = new RelentChatCompletionAPIConnection(apiKey);
35 |
36 | var policy = BuildPolicy();
37 |
38 | var stopWatch = new Stopwatch();
39 | stopWatch.Start();
40 |
41 | var result = await policy.ExecuteAsync(
42 | async cancellationToken
43 | => await connection.CompleteChatAsync(message, cancellationToken),
44 | CancellationToken.None);
45 |
46 | stopWatch.Stop();
47 | Debug.Log($"Elapsed time:{stopWatch.ElapsedMilliseconds / 1000}ms.");
48 |
49 | if (result is IUncertainSuccessResult success)
50 | {
51 | Debug.Log($"Result:\n{success.Result.ToJson()}");
52 | }
53 | else if (result is IUncertainRetryableResult retryable)
54 | {
55 | Debug.LogError(retryable.Message);
56 | }
57 | else if (result is IUncertainFailureResult failure)
58 | {
59 | Debug.LogError(failure.Message);
60 | }
61 | else
62 | {
63 | throw new UncertainResultPatternMatchException(nameof(result));
64 | }
65 | }
66 |
67 | private IPolicy BuildPolicy()
68 | {
69 | var totalTimeoutPolicy = TimeoutFactory.Timeout(
70 | timeout: TimeSpan.FromSeconds(30d));
71 |
72 | var retryPolicy = RetryFactory.RetryWithJitter(
73 | maxRetryCount: 5,
74 | minimum: 1d,
75 | maximum: 5d);
76 |
77 | var eachTimeoutPolicy = TimeoutFactory.Timeout(
78 | timeout: TimeSpan.FromSeconds(10d));
79 |
80 | var circuitBreakerPolicy = CircuitBreakerFactory.CircuitBreaker(
81 | failureThreshold: 3,
82 | interval: TimeSpan.FromSeconds(1d));
83 |
84 | var bulkheadPolicy = BulkheadFactory.Bulkhead(
85 | maxParallelization: 1);
86 |
87 | return totalTimeoutPolicy
88 | .Wrap(retryPolicy)
89 | .Wrap(eachTimeoutPolicy)
90 | .Wrap(circuitBreakerPolicy)
91 | .Wrap(bulkheadPolicy);
92 | }
93 | }
94 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.Tests/RelentChatCompletionAPIConnectionTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fd472299fc5c147b0b97d4a5bbff4a5e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 130bed76d13d346a8823f7b00c8dd03d
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/JsonSerializer.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Mochineko.Relent.Result;
3 | using Newtonsoft.Json;
4 |
5 | namespace Mochineko.ChatGPT_API.Relent
6 | {
7 | public static class JsonSerializer
8 | {
9 | public static IResult SerializeRequestBody(this ChatCompletionRequestBody requestBody)
10 | {
11 | try
12 | {
13 | var json = JsonConvert.SerializeObject(
14 | requestBody,
15 | Formatting.Indented,
16 | new JsonSerializerSettings
17 | {
18 | NullValueHandling = NullValueHandling.Ignore
19 | });
20 |
21 | if (!string.IsNullOrEmpty(json))
22 | {
23 | return Results.Succeed(json);
24 | }
25 | else
26 | {
27 | return Results.FailWithTrace(
28 | $"Failed to serialize because serialized JSON of {nameof(ChatCompletionRequestBody)} was null or empty.");
29 | }
30 | }
31 | catch (JsonException exception)
32 | {
33 | return Results.FailWithTrace(
34 | $"Failed to serialize {nameof(ChatCompletionRequestBody)} to JSON because -> {exception}");
35 | }
36 | }
37 |
38 | public static IResult DeserializeRequestBody(string json)
39 | {
40 | try
41 | {
42 | var requestBody = JsonConvert.DeserializeObject(json);
43 |
44 | if (requestBody != null)
45 | {
46 | return Results.Succeed(requestBody);
47 | }
48 | else
49 | {
50 | return Results.FailWithTrace(
51 | $"Failed to deserialize because deserialized object of {nameof(ChatCompletionRequestBody)} was null.");
52 | }
53 | }
54 | catch (JsonException exception)
55 | {
56 | return Results.FailWithTrace(
57 | $"Failed to deserialize {nameof(ChatCompletionRequestBody)} from JSON because -> {exception}");
58 | }
59 | }
60 |
61 | public static IResult SerializeResponseBody(this ChatCompletionResponseBody requestBody)
62 | {
63 | try
64 | {
65 | var json = JsonConvert.SerializeObject(
66 | requestBody,
67 | Formatting.Indented,
68 | new JsonSerializerSettings
69 | {
70 | NullValueHandling = NullValueHandling.Ignore
71 | });
72 |
73 | if (!string.IsNullOrEmpty(json))
74 | {
75 | return Results.Succeed(json);
76 | }
77 | else
78 | {
79 | return Results.FailWithTrace(
80 | $"Failed to serialize because serialized JSON of {nameof(ChatCompletionResponseBody)} was null or empty.");
81 | }
82 | }
83 | catch (JsonException exception)
84 | {
85 | return Results.FailWithTrace(
86 | $"Failed to serialize {nameof(ChatCompletionResponseBody)} to JSON because -> {exception}");
87 | }
88 | }
89 |
90 | public static IResult DeserializeResponseBody(string json)
91 | {
92 | try
93 | {
94 | var requestBody = JsonConvert.DeserializeObject(json);
95 |
96 | if (requestBody != null)
97 | {
98 | return Results.Succeed(requestBody);
99 | }
100 | else
101 | {
102 | return Results.FailWithTrace(
103 | $"Failed to deserialize because deserialized object of {nameof(ChatCompletionResponseBody)} was null.");
104 | }
105 | }
106 | catch (JsonSerializationException exception)
107 | {
108 | return Results.FailWithTrace(
109 | $"Failed to deserialize {nameof(ChatCompletionResponseBody)} from JSON because -> {exception}");
110 | }
111 | }
112 |
113 | public static IResult DeserializeRequestChunk(string json)
114 | {
115 | try
116 | {
117 | var requestBody = JsonConvert.DeserializeObject(json);
118 |
119 | if (requestBody != null)
120 | {
121 | return Results.Succeed(requestBody);
122 | }
123 | else
124 | {
125 | return Results.FailWithTrace(
126 | $"Failed to deserialize because deserialized object of {nameof(ChatCompletionStreamResponseChunk)} was null.");
127 | }
128 | }
129 | catch (JsonException exception)
130 | {
131 | return Results.FailWithTrace(
132 | $"Failed to deserialize {nameof(ChatCompletionStreamResponseChunk)} from JSON because -> {exception}");
133 | }
134 | }
135 | }
136 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/JsonSerializer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c4dac57f65e547f5877c26f9ddd4a181
3 | timeCreated: 1679386577
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 mochineko
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 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7aabd95139764df69bb4c91045e2f39a
3 | timeCreated: 1679287538
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/Mochineko.ChatGPT_API.Relent.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Relent",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
6 | "GUID:3ed995982eec04b2e9d304b5b6242945",
7 | "GUID:2620e54ab6edb48f48d55966fd5662fb",
8 | "GUID:f51ebe6a0ceec4240a699833d6309b23"
9 | ],
10 | "includePlatforms": [],
11 | "excludePlatforms": [],
12 | "allowUnsafeCode": false,
13 | "overrideReferences": true,
14 | "precompiledReferences": [
15 | "Newtonsoft.Json.dll"
16 | ],
17 | "autoReferenced": false,
18 | "defineConstraints": [],
19 | "versionDefines": [],
20 | "noEngineReferences": false
21 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/Mochineko.ChatGPT_API.Relent.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5c67e8a6c5956403bb150154fc83ee6f
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/RelentChatCompletionAPIConnection.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5969566575a244013b8057ce29a747ae
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.mochineko.chatgpt-api.relent",
3 | "version": "0.7.3",
4 | "displayName": "ChatGPT API / Relent",
5 | "description": "ChatGPT API implementation by Relent.",
6 | "unity": "2021.3",
7 | "author": {
8 | "name": "Mochineko",
9 | "email": "t.o.e.4315@gmail.com"
10 | },
11 | "dependencies": {
12 | "com.unity.nuget.newtonsoft-json": "3.0.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Relent/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1c05ebb3bfa54723b34d29a4794e8ca6
3 | timeCreated: 1679287542
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e29e77bba69c141cc9dece7cb810f622
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionAsStreamSample.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Text;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Cysharp.Threading.Tasks;
7 | using Mochineko.ChatGPT_API.Memory;
8 | using UnityEngine;
9 |
10 | namespace Mochineko.ChatGPT_API.Samples
11 | {
12 | ///
13 | /// A sample component to complete chat as stream by ChatGPT API on Unity.
14 | ///
15 | public sealed class ChatCompletionAsStreamSample : MonoBehaviour
16 | {
17 | [SerializeField, TextArea(3, 10)]
18 | private string prompt = string.Empty;
19 |
20 | ///
21 | /// Message sent to ChatGPT API.
22 | ///
23 | [SerializeField, TextArea(3, 10)] private string message = string.Empty;
24 |
25 | ///
26 | /// Max number of chat memory of queue.
27 | ///
28 | [SerializeField] private int maxMemoryCount = 10;
29 |
30 | private ChatCompletionAPIConnection? connection;
31 | private IChatMemory? memory;
32 |
33 | private void Start()
34 | {
35 | // Get API key from environment variable.
36 | var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
37 | if (string.IsNullOrEmpty(apiKey))
38 | {
39 | Debug.LogError("OpenAI API key must be set.");
40 | return;
41 | }
42 |
43 | memory = new FiniteQueueChatMemory(maxMemoryCount);
44 |
45 | // Create instance of ChatGPTConnection with specifying chat model.
46 | connection = new ChatCompletionAPIConnection(
47 | apiKey,
48 | memory,
49 | prompt);
50 | }
51 |
52 | [ContextMenu(nameof(SendChatAsStream))]
53 | public void SendChatAsStream()
54 | {
55 | SendChatAsStreamAsync(this.GetCancellationTokenOnDestroy())
56 | .Forget();
57 | }
58 |
59 | [ContextMenu(nameof(ClearChatMemory))]
60 | public void ClearChatMemory()
61 | {
62 | memory?.ClearAllMessages();
63 | }
64 |
65 | private async UniTask SendChatAsStreamAsync(CancellationToken cancellationToken)
66 | {
67 | // Validations
68 | if (connection == null)
69 | {
70 | Debug.LogError($"[ChatGPT_API.Samples] Connection is null.");
71 | return;
72 | }
73 |
74 | if (memory == null)
75 | {
76 | Debug.LogError($"[ChatGPT_API.Samples] Memory is null.");
77 | return;
78 | }
79 |
80 | if (string.IsNullOrEmpty(message))
81 | {
82 | Debug.LogError($"[ChatGPT_API.Samples] Chat content is empty.");
83 | return;
84 | }
85 |
86 | var builder = new StringBuilder();
87 | try
88 | {
89 | await UniTask.SwitchToThreadPool();
90 |
91 | // Receive enumerable from ChatGPT chat completion API.
92 | var enumerable = await connection.CompleteChatAsStreamAsync(
93 | message,
94 | cancellationToken,
95 | verbose: true);
96 |
97 | await foreach (var chunk in enumerable.WithCancellation(cancellationToken))
98 | {
99 | // First chunk has only "role" element.
100 | if (chunk.Choices[0].Delta.Content is null)
101 | {
102 | Debug.Log($"[ChatGPT_API.Samples] Role:{chunk.Choices[0].Delta.Role}.");
103 | continue;
104 | }
105 |
106 | var delta = chunk.Choices[0].Delta.Content;
107 | builder.Append(delta);
108 | Debug.Log($"[ChatGPT_API.Samples] Delta:{delta}, Current:{builder}");
109 | }
110 |
111 | var result = builder.ToString();
112 |
113 | // Log chat completion result.
114 | Debug.Log($"[ChatGPT_API.Samples] Completed: \n{result}");
115 |
116 | // Record result to memory.
117 | await memory.AddMessageAsync(Message.CreateAssistantMessage(
118 | content: result),
119 | cancellationToken);
120 | }
121 | catch (Exception e)
122 | {
123 | // Exceptions should be caught.
124 | Debug.LogException(e);
125 | return;
126 | }
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionAsStreamSample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c1ceb7cabdcb4d30abaa43ecfd791131
3 | timeCreated: 1688473562
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionSample.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Threading;
4 | using Cysharp.Threading.Tasks;
5 | using Mochineko.ChatGPT_API.Memory;
6 | using UnityEngine;
7 | using UnityEngine.Serialization;
8 |
9 | namespace Mochineko.ChatGPT_API.Samples
10 | {
11 | ///
12 | /// A sample component to complete chat by ChatGPT API on Unity.
13 | ///
14 | public sealed class ChatCompletionSample : MonoBehaviour
15 | {
16 | ///
17 | /// API key generated by OpenAPI.
18 | ///
19 | [SerializeField] private string apiKey = string.Empty;
20 |
21 | ///
22 | /// System message to instruct assistant.
23 | ///
24 | [SerializeField, TextArea] private string systemMessage = string.Empty;
25 |
26 | ///
27 | /// Message sent to ChatGPT API.
28 | ///
29 | [SerializeField, TextArea] private string message = string.Empty;
30 |
31 | ///
32 | /// Max number of chat memory of queue.
33 | ///
34 | [SerializeField] private int maxMemoryCount = 20;
35 |
36 | private ChatCompletionAPIConnection? connection;
37 | private IChatMemory? memory;
38 |
39 | private void Start()
40 | {
41 | // API Key must be set.
42 | if (string.IsNullOrEmpty(apiKey))
43 | {
44 | Debug.LogError("OpenAI API key must be set.");
45 | return;
46 | }
47 |
48 | memory = new FiniteQueueChatMemory(maxMemoryCount);
49 |
50 | // Create instance of ChatGPTConnection with specifying chat model.
51 | connection = new ChatCompletionAPIConnection(
52 | apiKey,
53 | memory,
54 | systemMessage);
55 | }
56 |
57 | [ContextMenu(nameof(SendChat))]
58 | public void SendChat()
59 | {
60 | SendChatAsync(this.GetCancellationTokenOnDestroy()).Forget();
61 | }
62 |
63 | [ContextMenu(nameof(ClearChatMemory))]
64 | public void ClearChatMemory()
65 | {
66 | memory?.ClearAllMessages();
67 | }
68 |
69 | private async UniTask SendChatAsync(CancellationToken cancellationToken)
70 | {
71 | // Validations
72 | if (connection == null)
73 | {
74 | Debug.LogError($"[ChatGPT_API.Samples] Connection is null.");
75 | return;
76 | }
77 |
78 | if (string.IsNullOrEmpty(message))
79 | {
80 | Debug.LogError($"[ChatGPT_API.Samples] Chat content is empty.");
81 | return;
82 | }
83 |
84 | ChatCompletionResponseBody response;
85 | try
86 | {
87 | await UniTask.SwitchToThreadPool();
88 |
89 | // Create message by ChatGPT chat completion API.
90 | response = await connection.CompleteChatAsync(
91 | message,
92 | cancellationToken);
93 | }
94 | catch (Exception e)
95 | {
96 | // Exceptions should be caught.
97 | Debug.LogException(e);
98 | return;
99 | }
100 |
101 | await UniTask.SwitchToMainThread(cancellationToken);
102 |
103 | // Log chat completion result.
104 | Debug.Log($"[ChatGPT_API.Samples] Result:\n{response.ResultMessage}");
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionSample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 97b17c98f86534d2fb54319893b39bc8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionSample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5998cc067509c4cbf8613365753a22a2
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionStreamSample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b1386681cad13d84793abe93794f7dfd
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/Mochineko.ChatGPT_API.Samples.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Samples",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
6 | "GUID:5ec8620e0ca6d4d9fb24dbcad8869bd5",
7 | "GUID:f51ebe6a0ceec4240a699833d6309b23"
8 | ],
9 | "includePlatforms": [],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false,
12 | "overrideReferences": false,
13 | "precompiledReferences": [],
14 | "autoReferenced": false,
15 | "defineConstraints": [],
16 | "versionDefines": [],
17 | "noEngineReferences": false
18 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Samples/Mochineko.ChatGPT_API.Samples.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1af33cd3116144512944739062670ae6
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2872f46351c1a40fb9181421f07e5956
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/ChatCompletionAPIConnectionTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using FluentAssertions;
7 | using NUnit.Framework;
8 | using UnityEngine;
9 | using UnityEngine.TestTools;
10 |
11 | #nullable enable
12 |
13 | namespace Mochineko.ChatGPT_API.Tests
14 | {
15 | [TestFixture]
16 | internal sealed class ChatCompletionAPIConnectionTest
17 | {
18 | [TestCase("あなたのことを教えて")]
19 | [RequiresPlayMode(false)]
20 | public async Task SendMessage(string message)
21 | {
22 | // This file is a target of .gitignore.
23 | var apiKeyPath = Path.Combine(
24 | Application.dataPath,
25 | "Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt");
26 |
27 | var apiKey = await File.ReadAllTextAsync(apiKeyPath);
28 |
29 | var connection = new ChatCompletionAPIConnection(apiKey);
30 |
31 | var result = await connection.CompleteChatAsync(message, CancellationToken.None);
32 |
33 | string.IsNullOrEmpty(result.ResultMessage).Should().BeFalse();
34 |
35 | Debug.Log($"Result:\n{result}");
36 | }
37 |
38 | [TestCase("あなたのことを教えて")]
39 | [RequiresPlayMode(false)]
40 | public async Task SendMessageWithDetailedParameters(string message)
41 | {
42 | // This file is a target of .gitignore.
43 | var apiKeyPath = Path.Combine(
44 | Application.dataPath,
45 | "Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt");
46 |
47 | var apiKey = await File.ReadAllTextAsync(apiKeyPath);
48 |
49 | var connection = new ChatCompletionAPIConnection(apiKey);
50 |
51 | var result = await connection.CompleteChatAsync(
52 | message,
53 | CancellationToken.None,
54 | model: Model.Turbo,
55 | temperature: 1f,
56 | topP: 1f,
57 | n: 1,
58 | stream: false,
59 | stop: null,
60 | maxTokens: null,
61 | presencePenalty: 0f,
62 | frequencyPenalty: 0f,
63 | user: "test");
64 |
65 | string.IsNullOrEmpty(result.ResultMessage).Should().BeFalse();
66 |
67 | Debug.Log($"Result:\n{result}");
68 | }
69 |
70 | [Test]
71 | [RequiresPlayMode(false)]
72 | public async Task TooLongMaxTokens()
73 | {
74 | // This file is a target of .gitignore.
75 | var apiKeyPath = Path.Combine(
76 | Application.dataPath,
77 | "Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt");
78 |
79 | var apiKey = await File.ReadAllTextAsync(apiKeyPath);
80 |
81 | var connection = new ChatCompletionAPIConnection(apiKey);
82 |
83 | Func send = async () => await connection.CompleteChatAsync(
84 | "a",
85 | CancellationToken.None,
86 | model: Model.Turbo,
87 | temperature: 1f,
88 | topP: 1f,
89 | n: 1,
90 | stream: false,
91 | stop: null,
92 | maxTokens: int.MaxValue, // Over 4096 tokens
93 | presencePenalty: 0f,
94 | frequencyPenalty: 0f,
95 | user: "test");
96 |
97 | await send.Should().ThrowAsync(because: "max_tokens is too long.");
98 | }
99 |
100 | [Test]
101 | [RequiresPlayMode(false)]
102 | public async Task InvalidAPIKey()
103 | {
104 | var apiKey = "invalid";
105 |
106 | var connection = new ChatCompletionAPIConnection(apiKey);
107 |
108 | Func send = async () => await connection.CompleteChatAsync("a", CancellationToken.None);
109 |
110 | await send.Should().ThrowAsync(because: "Invalid API key.");
111 | }
112 |
113 | [Test]
114 | [RequiresPlayMode(false)]
115 | public async Task FunctionCalling()
116 | {
117 | // This file is a target of .gitignore.
118 | var apiKeyPath = Path.Combine(
119 | Application.dataPath,
120 | "Mochineko/ChatGPT_API.Tests/OpenAI_API_Key.txt");
121 |
122 | var apiKey = await File.ReadAllTextAsync(apiKeyPath);
123 |
124 | var connection = new ChatCompletionAPIConnection(apiKey);
125 |
126 | var function = new Function
127 | (
128 | name: "emotion_simulator",
129 | description: "Simulate emotion of the assistant as human.",
130 | parameters: new Dictionary
131 | {
132 | { "type", "object" },
133 | {
134 | "properties", new Dictionary
135 | {
136 | {
137 | "emotion", new Dictionary
138 | {
139 | { "type", "string" },
140 | {
141 | "enum", new List
142 | {
143 | "neutral", "happy", "sad", "angry", "surprised", "disgusted", "fearful"
144 | }
145 | },
146 | }
147 | }
148 | }
149 | },
150 | { "required", new List { "emotion" } },
151 | }
152 | );
153 |
154 | var result = await connection
155 | .CompleteChatAsync(
156 | "Please tell me about yourself.",
157 | CancellationToken.None,
158 | model: Model.Turbo0613,
159 | functions: new List { function },
160 | functionCallSpecifying: new FunctionCallSpecifying(name: "emotion_simulator")
161 | );
162 |
163 | Debug.Log($"Result:\nname:{result.Choices[0].Message.FunctionCall?.Name},\narguments:{result.Choices[0].Message.FunctionCall?.Arguments}");
164 | }
165 | }
166 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/ChatCompletionAPIConnectionTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 291e28163d771422d8363d3721ef7339
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/Mochineko.ChatGPT_API.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Tests",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:27619889b8ba8c24980f49ee34dbb44a",
6 | "GUID:0acc523941302664db1f4e527237feb3",
7 | "GUID:e372c541aba5148868e12aa078ca7c20",
8 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
9 | "GUID:f51ebe6a0ceec4240a699833d6309b23"
10 | ],
11 | "includePlatforms": [
12 | "Editor"
13 | ],
14 | "excludePlatforms": [],
15 | "allowUnsafeCode": false,
16 | "overrideReferences": true,
17 | "precompiledReferences": [
18 | "nunit.framework.dll",
19 | "Newtonsoft.Json.dll"
20 | ],
21 | "autoReferenced": false,
22 | "defineConstraints": [
23 | "UNITY_INCLUDE_TESTS"
24 | ],
25 | "versionDefines": [],
26 | "noEngineReferences": false
27 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/Mochineko.ChatGPT_API.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b5c8a470ed6c6408598dddfd614cc1b8
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/ModelTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using FluentAssertions;
3 | using NUnit.Framework;
4 | using UnityEngine.TestTools;
5 |
6 | namespace Mochineko.ChatGPT_API.Tests
7 | {
8 | [TestFixture]
9 | internal sealed class ModelTest
10 | {
11 | [TestCase(Model.Turbo, "gpt-3.5-turbo")]
12 | [TestCase(Model.Turbo1106, "gpt-3.5-turbo-1106")]
13 | [TestCase(Model.Turbo16K, "gpt-3.5-turbo-16k")]
14 | [TestCase(Model.Four, "gpt-4")]
15 | [TestCase(Model.Four0613, "gpt-4-0613")]
16 | [TestCase(Model.Four32K, "gpt-4-32k")]
17 | [TestCase(Model.Four32K0613, "gpt-4-32k-0613")]
18 | [TestCase(Model.Four1106Preview, "gpt-4-1106-preview")]
19 | [TestCase(Model.FourVisionPreview, "gpt-4-vision-preview")]
20 | [RequiresPlayMode(false)]
21 | public void Resolve(Model model, string modelText)
22 | {
23 | model.ToText().Should().Be(modelText);
24 | modelText.ToModel().Should().Be(model);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/ModelTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f36c68c30f7b4cae94d742d8106d6f98
3 | timeCreated: 1677915461
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/RoleTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using FluentAssertions;
3 | using NUnit.Framework;
4 | using UnityEngine.TestTools;
5 |
6 | namespace Mochineko.ChatGPT_API.Tests
7 | {
8 | [TestFixture]
9 | internal sealed class RoleTest
10 | {
11 | [TestCase(Role.System, "system")]
12 | [TestCase(Role.Assistant, "assistant")]
13 | [TestCase(Role.User, "user")]
14 | [TestCase(Role.Tool, "tool")]
15 | [RequiresPlayMode(false)]
16 | public void Resolve(Role role, string roleText)
17 | {
18 | role.ToText().Should().Be(roleText);
19 | roleText.ToRole().Should().Be(role);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.Tests/RoleTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 326ba4ff416c4582a11f367bdb62546c
3 | timeCreated: 1677915454
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c3096237ab1f42db8ef4ea9ab3a321b
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/APIErrorException.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Net;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | ///
8 | /// See https://platform.openai.com/docs/guides/error-codes/api-errors
9 | ///
10 | public sealed class APIErrorException : Exception
11 | {
12 | internal APIErrorException(string message, HttpStatusCode statusCode, Exception innerException)
13 | : base(
14 | message: $"[ChatGPT_API] ({(int)statusCode}:{statusCode}) {message}",
15 | innerException: innerException)
16 | {
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/APIErrorException.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6ef0d6f5d14f42e6a4a80d9832f1ce9c
3 | timeCreated: 1677915211
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("Mochineko.ChatGPT_API.Tests")]
4 | [assembly: InternalsVisibleTo("Mochineko.ChatGPT_API.Relent")]
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/AssemblyInfo.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d63817b30e3f04518a43881daa2f07f9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionAPIConnection.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 638a2a8d5e3548179cd8c06680149d51
3 | timeCreated: 1677898671
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionRequestBody.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Collections.Generic;
4 | using Newtonsoft.Json;
5 |
6 | namespace Mochineko.ChatGPT_API
7 | {
8 | ///
9 | /// Request body of ChatGPT chat completion API.
10 | /// See https://platform.openai.com/docs/api-reference/chat/create
11 | ///
12 | [JsonObject]
13 | public sealed class ChatCompletionRequestBody
14 | {
15 | ///
16 | /// [Required]
17 | /// ID of the model to use.
18 | /// Currently, only gpt-3.5-turbo and gpt-3.5-turbo-0301 are supported.
19 | ///
20 | [JsonProperty("model"), JsonRequired]
21 | public string Model { get; }
22 |
23 | ///
24 | /// [Required]
25 | /// The messages to generate chat completions for, in the chat format.
26 | ///
27 | [JsonProperty("messages"), JsonRequired]
28 | public IReadOnlyList Messages { get; }
29 |
30 | ///
31 | /// [Optional] Defaults to null.
32 | /// A list of functions the model may generate JSON inputs for.
33 | ///
34 | [JsonProperty("functions")]
35 | public IReadOnlyList? Functions { get; }
36 |
37 | ///
38 | /// [Optional] Defaults to "auto".
39 | /// Controls how the model responds to function calls.
40 | /// "none" means the model does not call a function, and responds to the end-user.
41 | /// "auto" means the model can pick between an end-user or calling a function.
42 | /// Specifying a particular function via {"name":\ "my_function"} forces the model to call that function.
43 | /// "none" is the default when no functions are present.
44 | /// "auto" is the default if functions are present.
45 | ///
46 | [JsonProperty("function_call")]
47 | public object? FunctionCall { get; }
48 |
49 | ///
50 | /// [Optional] Defaults to 1.
51 | /// What sampling temperature to use, between 0 and 2.
52 | /// Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
53 | /// We generally recommend altering this or top_p but not both.
54 | ///
55 | [JsonProperty("temperature")]
56 | public float? Temperature { get; }
57 |
58 | ///
59 | /// [Optional] Defaults to 1.
60 | /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass.
61 | /// So 0.1 means only the tokens comprising the top 10% probability mass are considered.
62 | /// We generally recommend altering this or temperature but not both.
63 | ///
64 | [JsonProperty("top_p")]
65 | public float? TopP { get; }
66 |
67 | ///
68 | /// [Optional] Defaults to 1.
69 | /// How many chat completion choices to generate for each input message.
70 | ///
71 | [JsonProperty("n")]
72 | public uint? N { get; }
73 |
74 | ///
75 | /// [Optional] Defaults to false.
76 | /// If set, partial message deltas will be sent, like in ChatGPT.
77 | /// Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a data: [DONE] message.
78 | ///
79 | [JsonProperty("stream")]
80 | public bool? Stream { get; }
81 |
82 | ///
83 | /// [Optional] Defaults to null.
84 | /// Up to 4 sequences where the API will stop generating further tokens.
85 | ///
86 | [JsonProperty("stop")]
87 | public string[]? Stop { get; }
88 |
89 | ///
90 | /// [Optional] Defaults to inf.
91 | /// The maximum number of tokens allowed for the generated answer.
92 | /// By default, the number of tokens the model can return will be (4096 - prompt tokens).
93 | ///
94 | [JsonProperty("max_tokens")]
95 | public int? MaxTokens { get; }
96 |
97 | ///
98 | /// [Optional] Defaults to 0.
99 | /// Number between -2.0 and 2.0.
100 | /// Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.
101 | /// See more information about frequency and presence penalties.
102 | /// https://platform.openai.com/docs/api-reference/parameter-details
103 | ///
104 | [JsonProperty("presence_penalty")]
105 | public float? PresencePenalty { get; }
106 |
107 | ///
108 | /// [Optional] Defaults to 0.
109 | /// Number between -2.0 and 2.0.
110 | /// Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.
111 | /// See more information about frequency and presence penalties.
112 | /// https://platform.openai.com/docs/api-reference/parameter-details
113 | ///
114 | [JsonProperty("frequency_penalty")]
115 | public float? FrequencyPenalty { get; }
116 |
117 | ///
118 | /// [Optional] Defaults to null.
119 | /// Modify the likelihood of specified tokens appearing in the completion.
120 | /// Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100.
121 | /// Mathematically, the bias is added to the logits generated by the model prior to sampling.
122 | /// The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.
123 | ///
124 | [JsonProperty("logit_bias")]
125 | public Dictionary? LogitBias { get; }
126 |
127 | ///
128 | /// [Optional]
129 | /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Learn more.
130 | /// https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids
131 | ///
132 | [JsonProperty("user")]
133 | public string? User { get; }
134 |
135 | public ChatCompletionRequestBody(
136 | string model,
137 | IReadOnlyList messages,
138 | IReadOnlyList? functions = null,
139 | string? functionCallString = null,
140 | FunctionCallSpecifying? functionCallSpecifying = null,
141 | float? temperature = 1f,
142 | float? topP = 1f,
143 | uint? n = 1,
144 | bool? stream = false,
145 | string[]? stop = null,
146 | int? maxTokens = null,
147 | float? presencePenalty = 0f,
148 | float? frequencyPenalty = 0f,
149 | Dictionary? logitBias = null,
150 | string? user = null)
151 | {
152 | this.Model = model;
153 | this.Messages = messages;
154 | this.Functions = functions;
155 |
156 | if (functionCallString != null && functionCallSpecifying != null)
157 | {
158 | throw new ArgumentException($"Cannot specify both {nameof(functionCallString)} and {nameof(functionCallSpecifying)}.");
159 | }
160 | if (functionCallString != null)
161 | {
162 | this.FunctionCall = functionCallString;
163 | }
164 | else if (functionCallSpecifying != null)
165 | {
166 | this.FunctionCall = functionCallSpecifying;
167 | }
168 | else
169 | {
170 | this.FunctionCall = null;
171 | }
172 |
173 | this.Temperature = temperature;
174 | this.TopP = topP;
175 | this.N = n;
176 | this.Stream = stream;
177 | this.Stop = stop;
178 | this.MaxTokens = maxTokens;
179 | this.PresencePenalty = presencePenalty;
180 | this.FrequencyPenalty = frequencyPenalty;
181 | this.LogitBias = logitBias;
182 | this.User = user;
183 | }
184 |
185 | public string ToJson()
186 | => JsonConvert.SerializeObject(
187 | this,
188 | Formatting.Indented,
189 | new JsonSerializerSettings
190 | {
191 | NullValueHandling = NullValueHandling.Ignore,
192 | });
193 |
194 | public static ChatCompletionRequestBody? FromJson(string json)
195 | => JsonConvert.DeserializeObject(json);
196 | }
197 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionRequestBody.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8068f32cd56e4b54b21a7626a8866465
3 | timeCreated: 1677898648
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionResponseBody.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using Newtonsoft.Json;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | ///
8 | /// Response body of ChatGPT chat completion API.
9 | /// See https://platform.openai.com/docs/guides/chat/introduction.
10 | ///
11 | [JsonObject]
12 | public sealed class ChatCompletionResponseBody
13 | {
14 | [JsonProperty("id"), JsonRequired]
15 | public string ID { get; private set; } = string.Empty;
16 |
17 | [JsonProperty("object"), JsonRequired]
18 | public string Object { get; private set; } = string.Empty;
19 |
20 | [JsonProperty("created"), JsonRequired]
21 | public int Created { get; private set; }
22 |
23 | [JsonProperty("model"), JsonRequired]
24 | public string Model { get; private set; } = string.Empty;
25 |
26 | [JsonProperty("usage"), JsonRequired]
27 | public Usage Usage { get; private set; } = new();
28 |
29 | [JsonProperty("choices"), JsonRequired]
30 | public Choice[] Choices { get; private set; } = Array.Empty();
31 |
32 | ///
33 | /// Result of chat completion.
34 | ///
35 | [JsonIgnore]
36 | public string ResultMessage
37 | {
38 | get
39 | {
40 | if (Choices.Length == 0)
41 | {
42 | return string.Empty;
43 | }
44 |
45 | return Choices[0].Message.Content ?? string.Empty;
46 | }
47 | }
48 |
49 | public string ToJson()
50 | => JsonConvert.SerializeObject(this, Formatting.Indented);
51 |
52 | public static ChatCompletionResponseBody? FromJson(string json)
53 | => JsonConvert.DeserializeObject(json, new JsonSerializerSettings());
54 | }
55 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionResponseBody.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 32d4988559ad45d797c2581b3c616a91
3 | timeCreated: 1677898688
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionStreamResponseChunk.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using Newtonsoft.Json;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | ///
8 | /// Response body of ChatGPT chat completion API.
9 | /// See https://platform.openai.com/docs/guides/chat/introduction.
10 | ///
11 | [JsonObject]
12 | public sealed class ChatCompletionStreamResponseChunk
13 | {
14 | [JsonProperty("id"), JsonRequired]
15 | public string ID { get; private set; } = string.Empty;
16 |
17 | [JsonProperty("object"), JsonRequired]
18 | public string Object { get; private set; } = string.Empty;
19 |
20 | [JsonProperty("created"), JsonRequired]
21 | public int Created { get; private set; }
22 |
23 | [JsonProperty("model"), JsonRequired]
24 | public string Model { get; private set; } = string.Empty;
25 |
26 | [JsonProperty("choices"), JsonRequired]
27 | public ChoiceChunk[] Choices { get; private set; } = Array.Empty();
28 |
29 | public string ToJson()
30 | => JsonConvert.SerializeObject(this, Formatting.Indented);
31 |
32 | public static ChatCompletionStreamResponseChunk? FromJson(string json)
33 | => JsonConvert.DeserializeObject(json, new JsonSerializerSettings());
34 | }
35 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChatCompletionStreamResponseChunk.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: af95bb460c3b40c888f11e9c145409e3
3 | timeCreated: 1688472063
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Choice.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class Choice
8 | {
9 | [JsonProperty("message"), JsonRequired]
10 | public Message Message { get; private set; } = new Message();
11 |
12 | [JsonProperty("finish_reason"), JsonRequired]
13 | public string FinishReason { get; private set; } = string.Empty;
14 |
15 | [JsonProperty("index"), JsonRequired]
16 | public uint Index { get; private set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Choice.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 138d845ffcbe4321817412258e26f52a
3 | timeCreated: 1677898713
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChoiceChunk.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class ChoiceChunk
8 | {
9 | [JsonProperty("delta"), JsonRequired]
10 | public Delta Delta { get; private set; } = new Delta();
11 |
12 | [JsonProperty("index"), JsonRequired]
13 | public uint Index { get; private set; }
14 |
15 | [JsonProperty("finish_reason")]
16 | public string? FinishReason { get; private set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ChoiceChunk.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8665be552963411681c201b9a1d7015b
3 | timeCreated: 1688472076
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Delta.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class Delta
8 | {
9 | [JsonProperty("role")]
10 | public string? RoleString { get; private set; }
11 |
12 | [JsonIgnore]
13 | public Role? Role => RoleString?.ToRole();
14 |
15 | [JsonProperty("content")]
16 | public string? Content { get; private set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Delta.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1419db37366c4e93a863f8fa2314a82c
3 | timeCreated: 1688472090
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Function.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | [JsonObject]
8 | public sealed class Function
9 | {
10 | ///
11 | /// [Required]
12 | /// The name of the function to be called.
13 | /// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
14 | ///
15 | [JsonProperty("name"), JsonRequired]
16 | public string Name { get; private set; }
17 |
18 | ///
19 | /// [Optional]
20 | /// The description of what the function does.
21 | ///
22 | [JsonProperty("description")]
23 | public string? Description { get; private set; }
24 |
25 | ///
26 | /// [Optional]
27 | /// The parameters the functions accepts, described as a JSON Schema object.
28 | /// See the guide for examples, and the JSON Schema reference for documentation about the format.
29 | ///
30 | [JsonProperty("parameters")]
31 | public IReadOnlyDictionary? Parameters { get; private set; }
32 |
33 | public Function(
34 | string name,
35 | string? description = null,
36 | IReadOnlyDictionary? parameters = null)
37 | {
38 | this.Name = name;
39 | this.Description = description;
40 | this.Parameters = parameters;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Function.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8021f5d4ad814075b9f2042e3dc5e344
3 | timeCreated: 1686712501
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/FunctionCall.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class FunctionCall
8 | {
9 | [JsonProperty("name"), JsonRequired]
10 | public string Name { get; private set; } = string.Empty;
11 |
12 | [JsonProperty("arguments"), JsonRequired]
13 | public string Arguments { get; private set; } = string.Empty;
14 | }
15 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/FunctionCall.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0c91ddcc75a2480e9b16e82ac7b2f041
3 | timeCreated: 1686711731
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/FunctionCallSpecifying.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class FunctionCallSpecifying
8 | {
9 | [JsonProperty("name"), JsonRequired]
10 | public string Name { get; private set; }
11 |
12 | public FunctionCallSpecifying(string name)
13 | {
14 | this.Name = name;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/FunctionCallSpecifying.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cc7908b8ce8346b0af3b822cfbef1ab1
3 | timeCreated: 1686718111
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/HttpClientPool.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Net.Http;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | ///
7 | /// Pools to save socket.
8 | ///
9 | public static class HttpClientPool
10 | {
11 | private static HttpClient pooledClient;
12 | ///
13 | /// Pooled .
14 | ///
15 | public static HttpClient PooledClient => pooledClient;
16 |
17 | static HttpClientPool()
18 | {
19 | pooledClient = new HttpClient();
20 | }
21 |
22 | ///
23 | /// Set external to share instance with other usages.
24 | ///
25 | ///
26 | ///
27 | public static void SetExternalClient(HttpClient external, bool disposeOldClient)
28 | {
29 | if (disposeOldClient)
30 | {
31 | pooledClient?.Dispose();
32 | }
33 |
34 | pooledClient = external;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/HttpClientPool.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 090ca7d8ed014d81ad5d5a2565009b18
3 | timeCreated: 1679288276
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/IChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace Mochineko.ChatGPT_API
7 | {
8 | ///
9 | /// Defines a memory of chat.
10 | ///
11 | public interface IChatMemory
12 | {
13 | ///
14 | /// Messages in the memory.
15 | ///
16 | IReadOnlyList Messages { get; }
17 | ///
18 | /// Adds a message to the memory.
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | Task AddMessageAsync(Message message, CancellationToken cancellationToken);
25 | ///
26 | /// Clears all messages in the memory.
27 | ///
28 | void ClearAllMessages();
29 | }
30 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/IChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6567dd9911e0490296cbbbe53e3dd84b
3 | timeCreated: 1678756910
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/InverseDictionaryExtension.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | internal static class InverseDictionaryExtension
8 | {
9 | public static T Inverse(this IReadOnlyDictionary dictionary, string key)
10 | where T : Enum
11 | {
12 | foreach (var pair in dictionary)
13 | {
14 | if (pair.Value == key)
15 | {
16 | return pair.Key;
17 | }
18 | }
19 |
20 | throw new KeyNotFoundException(key);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/InverseDictionaryExtension.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 39be0f3fa6104528993bafd606c32a5e
3 | timeCreated: 1677898758
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 mochineko
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 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7c66a528929ad41fd85641cbba792f21
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 23c4b26ed42b64a2ea1a2afb1c75e0fc
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteQueueChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace Mochineko.ChatGPT_API.Memory
7 | {
8 | ///
9 | /// A chat memory that stores messages in a finite queue.
10 | ///
11 | public sealed class FiniteQueueChatMemory : IChatMemory
12 | {
13 | private readonly Queue queue;
14 | private readonly int maxMemoriesCount;
15 | private readonly object lockObject = new();
16 |
17 | public IReadOnlyList Messages
18 | {
19 | get
20 | {
21 | lock (lockObject)
22 | {
23 | return queue.ToArray();
24 | }
25 | }
26 | }
27 |
28 | public FiniteQueueChatMemory(int maxMemoriesCount)
29 | {
30 | this.maxMemoriesCount = maxMemoriesCount;
31 | this.queue = new Queue(maxMemoriesCount);
32 | }
33 |
34 | public Task AddMessageAsync(Message message, CancellationToken cancellationToken)
35 | {
36 | cancellationToken.ThrowIfCancellationRequested();
37 |
38 | lock (lockObject)
39 | {
40 | queue.Enqueue(message);
41 |
42 | while (queue.Count > maxMemoriesCount)
43 | {
44 | queue.Dequeue();
45 | }
46 | }
47 |
48 | return Task.CompletedTask;
49 | }
50 |
51 | public void ClearAllMessages()
52 | {
53 | lock (lockObject)
54 | {
55 | queue.Clear();
56 | }
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteQueueChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cdc3177650b6a4cc49ec2c6e26932e22
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteQueueWithFixedPromptsChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace Mochineko.ChatGPT_API.Memory
8 | {
9 | ///
10 | /// A chat memory that stores messages in a finite queue with fixed prompts.
11 | ///
12 | public sealed class FiniteQueueWithFixedPromptsChatMemory : IChatMemory
13 | {
14 | private readonly int maxMemoriesCountWithoutPrompts;
15 | private readonly Queue queue;
16 | private readonly List prompts = new();
17 | private readonly object lockObject = new();
18 |
19 | public FiniteQueueWithFixedPromptsChatMemory(int maxMemoriesCountWithoutPrompts)
20 | {
21 | this.maxMemoriesCountWithoutPrompts = maxMemoriesCountWithoutPrompts;
22 | this.queue = new Queue(maxMemoriesCountWithoutPrompts);
23 | }
24 |
25 | public IReadOnlyList Messages
26 | {
27 | get
28 | {
29 | lock (lockObject)
30 | {
31 | return prompts
32 | .Concat(queue)
33 | .ToList();
34 | }
35 | }
36 | }
37 |
38 | public Task AddMessageAsync(Message message, CancellationToken cancellationToken)
39 | {
40 | cancellationToken.ThrowIfCancellationRequested();
41 |
42 | lock (lockObject)
43 | {
44 | if (message.Role is Role.System)
45 | {
46 | prompts.Add(message);
47 | }
48 | else
49 | {
50 | queue.Enqueue(message);
51 |
52 | while (queue.Count > maxMemoriesCountWithoutPrompts)
53 | {
54 | queue.Dequeue();
55 | }
56 | }
57 | }
58 |
59 | return Task.CompletedTask;
60 | }
61 |
62 | public void ClearAllMessages()
63 | {
64 | lock (lockObject)
65 | {
66 | prompts.Clear();
67 | queue.Clear();
68 | }
69 | }
70 |
71 | public void ClearMessagesWithoutPrompts()
72 | {
73 | lock (lockObject)
74 | {
75 | queue.Clear();
76 | }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteQueueWithFixedPromptsChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 09f383a371c334c57abdaf5ce0ba7f40
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteTokenLengthQueueChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using TiktokenSharp;
6 |
7 | namespace Mochineko.ChatGPT_API.Memory
8 | {
9 | ///
10 | /// A chat memory that stores messages in a queue that has finite lenght of tokens.
11 | ///
12 | public sealed class FiniteTokenLengthQueueChatMemory : IChatMemory
13 | {
14 | private readonly int maxTokenLength;
15 | private readonly TikToken tikToken;
16 | private readonly Queue queue = new();
17 | private readonly object lockObject = new();
18 |
19 | public FiniteTokenLengthQueueChatMemory(
20 | int maxTokenLength,
21 | Model model)
22 | {
23 | this.maxTokenLength = maxTokenLength;
24 | this.tikToken = TikToken.EncodingForModel(model.ToText());
25 | }
26 |
27 | public IReadOnlyList Messages
28 | {
29 | get
30 | {
31 | lock (lockObject)
32 | {
33 | return queue.ToArray();
34 | }
35 | }
36 | }
37 |
38 | public int TokenLength
39 | {
40 | get
41 | {
42 | lock (lockObject)
43 | {
44 | return queue.TokenLength(tikToken);
45 | }
46 | }
47 | }
48 |
49 | public Task AddMessageAsync(Message message, CancellationToken cancellationToken)
50 | {
51 | cancellationToken.ThrowIfCancellationRequested();
52 |
53 | lock (lockObject)
54 | {
55 | queue.Enqueue(message);
56 |
57 | while (TokenLength > maxTokenLength)
58 | {
59 | queue.Dequeue();
60 | }
61 | }
62 |
63 | return Task.CompletedTask;
64 | }
65 |
66 | public void ClearAllMessages()
67 | {
68 | lock (lockObject)
69 | {
70 | queue.Clear();
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteTokenLengthQueueChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 67cd3900272f34e19b07a1e11476c83e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteTokenLengthQueueWithFixedPromptsChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using TiktokenSharp;
7 |
8 | namespace Mochineko.ChatGPT_API.Memory
9 | {
10 | ///
11 | /// A chat memory that stores messages in a queue that has finite lenght of tokens with fixed prompts.
12 | ///
13 | public sealed class FiniteTokenLengthQueueWithFixedPromptsChatMemory : IChatMemory
14 | {
15 | private readonly int maxTokenLengthWithoutPrompts;
16 | private readonly TikToken tikToken;
17 | private readonly Queue queue = new();
18 | private readonly List prompts = new();
19 | private readonly object lockObject = new();
20 |
21 | public FiniteTokenLengthQueueWithFixedPromptsChatMemory(
22 | int maxTokenLengthWithoutPrompts,
23 | Model model)
24 | {
25 | this.maxTokenLengthWithoutPrompts = maxTokenLengthWithoutPrompts;
26 | this.tikToken = TikToken.EncodingForModel(model.ToText());
27 | }
28 |
29 | public IReadOnlyList Messages
30 | {
31 | get
32 | {
33 | lock (lockObject)
34 | {
35 | return prompts
36 | .Concat(queue)
37 | .ToList();
38 | }
39 | }
40 | }
41 |
42 | public int TokenLengthWithoutPrompts
43 | {
44 | get
45 | {
46 | lock (lockObject)
47 | {
48 | return queue.TokenLength(tikToken);
49 | }
50 | }
51 | }
52 |
53 | private int PromptsTokenLength
54 | {
55 | get
56 | {
57 | lock (lockObject)
58 | {
59 | return prompts.TokenLength(tikToken);
60 | }
61 | }
62 | }
63 |
64 | public int MemoriesTokenLength
65 | {
66 | get
67 | {
68 | lock (lockObject)
69 | {
70 | return PromptsTokenLength
71 | + TokenLengthWithoutPrompts;
72 | }
73 | }
74 | }
75 |
76 | public Task AddMessageAsync(Message message, CancellationToken cancellationToken)
77 | {
78 | lock (lockObject)
79 | {
80 | if (message.Role is Role.System)
81 | {
82 | prompts.Add(message);
83 | }
84 | else
85 | {
86 | queue.Enqueue(message);
87 |
88 | while (TokenLengthWithoutPrompts > maxTokenLengthWithoutPrompts)
89 | {
90 | queue.Dequeue();
91 | }
92 | }
93 | }
94 |
95 | return Task.CompletedTask;
96 | }
97 |
98 | public void ClearAllMessages()
99 | {
100 | lock (lockObject)
101 | {
102 | prompts.Clear();
103 | queue.Clear();
104 | }
105 | }
106 |
107 | public void ClearMessagesWithoutPrompts()
108 | {
109 | lock (lockObject)
110 | {
111 | queue.Clear();
112 | }
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/FiniteTokenLengthQueueWithFixedPromptsChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 637c72b2741fe47e0a8b07c32a7b4412
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/Mochineko.ChatGPT_API.Memory.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API.Memory",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:d63d7a0555b6b4b0a9148c0dbfcd7265",
6 | "GUID:17094be796ef04d9597855583d8aa5f6"
7 | ],
8 | "includePlatforms": [],
9 | "excludePlatforms": [],
10 | "allowUnsafeCode": false,
11 | "overrideReferences": true,
12 | "precompiledReferences": [],
13 | "autoReferenced": true,
14 | "defineConstraints": [],
15 | "versionDefines": [],
16 | "noEngineReferences": false
17 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/Mochineko.ChatGPT_API.Memory.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5ec8620e0ca6d4d9fb24dbcad8869bd5
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/TokenizerExtensions.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using TiktokenSharp;
4 |
5 | namespace Mochineko.ChatGPT_API.Memory
6 | {
7 | ///
8 | /// Extensions for .
9 | ///
10 | public static class TokenizerExtensions
11 | {
12 | ///
13 | /// Calculates the length of tokens of the messages.
14 | ///
15 | ///
16 | ///
17 | ///
18 | public static int TokenLength(
19 | this IEnumerable messages,
20 | TikToken tikToken)
21 | {
22 | var length = 0;
23 | foreach (var message in messages)
24 | {
25 | length += tikToken
26 | .Encode(message.Content)
27 | .Count;
28 | }
29 |
30 | return length;
31 | }
32 |
33 | ///
34 | /// Calculates the length of tokens of the message.
35 | ///
36 | ///
37 | ///
38 | ///
39 | public static int TokenLength(this Message message, TikToken tikToken)
40 | => tikToken
41 | .Encode(message.Content)
42 | .Count;
43 | }
44 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Memory/TokenizerExtensions.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2e2f62d0c88fd4ace840695cd07c24ec
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Message.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using Newtonsoft.Json;
4 |
5 | namespace Mochineko.ChatGPT_API
6 | {
7 | ///
8 | /// A message between user, assistant and system.
9 | ///
10 | [JsonObject]
11 | public sealed class Message
12 | {
13 | ///
14 | /// [Required]
15 | /// The role of the messages author.
16 | ///
17 | [JsonProperty("role"), JsonRequired]
18 | public string RoleString
19 | {
20 | get => this.Role.ToText();
21 | set => this.Role = value.ToRole();
22 | }
23 |
24 | ///
25 | /// [Required]
26 | /// The role of the messages author.
27 | ///
28 | [JsonIgnore]
29 | public Role Role { get; private set; }
30 |
31 | ///
32 | /// [Optional]
33 | /// The contents of the message.
34 | /// "content" is required for all messages except assistant messages with function calls.
35 | ///
36 | [JsonProperty("content")]
37 | public string? Content { get; internal set; }
38 |
39 | ///
40 | /// [Optional]
41 | /// The tool calls generated by the model, such as function calls.
42 | ///
43 | [JsonProperty("tool_calls")]
44 | public ToolCalling[]? ToolCalls { get; internal set; }
45 |
46 | ///
47 | /// [Optional]
48 | /// Tool call that this message is responding to.
49 | ///
50 | [JsonProperty("tool_call_id")]
51 | public string? ToolCallId { get; internal set; }
52 |
53 | ///
54 | /// [Optional]
55 | /// The name of the author of this message.
56 | /// "name" is required if role is "function", and it should be the name of the function whose response is in the "content".
57 | /// May contain a-z, A-Z, 0-9, and underscores, with a maximum length of 64 characters.
58 | ///
59 | [JsonProperty("name")]
60 | [Obsolete("Function calling is deprecated.")]
61 | public string? Name { get; private set; }
62 |
63 | ///
64 | /// [Optional]
65 | /// The name and arguments of a function that should be called, as generated by the model.
66 | ///
67 | [JsonProperty("function_call")]
68 | [Obsolete("Function calling is deprecated.")]
69 | public FunctionCall? FunctionCall { get; private set; }
70 |
71 | internal Message()
72 | {
73 | this.Role = Role.Assistant;
74 | this.Content = string.Empty;
75 | }
76 |
77 | public Message(
78 | Role role,
79 | string? content = null,
80 | ToolCalling[]? toolCalls = null,
81 | string? toolCallId = null,
82 | string? name = null,
83 | FunctionCall? functionCall = null)
84 | {
85 | this.Role = role;
86 | this.Content = content;
87 | this.ToolCalls = toolCalls;
88 | this.ToolCallId = toolCallId;
89 | this.Name = name;
90 | this.FunctionCall = functionCall;
91 | }
92 |
93 | public static Message CreateSystemMessage(string content)
94 | {
95 | return new Message(Role.System, content);
96 | }
97 |
98 | public static Message CreateUserMessage(string content)
99 | {
100 | return new Message(Role.User, content);
101 | }
102 |
103 | public static Message CreateAssistantMessage(
104 | string content,
105 | ToolCalling[]? toolCalls = null,
106 | FunctionCall? functionCall = null)
107 | {
108 | return new Message(Role.Assistant, content, toolCalls, null, null, functionCall);
109 | }
110 |
111 | public static Message CreateToolMessage(string content, string toolCallId)
112 | {
113 | return new Message(Role.Tool, content, null, toolCallId);
114 | }
115 |
116 | [Obsolete("Function calling is deprecated.")]
117 | public static Message CreateFunctionMessage(string content, string name)
118 | {
119 | return new Message(Role.Function, content, null, null, name);
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Message.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 10a473915a1a475b9660b2e9fd78e94d
3 | timeCreated: 1677898678
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Mochineko.ChatGPT_API.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.ChatGPT_API",
3 | "rootNamespace": "",
4 | "references": [],
5 | "includePlatforms": [],
6 | "excludePlatforms": [],
7 | "allowUnsafeCode": false,
8 | "overrideReferences": true,
9 | "precompiledReferences": [
10 | "Newtonsoft.Json.dll"
11 | ],
12 | "autoReferenced": true,
13 | "defineConstraints": [],
14 | "versionDefines": [],
15 | "noEngineReferences": false
16 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Mochineko.ChatGPT_API.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d63d7a0555b6b4b0a9148c0dbfcd7265
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Model.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | ///
7 | /// Chat model.
8 | /// See also https://platform.openai.com/docs/models/model-endpoint-compatibility.
9 | ///
10 | public enum Model : byte
11 | {
12 | ///
13 | /// "gpt-3.5-turbo" latest GPT-3.5 turbo model.
14 | ///
15 | Turbo,
16 | ///
17 | /// "gpt-3.5-turbo-0301" fixed GPT-3.5 turbo model at 03/01/2023.
18 | ///
19 | [Obsolete("This model version will be deprecated on 06/13/2024.")]
20 | Turbo0301,
21 | ///
22 | /// "gpt-3.5-turbo-0613" fixed GPT-3.5 turbo model at 06/13/2023.
23 | ///
24 | [Obsolete("This model version will be deprecated on 06/13/2024.")]
25 | Turbo0613,
26 | ///
27 | /// "gpt-3.5-turbo-1106" updated GPT-3.5 turbo model for 4k tokens at 11/06/2023.
28 | ///
29 | Turbo1106,
30 | ///
31 | /// "gpt-3.5-turbo-16k" latest GPT-3.5 turbo model for 16k tokens.
32 | ///
33 | Turbo16K,
34 | ///
35 | /// "gpt-3.5-turbo-16k-0613" fixed GPT-3.5 turbo model for 16k tokens at 06/13/2023.
36 | ///
37 | [Obsolete("This model version will be deprecated on 06/13/2024.")]
38 | Turbo16K0613,
39 | ///
40 | /// "gpt-4" latest GPT-4 model.
41 | ///
42 | Four,
43 | ///
44 | /// "gpt-4-0314", fixed GPT-4 model at 03/14/2023.
45 | ///
46 | [Obsolete("This model version will be deprecated on 06/13/2024.")]
47 | Four0314,
48 | ///
49 | /// "gpt-4-0613", fixed GPT-4 model at 06/13/2023.
50 | ///
51 | Four0613,
52 | ///
53 | /// "gpt-4-32k", latest GPT-4 model for 32k tokens.
54 | ///
55 | Four32K,
56 | ///
57 | /// "gpt-4-32k-0314", fixed GPT-4 model for 32k tokens at 03/14/2023.
58 | ///
59 | [Obsolete("This model version will be deprecated on 06/13/2024.")]
60 | Four32K0314,
61 | ///
62 | /// "gpt-4-32k-0613", fixed GPT-4 model for 32k tokens at 06/13/2023.
63 | ///
64 | Four32K0613,
65 | ///
66 | /// "gpt-4-1106-preview" latest GPT-4 turbo model for 4k tokens at 11/06/2023.
67 | ///
68 | Four1106Preview,
69 | ///
70 | /// "gpt-4-vision-preview" latest GPT-4 turbo with vision model.
71 | ///
72 | FourVisionPreview,
73 | }
74 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Model.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7325cb6c59b24335a0623346260fd444
3 | timeCreated: 1677898749
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ModelResolver.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | public static class ModelResolver
7 | {
8 | private static readonly IReadOnlyDictionary Dictionary = new Dictionary
9 | {
10 | [Model.Turbo] = "gpt-3.5-turbo",
11 | [Model.Turbo0301] = "gpt-3.5-turbo-0301",
12 | [Model.Turbo0613] = "gpt-3.5-turbo-0613",
13 | [Model.Turbo1106] = "gpt-3.5-turbo-1106",
14 | [Model.Turbo16K] = "gpt-3.5-turbo-16k",
15 | [Model.Turbo16K0613] = "gpt-3.5-turbo-16k-0613",
16 | [Model.Four] = "gpt-4",
17 | [Model.Four0314] = "gpt-4-0314",
18 | [Model.Four0613] = "gpt-4-0613",
19 | [Model.Four32K] = "gpt-4-32k",
20 | [Model.Four32K0314] = "gpt-4-32k-0314",
21 | [Model.Four32K0613] = "gpt-4-32k-0613",
22 | [Model.Four1106Preview] = "gpt-4-1106-preview",
23 | [Model.FourVisionPreview] = "gpt-4-vision-preview",
24 | };
25 |
26 | public static Model ToModel(this string model)
27 | => Dictionary.Inverse(model);
28 |
29 | public static string ToText(this Model model)
30 | => Dictionary[model];
31 | }
32 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ModelResolver.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 71e96d200af047cf99762f22737f549f
3 | timeCreated: 1677898745
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Role.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | public enum Role : byte
7 | {
8 | ///
9 | /// "system" that instructs behavior of completion.
10 | ///
11 | System,
12 | ///
13 | /// "assistant" that is generated message by completion.
14 | ///
15 | Assistant,
16 | ///
17 | /// "user" that is input message by user.
18 | ///
19 | User,
20 | ///
21 | /// "function" that is generated message by function calling.
22 | ///
23 | [Obsolete("Deprecated and replaced by tool")]
24 | Function,
25 | ///
26 | /// "tool" that is generated message by tools.
27 | ///
28 | Tool,
29 | }
30 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Role.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 291cfa31724c4218abbb11e8f847651a
3 | timeCreated: 1677898753
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/RoleResolver.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | public static class RoleResolver
7 | {
8 | private static readonly IReadOnlyDictionary Dictionary = new Dictionary
9 | {
10 | [Role.System] = "system",
11 | [Role.Assistant] = "assistant",
12 | [Role.User] = "user",
13 | [Role.Function] = "function",
14 | };
15 |
16 | public static Role ToRole(this string role)
17 | => Dictionary.Inverse(role);
18 |
19 | public static string ToText(this Role role)
20 | => Dictionary[role];
21 | }
22 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/RoleResolver.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4620919ab702424199adeb7de7a538c8
3 | timeCreated: 1677898728
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/SimpleChatMemory.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace Mochineko.ChatGPT_API
7 | {
8 | public sealed class SimpleChatMemory : IChatMemory
9 | {
10 | private readonly List messages = new();
11 | public IReadOnlyList Messages
12 | {
13 | get
14 | {
15 | lock (lockObject)
16 | {
17 | return messages;
18 | }
19 | }
20 | }
21 |
22 | private readonly object lockObject = new();
23 |
24 | public Task AddMessageAsync(Message message, CancellationToken cancellationToken)
25 | {
26 | cancellationToken.ThrowIfCancellationRequested();
27 |
28 | lock (lockObject)
29 | {
30 | messages.Add(message);
31 | }
32 |
33 | return Task.CompletedTask;
34 | }
35 |
36 | public void ClearAllMessages()
37 | {
38 | lock (lockObject)
39 | {
40 | messages.Clear();
41 | }
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/SimpleChatMemory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9f4e3cbc49ce4b07a6c237dbdfa98a81
3 | timeCreated: 1678756920
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fa05d867492be4aaf946d2f3a1d44d7a
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/CoreBPE.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using TiktokenSharp.Utils;
8 |
9 | namespace TiktokenSharp
10 | {
11 | public class CoreBPE
12 | {
13 | private Dictionary _specialTokensEncoder { get; set; }
14 |
15 | // TODO private max_token_value ??
16 | private Dictionary _encoder { get; set; }
17 |
18 | private Regex _specialRegex { get; set; }
19 |
20 | private Regex _regex { get; set; }
21 |
22 | private Dictionary _decoder { get; set; }
23 |
24 |
25 | private Dictionary _specialTokensDecoder { get; set; }
26 |
27 | ///
28 | ///
29 | ///
30 | ///
31 | ///
32 | ///
33 | public CoreBPE(Dictionary encoder, Dictionary specialTokensEncoder, string pattern)
34 | {
35 | _encoder = encoder;
36 | _regex = new Regex(pattern);
37 | _specialRegex = new Regex(string.Join("|", specialTokensEncoder.Keys.Select(s => Regex.Escape(s))));
38 | _specialTokensEncoder = specialTokensEncoder;
39 |
40 | _decoder = _encoder.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
41 |
42 | if (_encoder.Count != _decoder.Count)
43 | {
44 | throw new ArgumentException("Encoder and decoder sizes don't match");
45 | }
46 |
47 | _specialTokensDecoder = specialTokensEncoder.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
48 |
49 | var sortedTokenBytes = _encoder.Keys.ToList();
50 | }
51 |
52 |
53 | public (List, int) EncodeNative(string text, HashSet allowedSpecial)
54 | {
55 | Regex specialRegex = _specialRegex;
56 | Regex regex = _regex;
57 | var ret = new List();
58 |
59 | int start = 0;
60 | int lastPieceTokenLen = 0;
61 | while (true)
62 | {
63 | Match nextSpecial;
64 | int startFind = start;
65 | while (true)
66 | {
67 | nextSpecial = specialRegex.Match(text, startFind);
68 | if (!nextSpecial.Success) break;
69 | if (allowedSpecial.Contains(text.Substring(nextSpecial.Index, nextSpecial.Length))) break;
70 | startFind = nextSpecial.Index + 1;
71 | }
72 |
73 | int end = nextSpecial.Success ? nextSpecial.Index : text.Length;
74 |
75 | foreach (Match mat in regex.Matches(text.Substring(start, end - start)))
76 | {
77 | var piece = Encoding.UTF8.GetBytes(mat.Value);
78 | if (_encoder.TryGetValue(piece, out int token))
79 | {
80 | lastPieceTokenLen = 1;
81 | ret.Add(token);
82 | continue;
83 | }
84 |
85 | var tokens = BytePairEncoding.BytePairEncode(piece, _encoder);
86 | lastPieceTokenLen = tokens.Count;
87 | ret.AddRange(tokens);
88 | }
89 |
90 | if (nextSpecial.Success)
91 | {
92 | var piece = nextSpecial.Value;
93 | var token = _specialTokensEncoder[piece];
94 | ret.Add(token);
95 | start = nextSpecial.Index + nextSpecial.Length;
96 | lastPieceTokenLen = 0;
97 | }
98 | else
99 | {
100 | break;
101 | }
102 | }
103 |
104 | return (ret, lastPieceTokenLen);
105 | }
106 |
107 |
108 | public byte[] DecodeNative(int[] tokens)
109 | {
110 | var ret = new List(tokens.Length * 2);
111 | foreach (var token in tokens)
112 | {
113 | byte[] tokenBytes = { };
114 | if (_decoder.TryGetValue(token, out var value))
115 | {
116 | tokenBytes = value;
117 | }
118 | else
119 | {
120 | if (_specialTokensDecoder.TryGetValue(token, out var valueS))
121 | {
122 | tokenBytes = UTF8Encoding.UTF8.GetBytes(valueS);
123 | }
124 | }
125 |
126 | if (tokenBytes.Length > 0)
127 | {
128 | ret.AddRange(tokenBytes);
129 | }
130 | }
131 |
132 | return ret.ToArray();
133 | }
134 |
135 | // NOTE: Extended
136 | public byte[] DecodeNative(int token)
137 | {
138 | if (_decoder.TryGetValue(token, out var value))
139 | {
140 | return value;
141 | }
142 | else if (_specialTokensDecoder.TryGetValue(token, out var valueS))
143 | {
144 | return UTF8Encoding.UTF8.GetBytes(valueS);
145 | }
146 | else
147 | {
148 | return null;
149 | }
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/CoreBPE.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a33e294677cd841fba78f4a6d92ca539
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8c5145f563c83476f9da623336eeab46
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Editor/Mochineko.TiktokenSharp.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.TiktokenSharp.Editor",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:17094be796ef04d9597855583d8aa5f6"
6 | ],
7 | "includePlatforms": [
8 | "Editor"
9 | ],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false,
12 | "overrideReferences": true,
13 | "precompiledReferences": [],
14 | "autoReferenced": false,
15 | "defineConstraints": [],
16 | "versionDefines": [],
17 | "noEngineReferences": false
18 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Editor/Mochineko.TiktokenSharp.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3e343587e65714ec1a511c5e1bc5024d
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Editor/TiktokenEditor.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 | namespace TiktokenSharp.Editor
7 | {
8 | internal sealed class TiktokenEditor : EditorWindow
9 | {
10 | [MenuItem("Mochineko/TiktokenEditor")]
11 | public static void Open()
12 | {
13 | GetWindow("Tiktoken");
14 | }
15 |
16 | private string model = "gpt-3.5-turbo";
17 | private string text = string.Empty;
18 | private List? tokens = null;
19 | private List? tokenizedText = null;
20 | private Vector2 scrollPosition = Vector2.zero;
21 |
22 | private void OnGUI()
23 | {
24 | EditorGUILayout.Space();
25 |
26 | model = EditorGUILayout.TextField("Model", model);
27 |
28 | EditorGUILayout.Space();
29 |
30 | EditorGUILayout.LabelField("Text:");
31 | text = EditorGUILayout.TextArea(text);
32 |
33 | EditorGUILayout.Space();
34 |
35 | if (GUILayout.Button("Tokenize"))
36 | {
37 | var tikToken = TikToken.EncodingForModel(model);
38 | tokens = tikToken.Encode(text);
39 | tokenizedText = Decode(tikToken, tokens);
40 | }
41 |
42 | EditorGUILayout.Space();
43 |
44 | EditorGUILayout.LabelField(
45 | "Token Length:",
46 | tokens != null ? tokens.Count.ToString() : "0");
47 |
48 | EditorGUILayout.Space();
49 |
50 | if (tokens != null && tokenizedText != null)
51 | {
52 | EditorGUILayout.LabelField("Tokens:");
53 | using (var scroll = new EditorGUILayout.ScrollViewScope(scrollPosition))
54 | using (_ = new EditorGUI.IndentLevelScope())
55 | {
56 | scrollPosition = scroll.scrollPosition;
57 | for (var i = 0; i < tokens.Count; i++)
58 | {
59 | EditorGUILayout.LabelField(
60 | $"{i}: {tokens[i]}",
61 | $"< {tokenizedText[i]}");
62 | }
63 | }
64 | }
65 | }
66 |
67 | private static List Decode(TikToken tikToken, List tokens)
68 | {
69 | var result = new List();
70 | for (var i = 0; i < tokens.Count; i++)
71 | {
72 | var tokenized = tikToken.Decode(tokens[i]);
73 | Debug.Log($"{i}:{tokenized}");
74 | result.Add(tokenized);
75 | }
76 |
77 | return result;
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Editor/TiktokenEditor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b1b431aac88da4e24bb0a1abecd481e3
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 aiqinxuancai
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 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/LICENSE.txt.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 25d4494fa17fc4b119a4b69a9ed2d7b9
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Mochineko.TiktokenSharp.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.TiktokenSharp",
3 | "rootNamespace": "",
4 | "references": [],
5 | "includePlatforms": [],
6 | "excludePlatforms": [],
7 | "allowUnsafeCode": false,
8 | "overrideReferences": true,
9 | "precompiledReferences": [],
10 | "autoReferenced": false,
11 | "defineConstraints": [],
12 | "versionDefines": [],
13 | "noEngineReferences": false
14 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Mochineko.TiktokenSharp.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 17094be796ef04d9597855583d8aa5f6
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Model.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fabb0685b34ff445d92f92a0bb7cf8b5
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Model/EncodingSettingModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using TiktokenSharp.Utils;
8 |
9 | namespace TiktokenSharp.Model
10 | {
11 | public class EncodingSettingModel
12 | {
13 | public string Name { get; set; }
14 |
15 | ///
16 | /// regex
17 | ///
18 | public string PatStr { get; set; }
19 |
20 |
21 | public int? ExplicitNVocab { get; set; }
22 |
23 | ///
24 | /// tiktoken file
25 | ///
26 | public Dictionary MergeableRanks { get; set; }
27 |
28 | public Dictionary SpecialTokens { get; set; }
29 |
30 |
31 | public int MaxTokenValue {
32 | get {
33 | return Math.Max(MergeableRanks.Values.Max(), SpecialTokens.Values.Max());
34 | }
35 | }
36 |
37 | public EncodingSettingModel() { }
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Model/EncodingSettingModel.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 182377632773548c0a48bcfc77b09e62
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Services.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 47fa7784e78084c7aba599117bd8dcff
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Services/EncodingManager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fcc88300b26cb419db83c75b1a34adeb
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/TikToken.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.CompilerServices;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 | using TiktokenSharp.Model;
9 | using TiktokenSharp.Services;
10 | using UnityEngine;
11 | using Debug = System.Diagnostics.Debug;
12 |
13 | namespace TiktokenSharp
14 | {
15 | public class TikToken
16 | {
17 |
18 | ///
19 | /// You can set this item before EncodingForModel to specify the location for storing and downloading the bpe file. If not set, it defaults to the AppContext.BaseDirectory\bpe directory.
20 | ///
21 | // NOTE: Override default path for Unity
22 | public static string PBEFileDirectory { get; set; } = Path.Combine(Application.persistentDataPath, "TikToken", "bpe"); // = Path.Combine(AppContext.BaseDirectory, "bpe");
23 |
24 | ///
25 | /// get encoding
26 | ///
27 | /// gpt-3.5-turbo
28 | ///
29 | public static TikToken EncodingForModel(string modelName)
30 | {
31 | EncodingManager.Instance.PBEFileDirectory = PBEFileDirectory;
32 | var setting = EncodingManager.Instance.GetEncodingSetting(modelName);
33 | return new TikToken(setting);
34 | }
35 |
36 | public static Regex SpecialTokenRegex(HashSet tokens)
37 | {
38 | var inner = string.Join("|", tokens.Select(Regex.Escape));
39 | return new Regex($"({inner})");
40 | }
41 |
42 | private CoreBPE _corePBE;
43 |
44 | private EncodingSettingModel _setting;
45 |
46 | public TikToken(EncodingSettingModel setting)
47 | {
48 |
49 |
50 | if (setting.ExplicitNVocab != null)
51 | {
52 | Debug.Assert(setting.SpecialTokens.Count + setting.MergeableRanks.Count == setting.ExplicitNVocab);
53 | Debug.Assert(setting.MaxTokenValue == setting.ExplicitNVocab - 1);
54 | }
55 |
56 |
57 |
58 | _corePBE = new CoreBPE(setting.MergeableRanks, setting.SpecialTokens, setting.PatStr);
59 | _setting = setting;
60 | }
61 |
62 | public HashSet SpecialTokensSet()
63 | {
64 | return new HashSet(_setting.SpecialTokens.Keys);
65 | }
66 |
67 | public List Encode(string text, object allowedSpecial = null, object disallowedSpecial = null)
68 | {
69 | if (allowedSpecial == null)
70 | {
71 | allowedSpecial = new HashSet();
72 | }
73 | if (disallowedSpecial == null)
74 | {
75 | disallowedSpecial = "all";
76 | }
77 |
78 |
79 |
80 | var allowedSpecialSet = allowedSpecial.Equals("all") ? SpecialTokensSet() : new HashSet((IEnumerable)allowedSpecial);
81 | var disallowedSpecialSet = disallowedSpecial.Equals("all") ? new HashSet(SpecialTokensSet().Except(allowedSpecialSet)) : new HashSet((IEnumerable)disallowedSpecial);
82 |
83 | if (disallowedSpecialSet.Count() > 0)
84 | {
85 | var specialTokenRegex = SpecialTokenRegex(disallowedSpecialSet);
86 | var match = specialTokenRegex.Match(text);
87 | if (match.Success)
88 | {
89 | throw new Exception(match.Value);
90 | }
91 | }
92 |
93 | return _corePBE.EncodeNative(text, allowedSpecialSet).Item1;
94 | }
95 |
96 |
97 | public string Decode(List tokens)
98 | {
99 | var ret = _corePBE.DecodeNative(tokens.ToArray());
100 | string str = Encoding.UTF8.GetString(ret.ToArray());
101 | return str;
102 | }
103 |
104 | // NOTE: Extended
105 | public string Decode(int token)
106 | {
107 | var ret = _corePBE.DecodeNative(token);
108 | if (ret != null)
109 | {
110 | return Encoding.UTF8.GetString(ret);
111 | }
112 | else
113 | {
114 | return null;
115 | }
116 | }
117 |
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/TikToken.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fffd7a0fd308444ee93a950f7cad906f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Utils.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 884aa3bfb4fb144c68f7f35df076da05
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Utils/ByteArrayComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace TiktokenSharp.Utils
6 | {
7 | public class ByteArrayComparer : IEqualityComparer
8 | {
9 | public bool Equals(byte[] x, byte[] y)
10 | {
11 | if (x == null || y == null)
12 | {
13 | return x == y;
14 | }
15 | if (x.Length != y.Length)
16 | {
17 | return false;
18 | }
19 | for (int i = 0; i < x.Length; i++)
20 | {
21 | if (x[i] != y[i])
22 | {
23 | return false;
24 | }
25 | }
26 | return true;
27 | }
28 |
29 | public int GetHashCode(byte[] obj)
30 | {
31 | if (obj == null)
32 | {
33 | throw new ArgumentNullException(nameof(obj));
34 | }
35 | int hash = 17;
36 | foreach (byte b in obj)
37 | {
38 | hash = hash * 31 + b;
39 | }
40 | return hash;
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Utils/ByteArrayComparer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3c65795e1b13447c48d2cfda2641d810
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Utils/BytePairEncoding.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 |
6 | namespace TiktokenSharp.Utils
7 | {
8 |
9 | public class BytePairEncoding
10 | {
11 | static List BytePairMerge(byte[] piece, Dictionary ranks, Func f)
12 | {
13 | var parts = Enumerable.Range(0, piece.Length + 1).Select(i => (i, int.MaxValue)).ToList();
14 | int? GetRank(int startIdx, int skip = 0)
15 | {
16 | if (startIdx + skip + 2 < parts.Count)
17 | {
18 | var slice = piece[parts[startIdx].Item1..parts[startIdx + skip + 2].Item1];
19 | if (ranks.TryGetValue(slice, out var rank))
20 | {
21 | return rank;
22 | }
23 | }
24 | return null;
25 | }
26 | for (int i = 0; i < parts.Count - 2; i++)
27 | {
28 | var rank = GetRank(i);
29 | if (rank != null)
30 | {
31 | Debug.Assert(rank.Value != int.MaxValue);
32 | parts[i] = (parts[i].Item1, rank.Value);
33 | }
34 | }
35 | while (parts.Count > 1)
36 | {
37 | var minRank = (int.MaxValue, 0);
38 | for (int i = 0; i < parts.Count - 1; i++)
39 | {
40 | if (parts[i].Item2 < minRank.Item1)
41 | {
42 | minRank = (parts[i].Item2, i);
43 | }
44 | }
45 | if (minRank.Item1 != int.MaxValue)
46 | {
47 | int i = minRank.Item2;
48 | parts[i] = (parts[i].Item1, GetRank(i, 1) ?? int.MaxValue);
49 | if (i > 0)
50 | {
51 | parts[i - 1] = (parts[i - 1].Item1, GetRank(i - 1, 1) ?? int.MaxValue);
52 | }
53 | parts.RemoveAt(i + 1);
54 | }
55 | else
56 | {
57 | break;
58 | }
59 | }
60 | var outList = new List(parts.Count - 1);
61 | for (int i = 0; i < parts.Count - 1; i++)
62 | {
63 | outList.Add(f(parts[i].Item1..parts[i + 1].Item1));
64 | }
65 | return outList;
66 | }
67 |
68 | public static List BytePairEncode(byte[] piece, Dictionary ranks)
69 | {
70 | if (piece.Length == 1)
71 | {
72 | return new List { ranks[piece] };
73 | }
74 | return BytePairMerge(piece, ranks, p => ranks[piece[p.Start..p.End]]);
75 | }
76 |
77 | public static List BytePairSplit(byte[] piece, Dictionary ranks)
78 | {
79 | if (piece.Length == 1)
80 | {
81 | return new List { piece };
82 | }
83 | return BytePairMerge(piece, ranks, p => piece[p.Start..p.End]);
84 | }
85 |
86 |
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/TiktokenSharp/Utils/BytePairEncoding.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 274db0bc52ec64be9b9ce7c48401e942
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ToolCalling.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class ToolCalling
8 | {
9 | ///
10 | /// [Required]
11 | /// The ID of the tool call.
12 | ///
13 | [JsonProperty("id"), JsonRequired]
14 | public string ID { get; private set; } = string.Empty;
15 |
16 | ///
17 | /// [Required]
18 | /// The type of the tool. Currently, only function is supported.
19 | ///
20 | [JsonProperty("type"), JsonRequired]
21 | public string Type { get; private set; } = string.Empty;
22 |
23 | ///
24 | /// [Required]
25 | /// The function that the model called.
26 | ///
27 | [JsonProperty("function"), JsonRequired]
28 | public ToolFunction Function { get; private set; } = new();
29 | }
30 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ToolCalling.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f655869ffdcc4468acb84b37e2c5aca4
3 | timeCreated: 1699355715
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ToolFunction.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class ToolFunction
8 | {
9 | ///
10 | /// [Required]
11 | /// The name of the function to call.
12 | ///
13 | [JsonProperty("name"), JsonRequired]
14 | public string Name { get; private set; } = string.Empty;
15 |
16 | ///
17 | /// [Required]
18 | /// The arguments to call the function with, as generated by the model in JSON format.
19 | /// Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema.
20 | /// Validate the arguments in your code before calling your function.
21 | ///
22 | [JsonProperty("arguments"), JsonRequired]
23 | public string Arguments { get; private set; } = string.Empty;
24 | }
25 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/ToolFunction.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9705c8f9c90949b0b71eb6b74de997bf
3 | timeCreated: 1699355723
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Usage.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Newtonsoft.Json;
3 |
4 | namespace Mochineko.ChatGPT_API
5 | {
6 | [JsonObject]
7 | public sealed class Usage
8 | {
9 | [JsonProperty("prompt_tokens")] public int PromptTokens { get; private set; }
10 | [JsonProperty("completion_tokens")] public int CompletionTokens { get; private set; }
11 | [JsonProperty("total_tokens")] public int TotalTokens { get; private set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/Usage.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cbf5b3b3260744e292bd0f6c10dfd624
3 | timeCreated: 1677898695
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.mochineko.chatgpt-api",
3 | "version": "0.7.3",
4 | "displayName": "ChatGPT API",
5 | "description": "ChatGPT chat completion API bindings to pure C#.",
6 | "unity": "2021.3",
7 | "author": {
8 | "name": "Mochineko",
9 | "email": "t.o.e.4315@gmail.com"
10 | },
11 | "dependencies": {
12 | "com.unity.nuget.newtonsoft-json": "3.0.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/ChatGPT_API/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5059804330bd24d919918ce18207ed4e
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/TiktokenSharp.Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a16c834beb5a44625a7269087fe5bfad
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Mochineko/TiktokenSharp.Tests/Mochineko.TiktokenSharp.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mochineko.TiktokenSharp.Tests",
3 | "rootNamespace": "",
4 | "references": [
5 | "GUID:27619889b8ba8c24980f49ee34dbb44a",
6 | "GUID:0acc523941302664db1f4e527237feb3",
7 | "GUID:17094be796ef04d9597855583d8aa5f6",
8 | "GUID:e372c541aba5148868e12aa078ca7c20"
9 | ],
10 | "includePlatforms": [
11 | "Editor"
12 | ],
13 | "excludePlatforms": [],
14 | "allowUnsafeCode": false,
15 | "overrideReferences": true,
16 | "precompiledReferences": [
17 | "nunit.framework.dll"
18 | ],
19 | "autoReferenced": false,
20 | "defineConstraints": [
21 | "UNITY_INCLUDE_TESTS"
22 | ],
23 | "versionDefines": [],
24 | "noEngineReferences": false
25 | }
--------------------------------------------------------------------------------
/Assets/Mochineko/TiktokenSharp.Tests/Mochineko.TiktokenSharp.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1d92c6ac152fd4c248095d4df74fe17a
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Mochineko/TiktokenSharp.Tests/TiktokenTest.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using FluentAssertions;
4 | using NUnit.Framework;
5 | using UnityEngine.TestTools;
6 |
7 | namespace TiktokenSharp.Tests
8 | {
9 | [TestFixture]
10 | internal sealed class TiktokenTest
11 | {
12 | [TestCase("gpt-3.5-turbo", "hello world", new[] { 15339, 1917 }, null)]
13 | [TestCase("gpt-3.5-turbo", "hello <|endoftext|>", new[] { 15339, 220, 100257 }, "all")]
14 | [TestCase("text-davinci-003", "hello world", new[] { 31373, 995 }, null)]
15 | [TestCase("text-davinci-003", "hello <|endoftext|>", new[] { 31373, 220, 50256 }, "all")]
16 | [RequiresPlayMode(false)]
17 | public void TokenizeTest(string model, string text, int[] expected, object allowedSpecial)
18 | {
19 | var tikToken = TikToken.EncodingForModel(model);
20 |
21 | var tokens = tikToken.Encode(text, allowedSpecial);
22 | var decoded = tikToken.Decode(tokens);
23 |
24 | tokens.Count.Should().Be(expected.Length);
25 | ShouldBeSameAs(expected, tokens);
26 |
27 | decoded.Should().Be(text);
28 | tikToken.Decode(new List(expected)).Should().Be(text);
29 | }
30 |
31 | private void ShouldBeSameAs(T[] expected, List actual)
32 | {
33 | actual.Count.Should().Be(expected.Length);
34 | for (var i = 0; i < expected.Length; i++)
35 | {
36 | actual[i].Should().Be(expected[i]);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Assets/Mochineko/TiktokenSharp.Tests/TiktokenTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a61aa74cfb0d04e1e98fdc449d7d985a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.7.3] - 2023-07-21
11 |
12 | ### Fixed
13 |
14 | - Fix default path to save PBE file in TikTokenSharp.
15 | - Fill recorded message content with empty string because messages in request parameter must have content field.
16 |
17 | ## [0.7.2] - 2023-07-12
18 |
19 | ### Fixed
20 |
21 | - Fix dependencies in `package.json`.
22 |
23 | ## [0.7.1] - 2023-07-05
24 |
25 | ### Fixed
26 |
27 | - Fix request to add `HttpCompletionOption.ResponseHeadersRead` to Relent streaming API.
28 |
29 | ## [0.7.0] - 2023-07-05
30 |
31 | ### Added
32 |
33 | - Add Streaming API sample.
34 |
35 | ### Changed
36 |
37 | - Change streaming API to use `IAsyncEnumerable`.
38 | - Change to `UniTask` from `Task` in Relent API.
39 |
40 | ## [0.6.0] - 2023-06-14
41 |
42 | ### Added
43 |
44 | - Add 16k context turbo model option.
45 | - Add function calling support.
46 | - Add optional `name` property to `Message`.
47 | - Add verbose log option.
48 |
49 | ## Changed
50 |
51 | - Update chat models at 2023-06-13.
52 | - Add dependencies to `package.json`.
53 |
54 | ## [0.5.0] - 2023-04-08
55 |
56 | ### Changed
57 |
58 | - Simplify package structure.
59 | - Update Relent version to 0.2.0.
60 |
61 | ## [0.4.0] - 2023-03-25
62 |
63 | ### Added
64 |
65 | - Add extensions of `IChatMemory`.
66 |
67 | ### Changed
68 |
69 | - Improve interface of `IChatMemory` for async operation.
70 | - Be `IChatMemory` implementations thread-safe.
71 |
72 | ### Fixed
73 |
74 | - Fix capacity of `FiniteQueueChatMemory`.
75 |
76 | ## [0.3.1] - 2023-03-25
77 |
78 | ### Changed
79 |
80 | - Improve accessibility of `Messaage`.
81 |
82 | ## [0.3.0] - 2023-03-23
83 |
84 | ### Added
85 |
86 | - Add `TiktokenSharp` that is a tokenizer to calculate token length of text in local.
87 |
88 | ## [0.2.2] - 2023-03-21
89 |
90 | ### Added
91 |
92 | - Add option to specify instance of `HttpClient`.
93 | - Add option to receive response as `Stream`.
94 |
95 | ### Changed
96 |
97 | - Improve null check of response content.
98 |
99 | ## [0.2.1] - 2023-03-20
100 |
101 | ### Added
102 |
103 | - Add GPT-4 all models.
104 |
105 | ## [0.2.0] - 2023-03-20
106 |
107 | ### Added
108 |
109 | - Add memory management of chat completion API by `IChatMemory`.
110 | - Add [resilient error handling implementation](https://github.com/mochi-neko/ChatGPT-API-unity/blob/main/Assets/Mochineko/ChatGPT_API.Relent/RelentChatCompletionAPIConnection.cs) of chat completion API by [Relent](https://github.com/mochi-neko/Relent).
111 | - Add GPT-4 model enum.
112 |
113 | ### Changed
114 |
115 | - Change name and arguments of completion method.
116 |
117 | ### Fixed
118 |
119 | - Fix deserialization error of `"usage"` in response body.
120 |
121 | ## [0.1.1] - 2023-03-06
122 |
123 | ### Added
124 |
125 | - Add optional request parameters.
126 |
127 | ### Fixed
128 |
129 | - Fix error handling of API response.
130 |
131 | ## [0.1.0] - 2023-03-04
132 |
133 | ### Added
134 |
135 | - Implement ChatGPT chat completion API bindings to C#.
136 | - Implement sample component of ChatGPT API.
137 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 mochineko
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 |
--------------------------------------------------------------------------------
/Packages/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.mochineko.relent": "https://github.com/mochi-neko/Relent.git?path=/Assets/Mochineko/Relent#0.2.0",
4 | "com.boundfoxstudios.fluentassertions": "https://github.com/BoundfoxStudios/fluentassertions-unity.git#upm",
5 | "com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
6 | "com.unity.nuget.newtonsoft-json": "3.0.2",
7 | "com.unity.collab-proxy": "1.15.15",
8 | "com.unity.feature.development": "1.0.1",
9 | "com.unity.ide.rider": "3.0.18",
10 | "com.unity.ide.visualstudio": "2.0.14",
11 | "com.unity.ide.vscode": "1.2.5",
12 | "com.unity.test-framework": "2.0.1-pre.18",
13 | "com.unity.textmeshpro": "3.0.6",
14 | "com.unity.timeline": "1.6.4",
15 | "com.unity.ugui": "1.0.0",
16 | "com.unity.visualscripting": "1.7.6",
17 | "com.unity.modules.ai": "1.0.0",
18 | "com.unity.modules.androidjni": "1.0.0",
19 | "com.unity.modules.animation": "1.0.0",
20 | "com.unity.modules.assetbundle": "1.0.0",
21 | "com.unity.modules.audio": "1.0.0",
22 | "com.unity.modules.cloth": "1.0.0",
23 | "com.unity.modules.director": "1.0.0",
24 | "com.unity.modules.imageconversion": "1.0.0",
25 | "com.unity.modules.imgui": "1.0.0",
26 | "com.unity.modules.jsonserialize": "1.0.0",
27 | "com.unity.modules.particlesystem": "1.0.0",
28 | "com.unity.modules.physics": "1.0.0",
29 | "com.unity.modules.physics2d": "1.0.0",
30 | "com.unity.modules.screencapture": "1.0.0",
31 | "com.unity.modules.terrain": "1.0.0",
32 | "com.unity.modules.terrainphysics": "1.0.0",
33 | "com.unity.modules.tilemap": "1.0.0",
34 | "com.unity.modules.ui": "1.0.0",
35 | "com.unity.modules.uielements": "1.0.0",
36 | "com.unity.modules.umbra": "1.0.0",
37 | "com.unity.modules.unityanalytics": "1.0.0",
38 | "com.unity.modules.unitywebrequest": "1.0.0",
39 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
40 | "com.unity.modules.unitywebrequestaudio": "1.0.0",
41 | "com.unity.modules.unitywebrequesttexture": "1.0.0",
42 | "com.unity.modules.unitywebrequestwww": "1.0.0",
43 | "com.unity.modules.vehicles": "1.0.0",
44 | "com.unity.modules.video": "1.0.0",
45 | "com.unity.modules.vr": "1.0.0",
46 | "com.unity.modules.wind": "1.0.0",
47 | "com.unity.modules.xr": "1.0.0"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!11 &1
4 | AudioManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Volume: 1
8 | Rolloff Scale: 1
9 | Doppler Factor: 1
10 | Default Speaker Mode: 2
11 | m_SampleRate: 0
12 | m_DSPBufferSize: 1024
13 | m_VirtualVoiceCount: 512
14 | m_RealVoiceCount: 32
15 | m_SpatializerPlugin:
16 | m_AmbisonicDecoderPlugin:
17 | m_DisableAudio: 0
18 | m_VirtualizeEffects: 1
19 | m_RequestedDSPBufferSize: 1024
20 |
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!236 &1
4 | ClusterInputManager:
5 | m_ObjectHideFlags: 0
6 | m_Inputs: []
7 |
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!55 &1
4 | PhysicsManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 11
7 | m_Gravity: {x: 0, y: -9.81, z: 0}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_BounceThreshold: 2
10 | m_SleepThreshold: 0.005
11 | m_DefaultContactOffset: 0.01
12 | m_DefaultSolverIterations: 6
13 | m_DefaultSolverVelocityIterations: 1
14 | m_QueriesHitBackfaces: 0
15 | m_QueriesHitTriggers: 1
16 | m_EnableAdaptiveForce: 0
17 | m_ClothInterCollisionDistance: 0
18 | m_ClothInterCollisionStiffness: 0
19 | m_ContactsGeneration: 1
20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
21 | m_AutoSimulation: 1
22 | m_AutoSyncTransforms: 0
23 | m_ReuseCollisionCallbacks: 1
24 | m_ClothInterCollisionSettingsToggle: 0
25 | m_ContactPairsMode: 0
26 | m_BroadphaseType: 0
27 | m_WorldBounds:
28 | m_Center: {x: 0, y: 0, z: 0}
29 | m_Extent: {x: 250, y: 250, z: 250}
30 | m_WorldSubdivisions: 8
31 | m_FrictionType: 0
32 | m_EnableEnhancedDeterminism: 0
33 | m_EnableUnifiedHeightmaps: 1
34 | m_DefaultMaxAngluarSpeed: 7
35 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1045 &1
4 | EditorBuildSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Scenes: []
8 | m_configObjects: {}
9 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!159 &1
4 | EditorSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 11
7 | m_ExternalVersionControlSupport: Visible Meta Files
8 | m_SerializationMode: 2
9 | m_LineEndingsForNewScripts: 0
10 | m_DefaultBehaviorMode: 0
11 | m_PrefabRegularEnvironment: {fileID: 0}
12 | m_PrefabUIEnvironment: {fileID: 0}
13 | m_SpritePackerMode: 0
14 | m_SpritePackerPaddingPower: 1
15 | m_EtcTextureCompressorBehavior: 1
16 | m_EtcTextureFastCompressor: 1
17 | m_EtcTextureNormalCompressor: 2
18 | m_EtcTextureBestCompressor: 4
19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref
20 | m_ProjectGenerationRootNamespace:
21 | m_CollabEditorSettings:
22 | inProgressEnabled: 1
23 | m_EnableTextureStreamingInEditMode: 1
24 | m_EnableTextureStreamingInPlayMode: 1
25 | m_AsyncShaderCompilation: 1
26 | m_EnterPlayModeOptionsEnabled: 0
27 | m_EnterPlayModeOptions: 3
28 | m_ShowLightmapResolutionOverlay: 1
29 | m_UseLegacyProbeSampleCount: 0
30 | m_SerializeInlineMappingsOnOneLine: 1
31 |
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!30 &1
4 | GraphicsSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 13
7 | m_Deferred:
8 | m_Mode: 1
9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
10 | m_DeferredReflections:
11 | m_Mode: 1
12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
13 | m_ScreenSpaceShadows:
14 | m_Mode: 1
15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
16 | m_LegacyDeferred:
17 | m_Mode: 1
18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
19 | m_DepthNormals:
20 | m_Mode: 1
21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
22 | m_MotionVectors:
23 | m_Mode: 1
24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
25 | m_LightHalo:
26 | m_Mode: 1
27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
28 | m_LensFlare:
29 | m_Mode: 1
30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
31 | m_AlwaysIncludedShaders:
32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
38 | m_PreloadedShaders: []
39 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
40 | type: 0}
41 | m_CustomRenderPipeline: {fileID: 0}
42 | m_TransparencySortMode: 0
43 | m_TransparencySortAxis: {x: 0, y: 0, z: 1}
44 | m_DefaultRenderingPath: 1
45 | m_DefaultMobileRenderingPath: 1
46 | m_TierSettings: []
47 | m_LightmapStripping: 0
48 | m_FogStripping: 0
49 | m_InstancingStripping: 0
50 | m_LightmapKeepPlain: 1
51 | m_LightmapKeepDirCombined: 1
52 | m_LightmapKeepDynamicPlain: 1
53 | m_LightmapKeepDynamicDirCombined: 1
54 | m_LightmapKeepShadowMask: 1
55 | m_LightmapKeepSubtractive: 1
56 | m_FogKeepLinear: 1
57 | m_FogKeepExp: 1
58 | m_FogKeepExp2: 1
59 | m_AlbedoSwatchInfos: []
60 | m_LightsUseLinearIntensity: 0
61 | m_LightsUseColorTemperature: 0
62 | m_LogWhenShaderIsCompiled: 0
63 | m_AllowEnlightenSupportForUpgradedProject: 0
64 |
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!13 &1
4 | InputManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Axes:
8 | - serializedVersion: 3
9 | m_Name: Horizontal
10 | descriptiveName:
11 | descriptiveNegativeName:
12 | negativeButton: left
13 | positiveButton: right
14 | altNegativeButton: a
15 | altPositiveButton: d
16 | gravity: 3
17 | dead: 0.001
18 | sensitivity: 3
19 | snap: 1
20 | invert: 0
21 | type: 0
22 | axis: 0
23 | joyNum: 0
24 | - serializedVersion: 3
25 | m_Name: Vertical
26 | descriptiveName:
27 | descriptiveNegativeName:
28 | negativeButton: down
29 | positiveButton: up
30 | altNegativeButton: s
31 | altPositiveButton: w
32 | gravity: 3
33 | dead: 0.001
34 | sensitivity: 3
35 | snap: 1
36 | invert: 0
37 | type: 0
38 | axis: 0
39 | joyNum: 0
40 | - serializedVersion: 3
41 | m_Name: Fire1
42 | descriptiveName:
43 | descriptiveNegativeName:
44 | negativeButton:
45 | positiveButton: left ctrl
46 | altNegativeButton:
47 | altPositiveButton: mouse 0
48 | gravity: 1000
49 | dead: 0.001
50 | sensitivity: 1000
51 | snap: 0
52 | invert: 0
53 | type: 0
54 | axis: 0
55 | joyNum: 0
56 | - serializedVersion: 3
57 | m_Name: Fire2
58 | descriptiveName:
59 | descriptiveNegativeName:
60 | negativeButton:
61 | positiveButton: left alt
62 | altNegativeButton:
63 | altPositiveButton: mouse 1
64 | gravity: 1000
65 | dead: 0.001
66 | sensitivity: 1000
67 | snap: 0
68 | invert: 0
69 | type: 0
70 | axis: 0
71 | joyNum: 0
72 | - serializedVersion: 3
73 | m_Name: Fire3
74 | descriptiveName:
75 | descriptiveNegativeName:
76 | negativeButton:
77 | positiveButton: left shift
78 | altNegativeButton:
79 | altPositiveButton: mouse 2
80 | gravity: 1000
81 | dead: 0.001
82 | sensitivity: 1000
83 | snap: 0
84 | invert: 0
85 | type: 0
86 | axis: 0
87 | joyNum: 0
88 | - serializedVersion: 3
89 | m_Name: Jump
90 | descriptiveName:
91 | descriptiveNegativeName:
92 | negativeButton:
93 | positiveButton: space
94 | altNegativeButton:
95 | altPositiveButton:
96 | gravity: 1000
97 | dead: 0.001
98 | sensitivity: 1000
99 | snap: 0
100 | invert: 0
101 | type: 0
102 | axis: 0
103 | joyNum: 0
104 | - serializedVersion: 3
105 | m_Name: Mouse X
106 | descriptiveName:
107 | descriptiveNegativeName:
108 | negativeButton:
109 | positiveButton:
110 | altNegativeButton:
111 | altPositiveButton:
112 | gravity: 0
113 | dead: 0
114 | sensitivity: 0.1
115 | snap: 0
116 | invert: 0
117 | type: 1
118 | axis: 0
119 | joyNum: 0
120 | - serializedVersion: 3
121 | m_Name: Mouse Y
122 | descriptiveName:
123 | descriptiveNegativeName:
124 | negativeButton:
125 | positiveButton:
126 | altNegativeButton:
127 | altPositiveButton:
128 | gravity: 0
129 | dead: 0
130 | sensitivity: 0.1
131 | snap: 0
132 | invert: 0
133 | type: 1
134 | axis: 1
135 | joyNum: 0
136 | - serializedVersion: 3
137 | m_Name: Mouse ScrollWheel
138 | descriptiveName:
139 | descriptiveNegativeName:
140 | negativeButton:
141 | positiveButton:
142 | altNegativeButton:
143 | altPositiveButton:
144 | gravity: 0
145 | dead: 0
146 | sensitivity: 0.1
147 | snap: 0
148 | invert: 0
149 | type: 1
150 | axis: 2
151 | joyNum: 0
152 | - serializedVersion: 3
153 | m_Name: Horizontal
154 | descriptiveName:
155 | descriptiveNegativeName:
156 | negativeButton:
157 | positiveButton:
158 | altNegativeButton:
159 | altPositiveButton:
160 | gravity: 0
161 | dead: 0.19
162 | sensitivity: 1
163 | snap: 0
164 | invert: 0
165 | type: 2
166 | axis: 0
167 | joyNum: 0
168 | - serializedVersion: 3
169 | m_Name: Vertical
170 | descriptiveName:
171 | descriptiveNegativeName:
172 | negativeButton:
173 | positiveButton:
174 | altNegativeButton:
175 | altPositiveButton:
176 | gravity: 0
177 | dead: 0.19
178 | sensitivity: 1
179 | snap: 0
180 | invert: 1
181 | type: 2
182 | axis: 1
183 | joyNum: 0
184 | - serializedVersion: 3
185 | m_Name: Fire1
186 | descriptiveName:
187 | descriptiveNegativeName:
188 | negativeButton:
189 | positiveButton: joystick button 0
190 | altNegativeButton:
191 | altPositiveButton:
192 | gravity: 1000
193 | dead: 0.001
194 | sensitivity: 1000
195 | snap: 0
196 | invert: 0
197 | type: 0
198 | axis: 0
199 | joyNum: 0
200 | - serializedVersion: 3
201 | m_Name: Fire2
202 | descriptiveName:
203 | descriptiveNegativeName:
204 | negativeButton:
205 | positiveButton: joystick button 1
206 | altNegativeButton:
207 | altPositiveButton:
208 | gravity: 1000
209 | dead: 0.001
210 | sensitivity: 1000
211 | snap: 0
212 | invert: 0
213 | type: 0
214 | axis: 0
215 | joyNum: 0
216 | - serializedVersion: 3
217 | m_Name: Fire3
218 | descriptiveName:
219 | descriptiveNegativeName:
220 | negativeButton:
221 | positiveButton: joystick button 2
222 | altNegativeButton:
223 | altPositiveButton:
224 | gravity: 1000
225 | dead: 0.001
226 | sensitivity: 1000
227 | snap: 0
228 | invert: 0
229 | type: 0
230 | axis: 0
231 | joyNum: 0
232 | - serializedVersion: 3
233 | m_Name: Jump
234 | descriptiveName:
235 | descriptiveNegativeName:
236 | negativeButton:
237 | positiveButton: joystick button 3
238 | altNegativeButton:
239 | altPositiveButton:
240 | gravity: 1000
241 | dead: 0.001
242 | sensitivity: 1000
243 | snap: 0
244 | invert: 0
245 | type: 0
246 | axis: 0
247 | joyNum: 0
248 | - serializedVersion: 3
249 | m_Name: Submit
250 | descriptiveName:
251 | descriptiveNegativeName:
252 | negativeButton:
253 | positiveButton: return
254 | altNegativeButton:
255 | altPositiveButton: joystick button 0
256 | gravity: 1000
257 | dead: 0.001
258 | sensitivity: 1000
259 | snap: 0
260 | invert: 0
261 | type: 0
262 | axis: 0
263 | joyNum: 0
264 | - serializedVersion: 3
265 | m_Name: Submit
266 | descriptiveName:
267 | descriptiveNegativeName:
268 | negativeButton:
269 | positiveButton: enter
270 | altNegativeButton:
271 | altPositiveButton: space
272 | gravity: 1000
273 | dead: 0.001
274 | sensitivity: 1000
275 | snap: 0
276 | invert: 0
277 | type: 0
278 | axis: 0
279 | joyNum: 0
280 | - serializedVersion: 3
281 | m_Name: Cancel
282 | descriptiveName:
283 | descriptiveNegativeName:
284 | negativeButton:
285 | positiveButton: escape
286 | altNegativeButton:
287 | altPositiveButton: joystick button 1
288 | gravity: 1000
289 | dead: 0.001
290 | sensitivity: 1000
291 | snap: 0
292 | invert: 0
293 | type: 0
294 | axis: 0
295 | joyNum: 0
296 |
--------------------------------------------------------------------------------
/ProjectSettings/MemorySettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!387306366 &1
4 | MemorySettings:
5 | m_ObjectHideFlags: 0
6 | m_EditorMemorySettings:
7 | m_MainAllocatorBlockSize: -1
8 | m_ThreadAllocatorBlockSize: -1
9 | m_MainGfxBlockSize: -1
10 | m_ThreadGfxBlockSize: -1
11 | m_CacheBlockSize: -1
12 | m_TypetreeBlockSize: -1
13 | m_ProfilerBlockSize: -1
14 | m_ProfilerEditorBlockSize: -1
15 | m_BucketAllocatorGranularity: -1
16 | m_BucketAllocatorBucketsCount: -1
17 | m_BucketAllocatorBlockSize: -1
18 | m_BucketAllocatorBlockCount: -1
19 | m_ProfilerBucketAllocatorGranularity: -1
20 | m_ProfilerBucketAllocatorBucketsCount: -1
21 | m_ProfilerBucketAllocatorBlockSize: -1
22 | m_ProfilerBucketAllocatorBlockCount: -1
23 | m_TempAllocatorSizeMain: -1
24 | m_JobTempAllocatorBlockSize: -1
25 | m_BackgroundJobTempAllocatorBlockSize: -1
26 | m_JobTempAllocatorReducedBlockSize: -1
27 | m_TempAllocatorSizeGIBakingWorker: -1
28 | m_TempAllocatorSizeNavMeshWorker: -1
29 | m_TempAllocatorSizeAudioWorker: -1
30 | m_TempAllocatorSizeCloudWorker: -1
31 | m_TempAllocatorSizeGfx: -1
32 | m_TempAllocatorSizeJobWorker: -1
33 | m_TempAllocatorSizeBackgroundWorker: -1
34 | m_TempAllocatorSizePreloadManager: -1
35 | m_PlatformMemorySettings: {}
36 |
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!126 &1
4 | NavMeshProjectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | areas:
8 | - name: Walkable
9 | cost: 1
10 | - name: Not Walkable
11 | cost: 1
12 | - name: Jump
13 | cost: 2
14 | - name:
15 | cost: 1
16 | - name:
17 | cost: 1
18 | - name:
19 | cost: 1
20 | - name:
21 | cost: 1
22 | - name:
23 | cost: 1
24 | - name:
25 | cost: 1
26 | - name:
27 | cost: 1
28 | - name:
29 | cost: 1
30 | - name:
31 | cost: 1
32 | - name:
33 | cost: 1
34 | - name:
35 | cost: 1
36 | - name:
37 | cost: 1
38 | - name:
39 | cost: 1
40 | - name:
41 | cost: 1
42 | - name:
43 | cost: 1
44 | - name:
45 | cost: 1
46 | - name:
47 | cost: 1
48 | - name:
49 | cost: 1
50 | - name:
51 | cost: 1
52 | - name:
53 | cost: 1
54 | - name:
55 | cost: 1
56 | - name:
57 | cost: 1
58 | - name:
59 | cost: 1
60 | - name:
61 | cost: 1
62 | - name:
63 | cost: 1
64 | - name:
65 | cost: 1
66 | - name:
67 | cost: 1
68 | - name:
69 | cost: 1
70 | - name:
71 | cost: 1
72 | m_LastAgentTypeID: -887442657
73 | m_Settings:
74 | - serializedVersion: 2
75 | agentTypeID: 0
76 | agentRadius: 0.5
77 | agentHeight: 2
78 | agentSlope: 45
79 | agentClimb: 0.75
80 | ledgeDropHeight: 0
81 | maxJumpAcrossDistance: 0
82 | minRegionArea: 2
83 | manualCellSize: 0
84 | cellSize: 0.16666667
85 | manualTileSize: 0
86 | tileSize: 256
87 | accuratePlacement: 0
88 | debug:
89 | m_Flags: 0
90 | m_SettingNames:
91 | - Humanoid
92 |
--------------------------------------------------------------------------------
/ProjectSettings/PackageManagerSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | m_EnablePreReleasePackages: 1
16 | m_EnablePackageDependencies: 1
17 | m_AdvancedSettingsExpanded: 1
18 | m_ScopedRegistriesSettingsExpanded: 1
19 | m_SeeAllPackageVersions: 0
20 | oneTimeWarningShown: 1
21 | m_Registries:
22 | - m_Id: main
23 | m_Name:
24 | m_Url: https://packages.unity.com
25 | m_Scopes: []
26 | m_IsDefault: 1
27 | m_Capabilities: 7
28 | m_UserSelectedRegistryName:
29 | m_UserAddingNewScopedRegistry: 0
30 | m_RegistryInfoDraft:
31 | m_Modified: 0
32 | m_ErrorMessage:
33 | m_UserModificationsInstanceId: -844
34 | m_OriginalInstanceId: -846
35 | m_LoadAssets: 0
36 |
--------------------------------------------------------------------------------
/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "m_Name": "Settings",
3 | "m_Path": "ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json",
4 | "m_Dictionary": {
5 | "m_DictionaryValues": []
6 | }
7 | }
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!19 &1
4 | Physics2DSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 4
7 | m_Gravity: {x: 0, y: -9.81}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_VelocityIterations: 8
10 | m_PositionIterations: 3
11 | m_VelocityThreshold: 1
12 | m_MaxLinearCorrection: 0.2
13 | m_MaxAngularCorrection: 8
14 | m_MaxTranslationSpeed: 100
15 | m_MaxRotationSpeed: 360
16 | m_BaumgarteScale: 0.2
17 | m_BaumgarteTimeOfImpactScale: 0.75
18 | m_TimeToSleep: 0.5
19 | m_LinearSleepTolerance: 0.01
20 | m_AngularSleepTolerance: 2
21 | m_DefaultContactOffset: 0.01
22 | m_JobOptions:
23 | serializedVersion: 2
24 | useMultithreading: 0
25 | useConsistencySorting: 0
26 | m_InterpolationPosesPerJob: 100
27 | m_NewContactsPerJob: 30
28 | m_CollideContactsPerJob: 100
29 | m_ClearFlagsPerJob: 200
30 | m_ClearBodyForcesPerJob: 200
31 | m_SyncDiscreteFixturesPerJob: 50
32 | m_SyncContinuousFixturesPerJob: 50
33 | m_FindNearestContactsPerJob: 100
34 | m_UpdateTriggerContactsPerJob: 100
35 | m_IslandSolverCostThreshold: 100
36 | m_IslandSolverBodyCostScale: 1
37 | m_IslandSolverContactCostScale: 10
38 | m_IslandSolverJointCostScale: 10
39 | m_IslandSolverBodiesPerJob: 50
40 | m_IslandSolverContactsPerJob: 50
41 | m_AutoSimulation: 1
42 | m_QueriesHitTriggers: 1
43 | m_QueriesStartInColliders: 1
44 | m_CallbacksOnDisable: 1
45 | m_ReuseCollisionCallbacks: 1
46 | m_AutoSyncTransforms: 0
47 | m_AlwaysShowColliders: 0
48 | m_ShowColliderSleep: 1
49 | m_ShowColliderContacts: 0
50 | m_ShowColliderAABB: 0
51 | m_ContactArrowScale: 0.2
52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
57 |
--------------------------------------------------------------------------------
/ProjectSettings/PresetManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1386491679 &1
4 | PresetManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_DefaultPresets: {}
8 |
--------------------------------------------------------------------------------
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 2021.3.0f1
2 | m_EditorVersionWithRevision: 2021.3.0f1 (6eacc8284459)
3 |
--------------------------------------------------------------------------------
/ProjectSettings/QualitySettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!47 &1
4 | QualitySettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 5
7 | m_CurrentQuality: 5
8 | m_QualitySettings:
9 | - serializedVersion: 2
10 | name: Very Low
11 | pixelLightCount: 0
12 | shadows: 0
13 | shadowResolution: 0
14 | shadowProjection: 1
15 | shadowCascades: 1
16 | shadowDistance: 15
17 | shadowNearPlaneOffset: 3
18 | shadowCascade2Split: 0.33333334
19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
20 | shadowmaskMode: 0
21 | blendWeights: 1
22 | textureQuality: 1
23 | anisotropicTextures: 0
24 | antiAliasing: 0
25 | softParticles: 0
26 | softVegetation: 0
27 | realtimeReflectionProbes: 0
28 | billboardsFaceCameraPosition: 0
29 | vSyncCount: 0
30 | lodBias: 0.3
31 | maximumLODLevel: 0
32 | streamingMipmapsActive: 0
33 | streamingMipmapsAddAllCameras: 1
34 | streamingMipmapsMemoryBudget: 512
35 | streamingMipmapsRenderersPerFrame: 512
36 | streamingMipmapsMaxLevelReduction: 2
37 | streamingMipmapsMaxFileIORequests: 1024
38 | particleRaycastBudget: 4
39 | asyncUploadTimeSlice: 2
40 | asyncUploadBufferSize: 16
41 | asyncUploadPersistentBuffer: 1
42 | resolutionScalingFixedDPIFactor: 1
43 | excludedTargetPlatforms: []
44 | - serializedVersion: 2
45 | name: Low
46 | pixelLightCount: 0
47 | shadows: 0
48 | shadowResolution: 0
49 | shadowProjection: 1
50 | shadowCascades: 1
51 | shadowDistance: 20
52 | shadowNearPlaneOffset: 3
53 | shadowCascade2Split: 0.33333334
54 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
55 | shadowmaskMode: 0
56 | blendWeights: 2
57 | textureQuality: 0
58 | anisotropicTextures: 0
59 | antiAliasing: 0
60 | softParticles: 0
61 | softVegetation: 0
62 | realtimeReflectionProbes: 0
63 | billboardsFaceCameraPosition: 0
64 | vSyncCount: 0
65 | lodBias: 0.4
66 | maximumLODLevel: 0
67 | streamingMipmapsActive: 0
68 | streamingMipmapsAddAllCameras: 1
69 | streamingMipmapsMemoryBudget: 512
70 | streamingMipmapsRenderersPerFrame: 512
71 | streamingMipmapsMaxLevelReduction: 2
72 | streamingMipmapsMaxFileIORequests: 1024
73 | particleRaycastBudget: 16
74 | asyncUploadTimeSlice: 2
75 | asyncUploadBufferSize: 16
76 | asyncUploadPersistentBuffer: 1
77 | resolutionScalingFixedDPIFactor: 1
78 | excludedTargetPlatforms: []
79 | - serializedVersion: 2
80 | name: Medium
81 | pixelLightCount: 1
82 | shadows: 1
83 | shadowResolution: 0
84 | shadowProjection: 1
85 | shadowCascades: 1
86 | shadowDistance: 20
87 | shadowNearPlaneOffset: 3
88 | shadowCascade2Split: 0.33333334
89 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
90 | shadowmaskMode: 0
91 | blendWeights: 2
92 | textureQuality: 0
93 | anisotropicTextures: 1
94 | antiAliasing: 0
95 | softParticles: 0
96 | softVegetation: 0
97 | realtimeReflectionProbes: 0
98 | billboardsFaceCameraPosition: 0
99 | vSyncCount: 1
100 | lodBias: 0.7
101 | maximumLODLevel: 0
102 | streamingMipmapsActive: 0
103 | streamingMipmapsAddAllCameras: 1
104 | streamingMipmapsMemoryBudget: 512
105 | streamingMipmapsRenderersPerFrame: 512
106 | streamingMipmapsMaxLevelReduction: 2
107 | streamingMipmapsMaxFileIORequests: 1024
108 | particleRaycastBudget: 64
109 | asyncUploadTimeSlice: 2
110 | asyncUploadBufferSize: 16
111 | asyncUploadPersistentBuffer: 1
112 | resolutionScalingFixedDPIFactor: 1
113 | excludedTargetPlatforms: []
114 | - serializedVersion: 2
115 | name: High
116 | pixelLightCount: 2
117 | shadows: 2
118 | shadowResolution: 1
119 | shadowProjection: 1
120 | shadowCascades: 2
121 | shadowDistance: 40
122 | shadowNearPlaneOffset: 3
123 | shadowCascade2Split: 0.33333334
124 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
125 | shadowmaskMode: 1
126 | blendWeights: 2
127 | textureQuality: 0
128 | anisotropicTextures: 1
129 | antiAliasing: 0
130 | softParticles: 0
131 | softVegetation: 1
132 | realtimeReflectionProbes: 1
133 | billboardsFaceCameraPosition: 1
134 | vSyncCount: 1
135 | lodBias: 1
136 | maximumLODLevel: 0
137 | streamingMipmapsActive: 0
138 | streamingMipmapsAddAllCameras: 1
139 | streamingMipmapsMemoryBudget: 512
140 | streamingMipmapsRenderersPerFrame: 512
141 | streamingMipmapsMaxLevelReduction: 2
142 | streamingMipmapsMaxFileIORequests: 1024
143 | particleRaycastBudget: 256
144 | asyncUploadTimeSlice: 2
145 | asyncUploadBufferSize: 16
146 | asyncUploadPersistentBuffer: 1
147 | resolutionScalingFixedDPIFactor: 1
148 | excludedTargetPlatforms: []
149 | - serializedVersion: 2
150 | name: Very High
151 | pixelLightCount: 3
152 | shadows: 2
153 | shadowResolution: 2
154 | shadowProjection: 1
155 | shadowCascades: 2
156 | shadowDistance: 70
157 | shadowNearPlaneOffset: 3
158 | shadowCascade2Split: 0.33333334
159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
160 | shadowmaskMode: 1
161 | blendWeights: 4
162 | textureQuality: 0
163 | anisotropicTextures: 2
164 | antiAliasing: 2
165 | softParticles: 1
166 | softVegetation: 1
167 | realtimeReflectionProbes: 1
168 | billboardsFaceCameraPosition: 1
169 | vSyncCount: 1
170 | lodBias: 1.5
171 | maximumLODLevel: 0
172 | streamingMipmapsActive: 0
173 | streamingMipmapsAddAllCameras: 1
174 | streamingMipmapsMemoryBudget: 512
175 | streamingMipmapsRenderersPerFrame: 512
176 | streamingMipmapsMaxLevelReduction: 2
177 | streamingMipmapsMaxFileIORequests: 1024
178 | particleRaycastBudget: 1024
179 | asyncUploadTimeSlice: 2
180 | asyncUploadBufferSize: 16
181 | asyncUploadPersistentBuffer: 1
182 | resolutionScalingFixedDPIFactor: 1
183 | excludedTargetPlatforms: []
184 | - serializedVersion: 2
185 | name: Ultra
186 | pixelLightCount: 4
187 | shadows: 2
188 | shadowResolution: 2
189 | shadowProjection: 1
190 | shadowCascades: 4
191 | shadowDistance: 150
192 | shadowNearPlaneOffset: 3
193 | shadowCascade2Split: 0.33333334
194 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
195 | shadowmaskMode: 1
196 | blendWeights: 4
197 | textureQuality: 0
198 | anisotropicTextures: 2
199 | antiAliasing: 2
200 | softParticles: 1
201 | softVegetation: 1
202 | realtimeReflectionProbes: 1
203 | billboardsFaceCameraPosition: 1
204 | vSyncCount: 1
205 | lodBias: 2
206 | maximumLODLevel: 0
207 | streamingMipmapsActive: 0
208 | streamingMipmapsAddAllCameras: 1
209 | streamingMipmapsMemoryBudget: 512
210 | streamingMipmapsRenderersPerFrame: 512
211 | streamingMipmapsMaxLevelReduction: 2
212 | streamingMipmapsMaxFileIORequests: 1024
213 | particleRaycastBudget: 4096
214 | asyncUploadTimeSlice: 2
215 | asyncUploadBufferSize: 16
216 | asyncUploadPersistentBuffer: 1
217 | resolutionScalingFixedDPIFactor: 1
218 | excludedTargetPlatforms: []
219 | m_PerPlatformDefaultQuality:
220 | Android: 2
221 | Lumin: 5
222 | Nintendo 3DS: 5
223 | Nintendo Switch: 5
224 | PS4: 5
225 | PSP2: 2
226 | Stadia: 5
227 | Standalone: 5
228 | WebGL: 3
229 | Windows Store Apps: 5
230 | XboxOne: 5
231 | iPhone: 2
232 | tvOS: 2
233 |
--------------------------------------------------------------------------------
/ProjectSettings/RiderScriptEditorPersistedState.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 0}
13 | m_Name:
14 | m_EditorClassIdentifier: Unity.Rider.Editor:Packages.Rider.Editor:RiderScriptEditorPersistedState
15 | lastWriteTicks: -8585237163592527186
16 |
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!78 &1
4 | TagManager:
5 | serializedVersion: 2
6 | tags: []
7 | layers:
8 | - Default
9 | - TransparentFX
10 | - Ignore Raycast
11 | -
12 | - Water
13 | - UI
14 | -
15 | -
16 | -
17 | -
18 | -
19 | -
20 | -
21 | -
22 | -
23 | -
24 | -
25 | -
26 | -
27 | -
28 | -
29 | -
30 | -
31 | -
32 | -
33 | -
34 | -
35 | -
36 | -
37 | -
38 | -
39 | -
40 | m_SortingLayers:
41 | - name: Default
42 | uniqueID: 0
43 | locked: 0
44 |
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!5 &1
4 | TimeManager:
5 | m_ObjectHideFlags: 0
6 | Fixed Timestep: 0.02
7 | Maximum Allowed Timestep: 0.33333334
8 | m_TimeScale: 1
9 | Maximum Particle Timestep: 0.03
10 |
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!310 &1
4 | UnityConnectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 1
7 | m_Enabled: 0
8 | m_TestMode: 0
9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com
12 | m_DashboardUrl: https://dashboard.unity3d.com
13 | m_TestInitMode: 0
14 | CrashReportingSettings:
15 | m_EventUrl: https://perf-events.cloud.unity3d.com
16 | m_Enabled: 0
17 | m_LogBufferSize: 10
18 | m_CaptureEditorExceptions: 1
19 | UnityPurchasingSettings:
20 | m_Enabled: 0
21 | m_TestMode: 0
22 | UnityAnalyticsSettings:
23 | m_Enabled: 0
24 | m_TestMode: 0
25 | m_InitializeOnStartup: 1
26 | UnityAdsSettings:
27 | m_Enabled: 0
28 | m_InitializeOnStartup: 1
29 | m_TestMode: 0
30 | m_IosGameId:
31 | m_AndroidGameId:
32 | m_GameIds: {}
33 | m_GameId:
34 | PerformanceReportingSettings:
35 | m_Enabled: 0
36 |
--------------------------------------------------------------------------------
/ProjectSettings/VFXManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!937362698 &1
4 | VFXManager:
5 | m_ObjectHideFlags: 0
6 | m_IndirectShader: {fileID: 0}
7 | m_CopyBufferShader: {fileID: 0}
8 | m_SortShader: {fileID: 0}
9 | m_StripUpdateShader: {fileID: 0}
10 | m_RenderPipeSettingsPath:
11 | m_FixedTimeStep: 0.016666668
12 | m_MaxDeltaTime: 0.05
13 |
--------------------------------------------------------------------------------
/ProjectSettings/VersionControlSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!890905787 &1
4 | VersionControlSettings:
5 | m_ObjectHideFlags: 0
6 | m_Mode: Visible Meta Files
7 | m_CollabEditorSettings:
8 | inProgressEnabled: 1
9 |
--------------------------------------------------------------------------------
/ProjectSettings/XRSettings.asset:
--------------------------------------------------------------------------------
1 | {
2 | "m_SettingKeys": [
3 | "VR Device Disabled",
4 | "VR Device User Alert"
5 | ],
6 | "m_SettingValues": [
7 | "False",
8 | "False"
9 | ]
10 | }
--------------------------------------------------------------------------------
/ProjectSettings/boot.config:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mochi-neko/ChatGPT-API-unity/cf95fea59021b6f4dc67b5381f4a96dd5b7d70d2/ProjectSettings/boot.config
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChatGPT-API-unity
2 |
3 | A client library of [ChatGPT chat completion API](https://platform.openai.com/docs/api-reference/chat/create) for Unity.
4 |
5 | See also official [document](https://platform.openai.com/docs/guides/chat) and [API reference](https://platform.openai.com/docs/api-reference/chat).
6 |
7 | ## How to import by Unity Package Manager
8 |
9 | Add following dependencies to your `/Packages/mainfest.json`.
10 |
11 | ```json
12 | {
13 | "dependencies": {
14 | "com.mochineko.chatgpt-api": "https://github.com/mochi-neko/ChatGPT-API-unity.git?path=/Assets/Mochineko/ChatGPT_API#0.7.3",
15 | ...
16 | }
17 | }
18 | ```
19 |
20 | ## How to use chat completion by ChatGPT API
21 |
22 | 1. Generate API key on [OpenAI](https://platform.openai.com/account/api-keys). (Take care your API key, this is a secret information then you should not open.)
23 | 2. You can specify chat model. (Available models are defined by `Model`.)
24 | 3. Create an instance of `ChatCompletionAPIConnection` with API key and chat model. (This instance memorizes old messages in session.)
25 | 4. You can set system message (prompt) to instruct assistant with your situation by constructor of `ChatCompletionAPIConnection`.
26 | 5. Input user message and call `ChatCompletionAPIConnection.CompleteChatAsync()`.
27 | 6. Response message is in `ChatCompletionResponseBody.ResultMessage` (= `ChatCompletionResponseBody.Choices[0].Message.Content`).
28 |
29 | An essential sample code with [UniTask](https://github.com/Cysharp/UniTask) is as follows:
30 |
31 | ```csharp
32 | #nullable enable
33 | using System;
34 | using System.Threading;
35 | using Cysharp.Threading.Tasks;
36 | using Mochineko.ChatGPT_API.Memories;
37 | using UnityEngine;
38 |
39 | namespace Mochineko.ChatGPT_API.Samples
40 | {
41 | ///
42 | /// A sample component to complete chat by ChatGPT API on Unity.
43 | ///
44 | public sealed class ChatCompletionSample : MonoBehaviour
45 | {
46 | ///
47 | /// API key generated by OpenAPI.
48 | ///
49 | [SerializeField] private string apiKey = string.Empty;
50 |
51 | ///
52 | /// System message to instruct assistant.
53 | ///
54 | [SerializeField, TextArea] private string systemMessage = string.Empty;
55 |
56 | ///
57 | /// Message sent to ChatGPT API.
58 | ///
59 | [SerializeField, TextArea] private string message = string.Empty;
60 |
61 | ///
62 | /// Max number of chat memory of queue.
63 | ///
64 | [SerializeField] private int maxMemoryCount = 20;
65 |
66 | private ChatCompletionAPIConnection? connection;
67 | private IChatMemory? memory;
68 |
69 | private void Start()
70 | {
71 | // API Key must be set.
72 | if (string.IsNullOrEmpty(apiKey))
73 | {
74 | Debug.LogError("OpenAI API key must be set.");
75 | return;
76 | }
77 |
78 | memory = new FiniteQueueChatMemory(maxMemoryCount);
79 |
80 | // Create instance of ChatGPTConnection with specifying chat model.
81 | connection = new ChatCompletionAPIConnection(
82 | apiKey,
83 | memory,
84 | systemMessage);
85 | }
86 |
87 | [ContextMenu(nameof(SendChat))]
88 | public void SendChat()
89 | {
90 | SendChatAsync(this.GetCancellationTokenOnDestroy()).Forget();
91 | }
92 |
93 | [ContextMenu(nameof(ClearChatMemory))]
94 | public void ClearChatMemory()
95 | {
96 | memory?.ClearAllMessages();
97 | }
98 |
99 | private async UniTask SendChatAsync(CancellationToken cancellationToken)
100 | {
101 | // Validations
102 | if (connection == null)
103 | {
104 | Debug.LogError($"[ChatGPT_API.Samples] Connection is null.");
105 | return;
106 | }
107 |
108 | if (string.IsNullOrEmpty(message))
109 | {
110 | Debug.LogError($"[ChatGPT_API.Samples] Chat content is empty.");
111 | return;
112 | }
113 |
114 | ChatCompletionResponseBody response;
115 | try
116 | {
117 | await UniTask.SwitchToThreadPool();
118 |
119 | // Create message by ChatGPT chat completion API.
120 | response = await connection.CompleteChatAsync(
121 | message,
122 | cancellationToken);
123 | }
124 | catch (Exception e)
125 | {
126 | // Exceptions should be caught.
127 | Debug.LogException(e);
128 | return;
129 | }
130 |
131 | await UniTask.SwitchToMainThread(cancellationToken);
132 |
133 | // Log chat completion result.
134 | Debug.Log($"[ChatGPT_API.Samples] Result:\n{response.ResultMessage}");
135 | }
136 | }
137 | }
138 | ```
139 |
140 | See also [Sample](./Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionSample.cs).
141 |
142 | ## How to use chat completion by ChatGPT API more resilient
143 |
144 | See `RelentChatCompletionAPIConnection` and `RelentChatCompletionSample`
145 | using [Relent](https://github.com/mochi-neko/Relent).
146 |
147 | You can use API with explicit error handling, retry, timeout, bulkhead, and so on.
148 |
149 | ```json
150 | {
151 | "dependencies": {
152 | "com.mochineko.chatgpt-api.relent": "https://github.com/mochi-neko/ChatGPT-API-unity.git?path=/Assets/Mochineko/ChatGPT_API.Relent#0.7.3",
153 | "com.mochineko.chatgpt-api": "https://github.com/mochi-neko/ChatGPT-API-unity.git?path=/Assets/Mochineko/ChatGPT_API#0.7.3",
154 | "com.mochineko.relent": "https://github.com/mochi-neko/Relent.git?path=/Assets/Mochineko/Relent#0.2.0",
155 | "com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
156 | ...
157 | }
158 | }
159 | ```
160 |
161 | ## How to calculate token length of text in local
162 |
163 | You can calculate token length of text
164 | by `TiktokenSharp.Tiktoken.Encode(string)` as follows:
165 |
166 | ```csharp
167 | using TiktokenSharp;
168 |
169 | private int CalculateTokenLength()
170 | {
171 | string text = "A text that you want to calculate token length.";
172 |
173 | // Specify model name.
174 | Tiktoken tiktoken = TikToken.EncodingForModel("gpt-3.5-turbo");
175 |
176 | // Encoding is tokenizing.
177 | int[] tokens = tikToken.Encode(text);
178 |
179 | return tokens.Length;
180 | }
181 | ```
182 |
183 | If you want to calculate on Unity editor,
184 | please use `ItemuMenu > Mochineko > TiktokenEditor` window.
185 |
186 | ## How to customize chat memories
187 |
188 | You can use customized memories of chat by implementing `IChatMemory` interface.
189 |
190 | Presets are available:
191 |
192 | - `FiniteQueueChatMemory`
193 | - A queue that has max number of messages.
194 | - `FiniteQueueWithFixedPromptsChatMemory`
195 | - A queue that has max number of user/assistant messages and free number of prompts (system messages).
196 | - `FiniteTokenLengthQueueChatMemory`
197 | - A queue that has max number of token lenght of all messages.
198 | - `FiniteTokenLengthQueueWithFixedPromptsChatMemory`
199 | - A queue that has max number of token lenght of user/assistant messages and free number of prompts (system messages).
200 |
201 | ## How to stream response
202 |
203 | See [streaming sample](./Assets/Mochineko/ChatGPT_API.Samples/ChatCompletionAsStreamSample.cs).
204 |
205 | You can await foreach as follows:
206 |
207 | ```csharp
208 | var builder = new StringBuilder();
209 | // Receive enumerable from ChatGPT chat completion API.
210 | var enumerable = await connection.CompleteChatAsStreamAsync(
211 | message,
212 | cancellationToken);
213 |
214 | await foreach (var chunk in enumerable.WithCancellation(cancellationToken))
215 | {
216 | // First chunk has only "role" element.
217 | if (chunk.Choices[0].Delta.Content is null)
218 | {
219 | Debug.Log($"[ChatGPT_API.Samples] Role:{chunk.Choices[0].Delta.Role}.");
220 | continue;
221 | }
222 |
223 | var delta = chunk.Choices[0].Delta.Content;
224 | builder.Append(delta);
225 | Debug.Log($"[ChatGPT_API.Samples] Delta:{delta}, Current:{builder}");
226 | }
227 |
228 | // Log chat completion result.
229 | Debug.Log($"[ChatGPT_API.Samples] Completed: \n{builder}");
230 | ```
231 | .
232 |
233 | ## How to use function calling
234 |
235 | 1. Define function with JSON schema.
236 | 2. Specify function by request parameters.
237 | 3. Call chat completion API.
238 | 4. Use `result.Choices[0].Message.FunctionCall`
239 |
240 | See `FunctionCalling()` in [test code](./Assets/Mochineko/ChatGPT_API.Tests/ChatCompletionAPIConnectionTest.cs).
241 |
242 | ## Changelog
243 |
244 | See [CHANGELOG](./CHANGELOG.md).
245 |
246 | ## 3rd Party Notices
247 |
248 | See [NOTICE](./NOTICE.md).
249 |
250 | ## License
251 |
252 | Licensed under the [MIT](./LICENSE) license.
253 |
--------------------------------------------------------------------------------