diff --git a/Assets/GameMain/Scripts/CustomComponent/AIChatComponent.cs b/Assets/GameMain/Scripts/CustomComponent/AIChatComponent.cs index 7c98fb6..7f9c51d 100644 --- a/Assets/GameMain/Scripts/CustomComponent/AIChatComponent.cs +++ b/Assets/GameMain/Scripts/CustomComponent/AIChatComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -15,13 +16,15 @@ namespace CustomComponent [DisallowMultipleComponent] public class AIChatComponent : GameFrameworkComponent { - [Header("OpenAI Config")] [SerializeField] - private string _apiBaseUrl = "https://api.openai.com"; + [Header("OpenAI Config")] + [SerializeField] private string _configFileName = "openai_config.json"; - [SerializeField] private string _apiKey = string.Empty; - [SerializeField] private string _chatCompletionsPath = "/v1/chat/completions"; - [SerializeField] private string _heartbeatPath = "/v1/models"; - [SerializeField] private string _model = "gpt-4o-mini"; + [SerializeField] private string _chatCompletionsPath = "/chat/completions"; + [SerializeField] private string _heartbeatPath = "/models"; + + private string _apiBaseUrl; + private string _apiKey; + private string _model; [Header("Request Options")] [SerializeField] private bool _autoInitializeOnEnable = true; @@ -85,6 +88,12 @@ namespace CustomComponent public void Initialize() { + if (!LoadConfigFromStreamingAssets()) + { + _isInitialized = false; + return; + } + _isInitialized = true; StartHeartbeat(); } @@ -465,6 +474,66 @@ namespace CustomComponent return Utility.Text.Format("{0}/{1}", _apiBaseUrl.TrimEnd('/'), pathOrUrl.TrimStart('/')); } + private bool LoadConfigFromStreamingAssets() + { + if (string.IsNullOrWhiteSpace(_configFileName)) + { + Log.Error("AIChat config filename is empty."); + return false; + } + + string configPath = Path.Combine(Application.streamingAssetsPath, _configFileName); + if (!File.Exists(configPath)) + { + Log.Error("AIChat config file not found. path='{0}'", configPath); + return false; + } + + string json; + try + { + json = File.ReadAllText(configPath, Encoding.UTF8); + } + catch (Exception exception) + { + Log.Error("AIChat config read failed. path='{0}', error='{1}'", configPath, exception.Message); + return false; + } + + OpenAIConfig config; + try + { + config = Utility.Json.ToObject(json); + } + catch (Exception exception) + { + Log.Error("AIChat config parse failed. error='{0}'", exception.Message); + return false; + } + + if (config == null || + string.IsNullOrWhiteSpace(config.apiBaseUrl) || + string.IsNullOrWhiteSpace(config.apiKey) || + string.IsNullOrWhiteSpace(config.model)) + { + Log.Error("AIChat config is invalid. baseUrl/key/model must be provided."); + return false; + } + + _apiBaseUrl = config.apiBaseUrl; + _apiKey = config.apiKey; + _model = config.model; + return true; + } + + [Serializable] + private sealed class OpenAIConfig + { + public string apiBaseUrl; + public string apiKey; + public string model; + } + private static IEnumerator WaitTask(Task task) { while (!task.IsCompleted) diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index 4e4eb3e..64a9955 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -253,134 +253,6 @@ Transform: type: 3} m_PrefabInstance: {fileID: 343730742} m_PrefabAsset: {fileID: 0} ---- !u!1 &265274946 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 265274950} - - component: {fileID: 265274949} - - component: {fileID: 265274947} - m_Layer: 0 - m_Name: Camera - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &265274947 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 265274946} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: 0 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!20 &265274949 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 265274946} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &265274950 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 265274946} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &343730742 PrefabInstance: m_ObjectHideFlags: 0 @@ -1116,15 +988,15 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 721362e43780c4043ae6e7ce92463755, type: 3} m_Name: m_EditorClassIdentifier: - _apiBaseUrl: https://dashscope.aliyuncs.com/compatible-mode/v1 - _apiKey: sk-cba96782070546aeade8de5f555a9c40 + _configFileName: openai_config.json _chatCompletionsPath: /chat/completions _heartbeatPath: /models - _model: qwen-plus _autoInitializeOnEnable: 1 _chatTimeoutSeconds: 60 _temperature: 0.7 - _systemPrompt: "\u4F60\u662F\u5317\u5B8B\u8457\u540D\u5EFA\u7B51\u5B66\u5BB6\u674E\u8BEB\uFF0C\u73B0\u5728\u4F60\u9700\u8981\u6839\u636E\u63D0\u95EE\u7684\u5185\u5BB9\u548C\u56DE\u7B54\u7684\u8981\u6C42\u5BF9\u95EE\u9898\u505A\u51FA\u56DE\u590D\uFF0C\u56DE\u7B54\u95EE\u9898\u5C31\u884C\uFF0C\u4E0D\u8981\u7528\u751F\u50FB\u5B57\uFF0C\u5207\u52FF\u53D1\u6563\u3002" + _systemPrompt: "\u4F60\u662F\u5317\u5B8B\u8457\u540D\u5EFA\u7B51\u5B66\u5BB6\u674E\u8BEB\uFF0C\u73B0\u5728\u4F60\u9700\u8981\u6839\u636E\u63D0\u95EE\u7684\u5185\u5BB9\u548C\u56DE\u7B54\u7684\u8981\u6C42\u5BF9\u95EE\u9898\u505A\u51FA\u56DE\u590D\uFF1A\n1. + \u53EA\u56DE\u7B54\u8EAB\u4EFD\u4ECB\u7ECD\u4EE5\u53CA\u5EFA\u7B51\u76F8\u5173\u7684\u95EE\u9898\uFF0C\u5176\u4ED6\u95EE\u9898\u4EE5\u4E0D\u61C2\u4E3A\u7531\u59D4\u5A49\u7684\u62D2\u7EDD\u3002\n2. + \u4E0D\u8981\u7528\u751F\u50FB\u5B57\u3002\n3. \u5207\u52FF\u53D1\u6563\u3002" _heartbeatIntervalSeconds: 5 _heartbeatTimeoutSeconds: 8 --- !u!1 &1852670052 @@ -1209,5 +1081,4 @@ SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 1852670053} - - {fileID: 265274950} - {fileID: 120093242} diff --git a/数据表/UIForm.xlsx b/数据表/UIForm.xlsx index 8dbbabd..8b2733b 100644 Binary files a/数据表/UIForm.xlsx and b/数据表/UIForm.xlsx differ