Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
Ftt_Common
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Ftt_Common
Commits
0fff0a7b
Commit
0fff0a7b
authored
Aug 27, 2026
by
段廷瑞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pref: 智能体模型选择与交互优化
parent
a3a8c203
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
272 additions
and
24 deletions
+272
-24
OpenAiCompatibleClient.cs
Tools/MyAgent/Agent/OpenAiCompatibleClient.cs
+68
-4
AgentConfig.cs
Tools/MyAgent/Config/AgentConfig.cs
+3
-0
AgentSettingsForm.Designer.cs
Tools/MyAgent/Forms/AgentSettingsForm.Designer.cs
+14
-1
AgentSettingsForm.cs
Tools/MyAgent/Forms/AgentSettingsForm.cs
+186
-19
wMyAgent.cs
Tools/MyAgent/wMyAgent.cs
+1
-0
No files found.
Tools/MyAgent/Agent/OpenAiCompatibleClient.cs
View file @
0fff0a7b
...
...
@@ -48,6 +48,61 @@ namespace Tools.MyAgent.Agent
public
double
Temperature
{
get
;
set
;
}
=
0.3
;
public
int
MaxTokens
{
get
;
set
;
}
=
8192
;
/// <summary>获取当前兼容接口公开的模型列表(不影响聊天请求)</summary>
public
async
Task
<(
bool
Ok
,
string
Message
,
List
<
string
>
Models
)>
FetchModelsAsync
(
CancellationToken
ct
)
{
try
{
using
(
var
cts
=
CancellationTokenSource
.
CreateLinkedTokenSource
(
ct
))
{
cts
.
CancelAfter
(
15000
);
string
baseUrl
=
BaseUrl
?.
Trim
().
TrimEnd
(
'/'
);
if
(
string
.
IsNullOrEmpty
(
baseUrl
))
return
(
false
,
"BaseUrl 不能为空"
,
null
);
string
modelsUrl
=
baseUrl
.
EndsWith
(
"/v1"
,
StringComparison
.
OrdinalIgnoreCase
)
?
baseUrl
+
"/models"
:
baseUrl
+
"/v1/models"
;
using
(
var
req
=
new
HttpRequestMessage
(
HttpMethod
.
Get
,
modelsUrl
))
{
if
(!
string
.
IsNullOrWhiteSpace
(
ApiKey
))
req
.
Headers
.
TryAddWithoutValidation
(
"Authorization"
,
"Bearer "
+
ApiKey
);
using
(
var
resp
=
await
Http
.
SendAsync
(
req
,
cts
.
Token
).
ConfigureAwait
(
false
))
{
string
json
=
await
resp
.
Content
.
ReadAsStringAsync
().
ConfigureAwait
(
false
);
if
(!
resp
.
IsSuccessStatusCode
)
return
(
false
,
$"HTTP
{(
int
)
resp
.
StatusCode
}
:
{
TruncateModelResponse
(
json
,
200
)}
"
,
null
);
var
obj
=
JObject
.
Parse
(
json
);
var
data
=
obj
[
"data"
]
as
JArray
;
var
models
=
data
==
null
?
new
List
<
string
>()
:
data
.
OfType
<
JObject
>()
.
Select
(
x
=>
x
[
"id"
]?.
Value
<
string
>())
.
Where
(
x
=>
!
string
.
IsNullOrWhiteSpace
(
x
))
.
Distinct
(
StringComparer
.
OrdinalIgnoreCase
)
.
OrderBy
(
x
=>
x
,
StringComparer
.
OrdinalIgnoreCase
)
.
ToList
();
return
models
.
Count
==
0
?
(
false
,
"接口未返回可用模型"
,
null
)
:
(
true
,
$"获取到
{
models
.
Count
}
个模型"
,
models
);
}
}
}
}
catch
(
OperationCanceledException
)
{
return
(
false
,
"获取模型列表超时,请检查网络与 BaseUrl。"
,
null
);
}
catch
(
Exception
ex
)
{
return
(
false
,
ex
.
Message
,
null
);
}
}
private
static
string
TruncateModelResponse
(
string
text
,
int
max
)
{
if
(
string
.
IsNullOrEmpty
(
text
))
return
""
;
return
text
.
Length
<=
max
?
text
:
text
.
Substring
(
0
,
max
)
+
"…"
;
}
/// <summary>是否使用系统代理(默认 true;公司内网常用)。
/// 优先读取 HTTPS_PROXY / HTTP_PROXY 环境变量,否则用系统 IE 代理设置。
/// 修复:原实现属性为死字段(handler 在构造时绑定,开关从不生效);
...
...
@@ -321,10 +376,9 @@ namespace Tools.MyAgent.Agent
return
messages
.
Count
>
1
;
}
/// <summary>发送一次请求并读取 SSE 流;非成功状态码抛 HttpRequestException(附 Data["HttpStatusCode"])</summary>
private
async
Task
<
ChatResult
>
SendOnceAsync
(
JObject
body
,
CancellationToken
ct
)
{
var
req
=
new
HttpRequestMessage
(
HttpMethod
.
Post
,
BaseUrl
.
TrimEnd
(
'/'
)
+
"/chat/completions"
);
var
req
=
new
HttpRequestMessage
(
HttpMethod
.
Post
,
ResolveChatEndpoint
(
BaseUrl
)
);
req
.
Headers
.
TryAddWithoutValidation
(
"Authorization"
,
"Bearer "
+
ApiKey
);
req
.
Content
=
new
StringContent
(
body
.
ToString
(
Formatting
.
None
),
Encoding
.
UTF8
,
"application/json"
);
...
...
@@ -372,7 +426,15 @@ namespace Tools.MyAgent.Agent
}
}
/// <summary>连接测试:发送最小补全请求,返回(是否成功,信息)</summary>
private
static
string
ResolveChatEndpoint
(
string
baseUrl
)
{
string
value
=
(
baseUrl
??
""
).
Trim
().
TrimEnd
(
'/'
);
if
(
value
.
EndsWith
(
"/chat/completions"
,
StringComparison
.
OrdinalIgnoreCase
))
return
value
;
return
value
.
EndsWith
(
"/v1"
,
StringComparison
.
OrdinalIgnoreCase
)
?
value
+
"/chat/completions"
:
value
+
"/v1/chat/completions"
;
}
public
async
Task
<(
bool
Ok
,
string
Message
)>
TestConnectionAsync
(
CancellationToken
ct
)
{
try
...
...
@@ -387,7 +449,7 @@ namespace Tools.MyAgent.Agent
using
(
var
cts
=
CancellationTokenSource
.
CreateLinkedTokenSource
(
ct
))
{
cts
.
CancelAfter
(
15000
);
var
req
=
new
HttpRequestMessage
(
HttpMethod
.
Post
,
BaseUrl
.
TrimEnd
(
'/'
)
+
"/chat/completions"
);
var
req
=
new
HttpRequestMessage
(
HttpMethod
.
Post
,
ResolveChatEndpoint
(
BaseUrl
)
);
req
.
Headers
.
TryAddWithoutValidation
(
"Authorization"
,
"Bearer "
+
ApiKey
);
req
.
Content
=
new
StringContent
(
body
.
ToString
(
Formatting
.
None
),
Encoding
.
UTF8
,
"application/json"
);
...
...
@@ -396,6 +458,8 @@ namespace Tools.MyAgent.Agent
string
json
=
await
resp
.
Content
.
ReadAsStringAsync
().
ConfigureAwait
(
false
);
if
(!
resp
.
IsSuccessStatusCode
)
return
(
false
,
$"HTTP
{(
int
)
resp
.
StatusCode
}
:
{
Truncate
(
json
,
200
)}
"
);
if
(
json
.
TrimStart
().
StartsWith
(
"<"
,
StringComparison
.
Ordinal
))
return
(
false
,
"接口返回 HTML,请检查 BaseUrl 是否正确(通常应填写服务根地址或 /v1 地址)。"
);
var
obj
=
JObject
.
Parse
(
json
);
var
content
=
obj
[
"choices"
]?[
0
]?[
"message"
]?[
"content"
]?.
Value
<
string
>();
...
...
Tools/MyAgent/Config/AgentConfig.cs
View file @
0fff0a7b
...
...
@@ -23,6 +23,9 @@
/// <summary>【核心】模型名称(可填写任意 OpenAI 兼容模型,如 Ollama 本地模型)</summary>
public
string
Model
{
get
;
set
;
}
=
"deepseek-v4-flash"
;
/// <summary>按提供商保存的模型列表(获取成功后持久化,兼容旧配置缺省为空)</summary>
public
Dictionary
<
string
,
List
<
string
>>
ModelLists
{
get
;
set
;
}
=
new
Dictionary
<
string
,
List
<
string
>>();
/// <summary>【核心】知识库根目录(支持本地路径或网络共享 UNC 路径,如 \\服务器\共享名)</summary>
public
string
KnowledgeBasePath
{
get
;
set
;
}
=
""
;
...
...
Tools/MyAgent/Forms/AgentSettingsForm.Designer.cs
View file @
0fff0a7b
...
...
@@ -36,6 +36,7 @@
this
.
lblApiKey
=
new
System
.
Windows
.
Forms
.
Label
();
this
.
txtApiKey
=
new
System
.
Windows
.
Forms
.
TextBox
();
this
.
btnTestApi
=
new
System
.
Windows
.
Forms
.
Button
();
this
.
btnFetchModels
=
new
System
.
Windows
.
Forms
.
Button
();
this
.
lblBaseUrl
=
new
System
.
Windows
.
Forms
.
Label
();
this
.
txtBaseUrl
=
new
System
.
Windows
.
Forms
.
TextBox
();
this
.
lblModel
=
new
System
.
Windows
.
Forms
.
Label
();
...
...
@@ -165,6 +166,7 @@
this
.
grpModel
.
Controls
.
Add
(
this
.
txtBaseUrl
);
this
.
grpModel
.
Controls
.
Add
(
this
.
lblModel
);
this
.
grpModel
.
Controls
.
Add
(
this
.
cmbModel
);
this
.
grpModel
.
Controls
.
Add
(
this
.
btnFetchModels
);
this
.
grpModel
.
Location
=
new
System
.
Drawing
.
Point
(
8
,
12
);
this
.
grpModel
.
Name
=
"grpModel"
;
this
.
grpModel
.
Size
=
new
System
.
Drawing
.
Size
(
596
,
164
);
...
...
@@ -260,9 +262,19 @@
"deepseek-r1"
});
this
.
cmbModel
.
Location
=
new
System
.
Drawing
.
Point
(
92
,
124
);
this
.
cmbModel
.
Name
=
"cmbModel"
;
this
.
cmbModel
.
Size
=
new
System
.
Drawing
.
Size
(
48
6
,
25
);
this
.
cmbModel
.
Size
=
new
System
.
Drawing
.
Size
(
30
6
,
25
);
this
.
cmbModel
.
TabIndex
=
8
;
//
// btnFetchModels
//
this
.
btnFetchModels
.
Location
=
new
System
.
Drawing
.
Point
(
406
,
123
);
this
.
btnFetchModels
.
Name
=
"btnFetchModels"
;
this
.
btnFetchModels
.
Size
=
new
System
.
Drawing
.
Size
(
172
,
25
);
this
.
btnFetchModels
.
TabIndex
=
9
;
this
.
btnFetchModels
.
Text
=
"获取模型列表"
;
this
.
btnFetchModels
.
UseVisualStyleBackColor
=
true
;
this
.
btnFetchModels
.
Click
+=
new
System
.
EventHandler
(
this
.
OnFetchModels
);
//
// grpKb
//
this
.
grpKb
.
Controls
.
Add
(
this
.
lblMode
);
...
...
@@ -1084,6 +1096,7 @@
private
System
.
Windows
.
Forms
.
Label
lblApiKey
;
private
System
.
Windows
.
Forms
.
TextBox
txtApiKey
;
private
System
.
Windows
.
Forms
.
Button
btnTestApi
;
private
System
.
Windows
.
Forms
.
Button
btnFetchModels
;
private
System
.
Windows
.
Forms
.
Label
lblBaseUrl
;
private
System
.
Windows
.
Forms
.
TextBox
txtBaseUrl
;
private
System
.
Windows
.
Forms
.
Label
lblModel
;
...
...
Tools/MyAgent/Forms/AgentSettingsForm.cs
View file @
0fff0a7b
...
...
@@ -21,8 +21,33 @@ namespace Tools.MyAgent.Forms
/// </summary>
public
partial
class
AgentSettingsForm
:
Form
{
/// <summary>仅支持的模型</summary>
public
static
readonly
string
[]
SupportedModels
=
{
"deepseek-v4-flash"
,
"deepseek-v4-pro"
};
/// <summary>模型建议列表(下拉仅作建议,模型框仍允许输入任意兼容模型)</summary>
private
static
readonly
string
[][]
ProviderModelSuggestions
=
{
new
[]
{
"deepseek-v4-flash"
,
"deepseek-v4-pro"
,
"deepseek-reasoner"
},
new
[]
{
"qwen-plus"
,
"qwen-turbo"
,
"qwen-max"
,
"qwen-vl-plus"
},
new
[]
{
"gpt-4o-mini"
,
"gpt-4o"
,
"gpt-4.1-mini"
},
new
[]
{
"qwen2.5"
,
"qwen2.5:7b"
,
"llama3.1"
,
"deepseek-r1"
},
new
string
[
0
],
};
/// <summary>兼容旧配置中的提供商名称(保存时统一为当前预设名称)</summary>
private
static
readonly
string
[][]
ProviderAliases
=
{
new
[]
{
"deepseek"
,
"DeepSeek"
},
new
[]
{
"qwen"
,
"通义"
,
"通义千问"
,
"aliyun"
,
"dashscope"
},
new
[]
{
"openai"
},
new
[]
{
"ollama"
,
"本地ollama"
,
"本地 Ollama"
},
new
[]
{
"custom"
,
"自定义"
},
};
/// <summary>兼容旧调用方的模型集合;设置页实际按提供商显示建议。</summary>
public
static
readonly
string
[]
SupportedModels
=
{
"deepseek-v4-flash"
,
"deepseek-v4-pro"
,
"deepseek-reasoner"
,
"qwen-plus"
,
"qwen-turbo"
,
"qwen-max"
,
"qwen-vl-plus"
,
"gpt-4o-mini"
,
"gpt-4o"
,
"gpt-4.1-mini"
,
"qwen2.5"
,
"qwen2.5:7b"
,
"llama3.1"
,
"deepseek-r1"
,
};
/// <summary>提供商预设(选择后自动填充 BaseUrl / 模型名;「自定义」保留 BaseUrl 自由输入)</summary>
public
static
readonly
(
string
Name
,
string
BaseUrl
,
string
Model
)[]
ProviderPresets
=
...
...
@@ -41,13 +66,10 @@ namespace Tools.MyAgent.Forms
public
static
int
CurrentProviderIndex
(
AgentConfig
config
)
{
string
provider
=
(
config
?.
Provider
??
""
).
Trim
();
int
aliasIndex
=
FindProviderAlias
(
provider
);
if
(
aliasIndex
>=
0
)
return
aliasIndex
;
if
(
provider
.
Length
>
0
)
{
for
(
int
i
=
0
;
i
<
ProviderPresets
.
Length
;
i
++)
if
(
string
.
Equals
(
ProviderPresets
[
i
].
Name
,
provider
,
StringComparison
.
OrdinalIgnoreCase
))
return
i
;
return
CustomProviderIndex
;
// 保存的提供商不在预设内 → 自定义
}
string
baseUrl
=
(
config
?.
BaseUrl
??
""
).
ToLowerInvariant
();
if
(
baseUrl
.
Contains
(
"localhost"
)
||
baseUrl
.
Contains
(
"11434"
))
return
3
;
// Ollama
if
(
baseUrl
.
Contains
(
"dashscope"
)
||
baseUrl
.
Contains
(
"aliyun"
))
return
1
;
// 通义
...
...
@@ -58,6 +80,12 @@ namespace Tools.MyAgent.Forms
private
readonly
AgentConfig
_config
;
// 各提供商独立保存 API Key、当前模型和已获取的模型列表,切换时互不覆盖。
private
readonly
Dictionary
<
int
,
string
>
_cachedApiKeys
=
new
Dictionary
<
int
,
string
>();
private
readonly
Dictionary
<
int
,
string
>
_cachedModels
=
new
Dictionary
<
int
,
string
>();
private
readonly
Dictionary
<
int
,
List
<
string
>>
_cachedModelItems
=
new
Dictionary
<
int
,
List
<
string
>>();
private
int
_lastProviderIndex
=
-
1
;
// 本地/共享两种方式各自的路径缓存(切换方式时互相恢复)
private
string
_cachedLocalPath
=
""
,
_cachedSharedPath
=
""
;
private
bool
_lastSharedMode
;
...
...
@@ -204,13 +232,15 @@ namespace Tools.MyAgent.Forms
private
void
BindConfig
()
{
// 基础配置:模型(先设提供商以触发预设联动,再以配置覆盖模型/Key)
cmbProvider
.
SelectedIndex
=
CurrentProviderIndex
(
_config
);
int
providerIndex
=
CurrentProviderIndex
(
_config
);
cmbProvider
.
SelectedIndex
=
providerIndex
;
LoadModelCache
();
_lastProviderIndex
=
providerIndex
;
_cachedModels
[
providerIndex
]
=
_config
.
Model
??
""
;
txtApiKey
.
Text
=
_config
.
ApiKey
;
txtBaseUrl
.
Text
=
_config
.
BaseUrl
;
if
(
SupportedModels
.
Contains
(
_config
.
Model
??
""
))
cmbModel
.
SelectedItem
=
_config
.
Model
;
else
cmbModel
.
Text
=
_config
.
Model
??
""
;
RefreshModelItems
();
cmbModel
.
Text
=
_config
.
Model
??
""
;
// 基础配置:知识库(先写路径/账号缓存,再切方式,避免 SyncPathWithMode 误动)
string
savedMode
=
(
_config
.
KbMode
??
""
).
Trim
().
ToLowerInvariant
();
...
...
@@ -304,6 +334,134 @@ namespace Tools.MyAgent.Forms
}
}
/// <summary>更新模型建议;当前配置始终保留在可选项中,兼容新发布模型和旧配置。</summary>
private
static
void
SetModelSuggestions
(
ComboBox
combo
,
int
providerIndex
,
string
currentModel
)
{
if
(
combo
==
null
)
return
;
string
[]
suggestions
=
providerIndex
>=
0
&&
providerIndex
<
ProviderModelSuggestions
.
Length
?
ProviderModelSuggestions
[
providerIndex
]
:
new
string
[
0
];
string
current
=
(
currentModel
??
""
).
Trim
();
combo
.
Items
.
Clear
();
foreach
(
string
model
in
suggestions
)
combo
.
Items
.
Add
(
model
);
if
(
current
.
Length
>
0
&&
!
suggestions
.
Contains
(
current
,
StringComparer
.
OrdinalIgnoreCase
))
combo
.
Items
.
Add
(
current
);
}
private
static
bool
IsSuggestedModel
(
string
model
)
{
string
value
=
(
model
??
""
).
Trim
();
if
(
value
.
Length
==
0
)
return
true
;
foreach
(
string
[]
suggestions
in
ProviderModelSuggestions
)
if
(
suggestions
.
Contains
(
value
,
StringComparer
.
OrdinalIgnoreCase
))
return
true
;
return
false
;
}
/// <summary>根据旧配置的 Provider 或 BaseUrl 推断当前预设。</summary>
private
static
int
FindProviderAlias
(
string
provider
)
{
string
value
=
(
provider
??
""
).
Trim
();
for
(
int
i
=
0
;
i
<
ProviderAliases
.
Length
;
i
++)
foreach
(
string
alias
in
ProviderAliases
[
i
])
if
(
string
.
Equals
(
alias
,
value
,
StringComparison
.
OrdinalIgnoreCase
))
return
i
;
return
-
1
;
}
/// <summary>按提供商刷新模型下拉项:优先使用已保存的远程列表,没有时使用内置建议。</summary>
private
void
RefreshModelItems
()
{
int
index
=
cmbProvider
.
SelectedIndex
;
if
(
index
<
0
)
return
;
string
current
=
cmbModel
.
Text
.
Trim
();
if
(
_cachedModelItems
.
TryGetValue
(
index
,
out
var
cached
)
&&
cached
.
Count
>
0
)
{
cmbModel
.
Items
.
Clear
();
cmbModel
.
Items
.
AddRange
(
cached
.
ToArray
());
if
(
current
.
Length
>
0
&&
!
cached
.
Contains
(
current
,
StringComparer
.
OrdinalIgnoreCase
))
cmbModel
.
Items
.
Add
(
current
);
}
else
{
SetModelSuggestions
(
cmbModel
,
index
,
current
);
}
}
private
void
LoadModelCache
()
{
_cachedModelItems
.
Clear
();
var
saved
=
_config
.
ModelLists
;
if
(
saved
==
null
)
return
;
for
(
int
i
=
0
;
i
<
ProviderPresets
.
Length
;
i
++)
{
var
hit
=
saved
.
FirstOrDefault
(
kv
=>
string
.
Equals
(
kv
.
Key
,
ProviderPresets
[
i
].
Name
,
StringComparison
.
OrdinalIgnoreCase
));
if
(!
string
.
IsNullOrEmpty
(
hit
.
Key
)
&&
hit
.
Value
!=
null
)
_cachedModelItems
[
i
]
=
hit
.
Value
.
Where
(
m
=>
!
string
.
IsNullOrWhiteSpace
(
m
)).
Distinct
(
StringComparer
.
OrdinalIgnoreCase
).
ToList
();
}
}
private
void
SaveModelCache
()
{
var
saved
=
new
Dictionary
<
string
,
List
<
string
>>(
StringComparer
.
OrdinalIgnoreCase
);
foreach
(
var
pair
in
_cachedModelItems
)
if
(
pair
.
Key
>=
0
&&
pair
.
Key
<
ProviderPresets
.
Length
&&
pair
.
Value
!=
null
)
saved
[
ProviderPresets
[
pair
.
Key
].
Name
]
=
pair
.
Value
.
ToList
();
_config
.
ModelLists
=
saved
;
}
private
static
bool
IsLocalEndpoint
(
string
baseUrl
)
{
if
(
string
.
IsNullOrWhiteSpace
(
baseUrl
))
return
false
;
string
value
=
baseUrl
.
ToLowerInvariant
();
return
value
.
Contains
(
"localhost"
)
||
value
.
Contains
(
"127.0.0.1"
)
||
value
.
Contains
(
"11434"
);
}
private
async
void
OnFetchModels
(
object
sender
,
EventArgs
e
)
{
string
baseUrl
=
EffectiveBaseUrl
();
if
(
string
.
IsNullOrWhiteSpace
(
baseUrl
))
{
AgentUtils
.
Toast
(
"请先填写 BaseUrl"
,
3000
);
return
;
}
if
(
string
.
IsNullOrWhiteSpace
(
txtApiKey
.
Text
)
&&
!
IsLocalEndpoint
(
baseUrl
))
{
AgentUtils
.
Toast
(
"请先填写 API Key"
,
3000
);
return
;
}
var
btn
=
(
Button
)
sender
;
btn
.
Enabled
=
false
;
btn
.
Text
=
"获取中..."
;
try
{
using
(
var
client
=
new
OpenAiCompatibleClient
{
BaseUrl
=
baseUrl
,
ApiKey
=
txtApiKey
.
Text
.
Trim
(),
})
{
var
result
=
await
client
.
FetchModelsAsync
(
CancellationToken
.
None
);
if
(!
result
.
Ok
)
{
AgentUtils
.
Toast
(
"获取模型列表失败:"
+
result
.
Message
,
5000
);
return
;
}
int
index
=
cmbProvider
.
SelectedIndex
;
_cachedModelItems
[
index
]
=
result
.
Models
;
string
current
=
cmbModel
.
Text
.
Trim
();
RefreshModelItems
();
if
(
string
.
IsNullOrEmpty
(
current
)
&&
cmbModel
.
Items
.
Count
>
0
)
cmbModel
.
SelectedIndex
=
0
;
AgentUtils
.
Toast
(
result
.
Message
+
",已填充下拉选项"
,
2500
);
}
}
finally
{
btn
.
Enabled
=
true
;
btn
.
Text
=
"获取模型列表"
;
}
}
// ══ 基础配置页布局联动 ══
/// <summary>提供商联动:仅「自定义」显示 BaseUrl 行,其余预设隐藏(减少心智负担)</summary>
...
...
@@ -312,10 +470,11 @@ namespace Tools.MyAgent.Forms
bool
custom
=
cmbProvider
.
SelectedIndex
==
CustomProviderIndex
;
lblBaseUrl
.
Visible
=
custom
;
txtBaseUrl
.
Visible
=
custom
;
var
lblModel
=
grpModel
.
Controls
[
"lblModel"
];
int
modelY
=
custom
?
128
:
96
;
if
(
lblModel
!=
null
)
lblModel
.
Top
=
modelY
;
var
modelLabel
=
grpModel
.
Controls
[
"lblModel"
];
if
(
modelLabel
!=
null
)
modelLabel
.
Top
=
modelY
;
cmbModel
.
Top
=
modelY
-
4
;
btnFetchModels
.
Top
=
modelY
-
5
;
grpModel
.
Height
=
custom
?
164
:
132
;
ApplyBasicLayout
();
}
...
...
@@ -376,13 +535,18 @@ namespace Tools.MyAgent.Forms
{
if
(
cmbProvider
.
SelectedIndex
<
0
)
return
;
ApplyProviderMode
();
if
(
cmbProvider
.
SelectedIndex
!=
CustomProviderIndex
)
if
(
_lastProviderIndex
>=
0
)
{
var
p
=
ProviderPresets
[
cmbProvider
.
SelectedIndex
];
cmbModel
.
Text
=
p
.
Model
;
if
(
p
.
Name
==
"本地 Ollama"
&&
string
.
IsNullOrEmpty
(
txtApiKey
.
Text
))
txtApiKey
.
Text
=
"ollama"
;
_cachedApiKeys
[
_lastProviderIndex
]
=
txtApiKey
.
Text
.
Trim
();
_cachedModels
[
_lastProviderIndex
]
=
cmbModel
.
Text
.
Trim
();
}
_lastProviderIndex
=
cmbProvider
.
SelectedIndex
;
var
p
=
ProviderPresets
[
cmbProvider
.
SelectedIndex
];
txtApiKey
.
Text
=
_cachedApiKeys
.
TryGetValue
(
_lastProviderIndex
,
out
string
key
)
?
key
:
(
p
.
Name
==
"本地 Ollama"
?
"ollama"
:
""
);
RefreshModelItems
();
cmbModel
.
Text
=
_cachedModels
.
TryGetValue
(
_lastProviderIndex
,
out
string
model
)
&&
!
string
.
IsNullOrWhiteSpace
(
model
)
?
model
:
(
cmbProvider
.
SelectedIndex
==
CustomProviderIndex
?
""
:
p
.
Model
);
}
/// <summary>知识库方式切换:布局联动 + 路径缓存互切(初始化回填由 BindConfig 抑制)</summary>
...
...
@@ -540,6 +704,9 @@ namespace Tools.MyAgent.Forms
_config
.
Provider
=
cmbProvider
.
SelectedIndex
>=
0
?
ProviderPresets
[
cmbProvider
.
SelectedIndex
].
Name
:
""
;
_config
.
BaseUrl
=
custom
?
txtBaseUrl
.
Text
.
Trim
()
:
EffectiveBaseUrl
();
_config
.
Model
=
string
.
IsNullOrEmpty
(
cmbModel
.
Text
.
Trim
())
?
SupportedModels
[
0
]
:
cmbModel
.
Text
.
Trim
();
if
(
cmbProvider
.
SelectedIndex
>=
0
)
_cachedModels
[
cmbProvider
.
SelectedIndex
]
=
_config
.
Model
;
SaveModelCache
();
// 基础配置:知识库(方式以用户选择为准,避免重新打开时被路径自动识别回退)
_config
.
KnowledgeBasePath
=
txtKb
.
Text
.
Trim
();
_config
.
KbMode
=
rdoShared
.
Checked
?
"shared"
:
"local"
;
...
...
Tools/MyAgent/wMyAgent.cs
View file @
0fff0a7b
...
...
@@ -216,6 +216,7 @@ namespace Tools.MyAgent
BaseUrl
=
cfg
.
BaseUrl
,
Model
=
cfg
.
Model
,
Provider
=
cfg
.
Provider
,
ModelLists
=
cfg
.
ModelLists
??
new
Dictionary
<
string
,
List
<
string
>>(),
KnowledgeBasePath
=
cfg
.
KnowledgeBasePath
,
KbMode
=
cfg
.
KbMode
,
ShareUser
=
cfg
.
ShareUser
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment