Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
AI
/
large-language-model
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
cc2771a5
authored
Mar 18, 2025
by
王一诺
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
文本和图片接口都是用了openai 标准接口,返回值提供stream 和 json 两种形式
parent
fc19145a
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
715 additions
and
564 deletions
.idea/vcs.xml
.idea/workspace.xml
api-llm/src/main/java/com/coolook/llm/api/remote/ServiceLLMClient.java
api-llm/src/main/java/com/coolook/llm/api/service/impl/AiServiceImpl.java
api-llm/src/main/resources/application-global.yml
api-llm/src/main/resources/application.yml
common-llm/src/main/java/com/coolook/common/llm/constant/ContentDeserializer.java
common-llm/src/main/java/com/coolook/common/llm/dto/Choices.java
common-llm/src/main/java/com/coolook/common/llm/dto/Usage.java
common-llm/src/main/java/com/coolook/common/llm/request/OpenAiImageRequest.java
common-llm/src/main/java/com/coolook/common/llm/request/TextContent.java
common-llm/src/main/java/com/coolook/common/llm/request/base/BaseMessage.java
common-llm/src/main/java/com/coolook/common/llm/request/base/BaseRequest.java
common-llm/src/main/java/com/coolook/common/llm/request/ImageContent.java → common-llm/src/main/java/com/coolook/common/llm/request/image/ImageContent.java
common-llm/src/main/java/com/coolook/common/llm/request/ImageMessage.java → common-llm/src/main/java/com/coolook/common/llm/request/image/ImageMessage.java
common-llm/src/main/java/com/coolook/common/llm/request/image/ImageRequest.java
common-llm/src/main/java/com/coolook/common/llm/request/ImageUrl.java → common-llm/src/main/java/com/coolook/common/llm/request/image/ImageUrl.java
common-llm/src/main/java/com/coolook/common/llm/request/TextMessage.java → common-llm/src/main/java/com/coolook/common/llm/request/text/TextMessage.java
common-llm/src/main/java/com/coolook/common/llm/request/OpenAiTextRequest.java → common-llm/src/main/java/com/coolook/common/llm/request/text/TextRequest.java
common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModel.java
common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModelError.java
service-llm/src/main/java/com/coolook/service/llm/controller/SearchConfigController.java → service-llm/src/main/java/com/coolook/service/llm/controller/ConfigController.java
service-llm/src/main/java/com/coolook/service/llm/controller/CustomModelController.java
service-llm/src/main/java/com/coolook/service/llm/controller/ModelController.java
service-llm/src/main/java/com/coolook/service/llm/controller/DataSyncController.java → service-llm/src/main/java/com/coolook/service/llm/controller/ModelManagerController.java
service-llm/src/main/java/com/coolook/service/llm/remote/LLMClient.java
service-llm/src/main/java/com/coolook/service/llm/service/SearchConfigService.java → service-llm/src/main/java/com/coolook/service/llm/service/ConfigService.java
service-llm/src/main/java/com/coolook/service/llm/service/IImageModelService.java
service-llm/src/main/java/com/coolook/service/llm/service/ITextModelService.java
service-llm/src/main/java/com/coolook/service/llm/service/InitializerService.java → service-llm/src/main/java/com/coolook/service/llm/service/InitTaskService.java
service-llm/src/main/java/com/coolook/service/llm/service/ModelDataService.java
service-llm/src/main/java/com/coolook/service/llm/service/ModelService.java → service-llm/src/main/java/com/coolook/service/llm/service/impl/ImageModelServiceImpl.java
service-llm/src/main/java/com/coolook/service/llm/service/impl/TextModelServiceImpl.java
service-llm/src/main/resources/application-global.yml
service-llm/src/main/resources/application.yml
.idea/vcs.xml
0 → 100644
View file @
cc2771a5
<?xml version="1.0" encoding="UTF-8"?>
<project
version=
"4"
>
<component
name=
"VcsDirectoryMappings"
>
<mapping
directory=
"$PROJECT_DIR$"
vcs=
"Git"
/>
</component>
</project>
\ No newline at end of file
.idea/workspace.xml
View file @
cc2771a5
...
...
@@ -4,7 +4,41 @@
<option
name=
"autoReloadType"
value=
"SELECTIVE"
/>
</component>
<component
name=
"ChangeListManager"
>
<list
default=
"true"
id=
"6879e488-b2d7-4692-a578-ccef01aca622"
name=
"Changes"
comment=
""
/>
<list
default=
"true"
id=
"6879e488-b2d7-4692-a578-ccef01aca622"
name=
"Changes"
comment=
""
>
<change
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/constant/ContentDeserializer.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/base/BaseMessage.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/base/BaseRequest.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/image/ImageRequest.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/ModelController.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/IImageModelService.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ITextModelService.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/impl/ImageModelServiceImpl.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/api-llm/src/main/java/com/coolook/llm/api/remote/ServiceLLMClient.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/api-llm/src/main/java/com/coolook/llm/api/remote/ServiceLLMClient.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/api-llm/src/main/java/com/coolook/llm/api/service/impl/AiServiceImpl.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/api-llm/src/main/java/com/coolook/llm/api/service/impl/AiServiceImpl.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/api-llm/src/main/resources/application-global.yml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/api-llm/src/main/resources/application-global.yml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/api-llm/src/main/resources/application.yml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/api-llm/src/main/resources/application.yml"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/dto/Choices.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/dto/Usage.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/ImageContent.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/image/ImageContent.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/ImageMessage.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/image/ImageMessage.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/ImageUrl.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/image/ImageUrl.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/OpenAiImageRequest.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/OpenAiTextRequest.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/text/TextRequest.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/TextContent.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/TextMessage.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/request/text/TextMessage.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModel.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModelError.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/CustomModelController.java"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/DataSyncController.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/ModelManagerController.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/SearchConfigController.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/controller/ConfigController.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/remote/LLMClient.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/remote/LLMClient.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/InitializerService.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/InitTaskService.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ModelDataService.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ModelDataService.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ModelService.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/impl/TextModelServiceImpl.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/SearchConfigService.java"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ConfigService.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/resources/application-global.yml"
beforeDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/service-llm/src/main/resources/application.yml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/service-llm/src/main/resources/application.yml"
afterDir=
"false"
/>
</list>
<option
name=
"SHOW_DIALOG"
value=
"false"
/>
<option
name=
"HIGHLIGHT_CONFLICTS"
value=
"true"
/>
<option
name=
"HIGHLIGHT_NON_ACTIVE_CHANGELIST"
value=
"false"
/>
...
...
@@ -19,6 +53,9 @@
</list>
</option>
</component>
<component
name=
"Git.Settings"
>
<option
name=
"RECENT_GIT_ROOT_PATH"
value=
"$PROJECT_DIR$"
/>
</component>
<component
name=
"KubernetesApiPersistence"
>
{}
</component>
<component
name=
"KubernetesApiProvider"
>
{
"
isMigrated
"
: true
...
...
@@ -34,53 +71,57 @@
<option
name=
"hideEmptyMiddlePackages"
value=
"true"
/>
<option
name=
"showLibraryContents"
value=
"true"
/>
</component>
<component
name=
"PropertiesComponent"
>
{
"
keyToString
"
: {
"
Application.LLMClient.executor
"
:
"
Run
"
,
"
Maven. [org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate].executor
"
:
"
Run
"
,
"
Maven.api-llm [clean].executor
"
:
"
Run
"
,
"
Maven.api-llm [package].executor
"
:
"
Run
"
,
"
Maven.common-llm [clean].executor
"
:
"
Run
"
,
"
Maven.common-llm [compile].executor
"
:
"
Run
"
,
"
Maven.common-llm [install].executor
"
:
"
Run
"
,
"
Maven.common-llm [package].executor
"
:
"
Run
"
,
"
Maven.large-language-model [clean].executor
"
:
"
Run
"
,
"
Maven.large-language-model [package].executor
"
:
"
Run
"
,
"
Maven.llm-api [clean].executor
"
:
"
Run
"
,
"
Maven.llm-api [compile].executor
"
:
"
Run
"
,
"
Maven.llm-api [package].executor
"
:
"
Run
"
,
"
Maven.llm-api [test].executor
"
:
"
Run
"
,
"
Maven.service-llm [clean].executor
"
:
"
Run
"
,
"
Maven.service-llm [package].executor
"
:
"
Run
"
,
"
Maven.service-llm-text [clean].executor
"
:
"
Run
"
,
"
Maven.service-llm-text [compile].executor
"
:
"
Run
"
,
"
Maven.service-llm-text [package].executor
"
:
"
Run
"
,
"
RequestMappingsPanelOrder0
"
:
"
0
"
,
"
RequestMappingsPanelOrder1
"
:
"
1
"
,
"
RequestMappingsPanelWidth0
"
:
"
75
"
,
"
RequestMappingsPanelWidth1
"
:
"
75
"
,
"
RunOnceActivity.ShowReadmeOnStart
"
:
"
true
"
,
"
Spring Boot.LLMApiApplication.executor
"
:
"
Run
"
,
"
Spring Boot.ServiceLlmApplication.executor
"
:
"
Run
"
,
"
com.codeium.enabled
"
:
"
true
"
,
"
kotlin-language-version-configured
"
:
"
true
"
,
"
last_opened_file_path
"
:
"
/Users/wangyinuo/workspace/code/java/large-language-model/api-llm/src/main/resources
"
,
"
node.js.detected.package.eslint
"
:
"
true
"
,
"
node.js.detected.package.tslint
"
:
"
true
"
,
"
node.js.selected.package.eslint
"
:
"
(autodetect)
"
,
"
node.js.selected.package.tslint
"
:
"
(autodetect)
"
,
"
nodejs_package_manager_path
"
:
"
npm
"
,
"
project.structure.last.edited
"
:
"
Modules
"
,
"
project.structure.proportion
"
:
"
0.0
"
,
"
project.structure.side.proportion
"
:
"
0.0
"
,
"
settings.editor.selected.configurable
"
:
"
build.tools
"
,
"
vue.rearranger.settings.migration
"
:
"
true
"
<component
name=
"PropertiesComponent"
>
<![CDATA[{
"keyToString": {
"Application.LLMClient.executor": "Run",
"Maven. [org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate].executor": "Run",
"Maven.api-llm [clean].executor": "Run",
"Maven.api-llm [package].executor": "Run",
"Maven.common-llm [clean].executor": "Run",
"Maven.common-llm [compile].executor": "Run",
"Maven.common-llm [install].executor": "Run",
"Maven.common-llm [package].executor": "Run",
"Maven.large-language-model [clean].executor": "Run",
"Maven.large-language-model [package].executor": "Run",
"Maven.llm-api [clean].executor": "Run",
"Maven.llm-api [compile].executor": "Run",
"Maven.llm-api [package].executor": "Run",
"Maven.llm-api [test].executor": "Run",
"Maven.service-llm [clean].executor": "Run",
"Maven.service-llm [package].executor": "Run",
"Maven.service-llm-text [clean].executor": "Run",
"Maven.service-llm-text [compile].executor": "Run",
"Maven.service-llm-text [package].executor": "Run",
"RequestMappingsPanelOrder0": "0",
"RequestMappingsPanelOrder1": "1",
"RequestMappingsPanelWidth0": "75",
"RequestMappingsPanelWidth1": "75",
"RunOnceActivity.ShowReadmeOnStart": "true",
"Spring Boot.LLMApiApplication.executor": "Run",
"Spring Boot.ServiceLlmApplication.executor": "Debug",
"com.codeium.enabled": "true",
"git-widget-placeholder": "main",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "/Users/wangyinuo/workspace/code/java/large-language-model/api-llm/src/main/resources",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"project.structure.last.edited": "Modules",
"project.structure.proportion": "0.0",
"project.structure.side.proportion": "0.0",
"settings.editor.selected.configurable": "build.tools",
"vue.rearranger.settings.migration": "true"
}
}
</component>
}
]]>
</component>
<component
name=
"ReactorSettings"
>
<option
name=
"notificationShown"
value=
"true"
/>
</component>
<component
name=
"RecentsManager"
>
<key
name=
"CreateClassDialog.RecentsKey"
>
<recent
name=
"com.coolook.common.llm.response"
/>
</key>
<key
name=
"CopyFile.RECENT_KEYS"
>
<recent
name=
"$PROJECT_DIR$/api-llm/src/main/resources"
/>
<recent
name=
"$PROJECT_DIR$/service-llm/src/main/resources"
/>
...
...
@@ -89,11 +130,11 @@
<recent
name=
"$PROJECT_DIR$/common-llm/src/main/java/com/coolook/common/llm/utils"
/>
</key>
<key
name=
"CopyClassDialog.RECENTS_KEY"
>
<recent
name=
"com.coolook.service.llm.controller"
/>
<recent
name=
"com.coolook.service.llm.service"
/>
<recent
name=
"com.coolook.common.llm.request"
/>
<recent
name=
"com.coolook.common.llm.request.text"
/>
<recent
name=
"com.coolook.common.llm.dto"
/>
<recent
name=
"com.coolook.common.llm.response"
/>
<recent
name=
"com.coolook.service.llm.controller"
/>
<recent
name=
"com.coolook.common.llm.pojo"
/>
</key>
</component>
<component
name=
"RunDashboard"
>
...
...
@@ -193,13 +234,25 @@
<workItem
from=
"1741920343491"
duration=
"1645000"
/>
<workItem
from=
"1741931944414"
duration=
"27842000"
/>
<workItem
from=
"1742177794559"
duration=
"6136000"
/>
<workItem
from=
"1742193641040"
duration=
"4084000"
/>
<workItem
from=
"1742193641040"
duration=
"7021000"
/>
<workItem
from=
"1742201439685"
duration=
"34459000"
/>
</task>
<servers
/>
</component>
<component
name=
"TypeScriptGeneratedFilesManager"
>
<option
name=
"version"
value=
"3"
/>
</component>
<component
name=
"Vcs.Log.Tabs.Properties"
>
<option
name=
"TAB_STATES"
>
<map>
<entry
key=
"MAIN"
>
<value>
<State
/>
</value>
</entry>
</map>
</option>
</component>
<component
name=
"XDebuggerManager"
>
<breakpoint-manager>
<breakpoints>
...
...
@@ -207,11 +260,6 @@
<properties
class=
"java.lang.NullPointerException"
package=
"java.lang"
/>
<option
name=
"timeStamp"
value=
"1"
/>
</breakpoint>
<line-breakpoint
enabled=
"true"
type=
"java-line"
>
<url>
file://$PROJECT_DIR$/service-llm/src/main/java/com/coolook/service/llm/service/ModelService.java
</url>
<line>
101
</line>
<option
name=
"timeStamp"
value=
"2"
/>
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
<watches-manager>
...
...
api-llm/src/main/java/com/coolook/llm/api/remote/ServiceLLMClient.java
View file @
cc2771a5
package
com
.
coolook
.
llm
.
api
.
remote
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.response.ResponseResult
;
import
com.coolook.common.llm.request.OpenAiTextRequest
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.ResponseEntity
;
...
...
@@ -11,7 +10,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author: Wang Yinuo
...
...
@@ -22,8 +20,8 @@ import java.util.Map;
public
interface
ServiceLLMClient
{
@RequestMapping
(
method
=
RequestMethod
.
POST
,
value
=
"/text/v1/chat/completions"
)
public
ResponseEntity
<
String
>
chat
(
@RequestBody
OpenAi
TextRequest
content
);
public
ResponseEntity
<
String
>
chat
(
@RequestBody
TextRequest
content
);
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/v1/models"
)
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/
text/
v1/models"
)
public
HttpEntity
<
List
<
ModelsDto
>>
getAvailableModelList
();
}
api-llm/src/main/java/com/coolook/llm/api/service/impl/AiServiceImpl.java
View file @
cc2771a5
...
...
@@ -6,9 +6,8 @@ import com.alibaba.fastjson2.JSONObject;
import
com.coolook.common.llm.constant.AiStatus
;
import
com.coolook.common.llm.dto.Message
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.request.OpenAiTextRequest
;
import
com.coolook.common.llm.request.TextContent
;
import
com.coolook.common.llm.request.TextMessage
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
com.coolook.common.llm.request.text.TextMessage
;
import
com.coolook.common.llm.response.ResponseResult
;
import
com.coolook.common.llm.utils.SecurityUtils
;
import
com.coolook.llm.api.remote.ServiceLLMClient
;
...
...
@@ -22,7 +21,6 @@ import lombok.extern.slf4j.Slf4j;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author: WangYinuo
...
...
@@ -61,7 +59,6 @@ public class AiServiceImpl implements IAiService {
return
ResponseResult
.
success
(
error
);
}
@Override
public
ResponseResult
<
Message
>
ask
(
Message
msg
)
{
String
msgId
=
msg
.
getMsgId
().
replace
(
"_forword"
,
""
);;
...
...
@@ -84,17 +81,20 @@ public class AiServiceImpl implements IAiService {
HttpEntity
<
List
<
ModelsDto
>>
availableModelEntity
=
serviceLlmClient
.
getAvailableModelList
();
List
<
ModelsDto
>
textModelList
=
availableModelEntity
.
getBody
();
OpenAiTextRequest
openAiTextRequest
=
new
OpenAi
TextRequest
();
TextRequest
openAiTextRequest
=
new
TextRequest
();
openAiTextRequest
.
setModel
(
textModelList
.
get
(
0
).
getId
());
List
<
TextMessage
>
messageList
=
new
ArrayList
();
messageList
.
add
(
new
TextMessage
(
"user"
,
msg
.
getAiQuestion
()));
TextMessage
textMessage
=
new
TextMessage
();
textMessage
.
setContent
(
msg
.
getAiQuestion
());
textMessage
.
setRole
(
"user"
);
messageList
.
add
(
textMessage
);
openAiTextRequest
.
setMessages
(
messageList
);
ResponseEntity
<
String
>
responseMsg
=
serviceLlmClient
.
chat
(
openAiTextRequest
);
String
content
=
parseResponseEntity
(
responseMsg
.
getBody
());
log
.
info
(
"responseMsg:{}"
,
responseMsg
);
if
(
responseMsg
!=
null
)
{
Message
aiMessage
=
new
Message
();
...
...
api-llm/src/main/resources/application-global.yml
View file @
cc2771a5
...
...
@@ -8,4 +8,4 @@ spring:
cloud
:
nacos
:
discovery
:
server-addr
:
158.178.244.87
\ No newline at end of file
server-addr
:
158.178.244.87:8848
\ No newline at end of file
api-llm/src/main/resources/application.yml
View file @
cc2771a5
server
:
port
:
8900
port
:
9009
servlet
:
# 应用的访问路径
context-path
:
/ai-server
...
...
@@ -8,7 +8,7 @@ spring:
application
:
name
:
llm-api
profiles
:
active
:
loc
al
active
:
glob
al
app
:
displacementDictionary
:
"
aigmzp79Y6FOodkI4etj5XbfxGrRSHEZcAw0UDPn8LBhV1yqMuvKWsJlCN3T2Q"
common-llm/src/main/java/com/coolook/common/llm/constant/ContentDeserializer.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
constant
;
import
com.coolook.common.llm.request.image.ImageContent
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonDeserializer
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
java.io.IOException
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-18:PM4:38
*/
public
class
ContentDeserializer
extends
JsonDeserializer
<
Object
>
{
private
final
ObjectMapper
objectMapper
=
new
ObjectMapper
();
@Override
public
Object
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
JsonNode
node
=
p
.
getCodec
().
readTree
(
p
);
// 判断 content 是 String 还是 List
if
(
node
.
isTextual
())
{
// 解析为字符串(文本请求)
return
node
.
asText
();
}
else
if
(
node
.
isArray
())
{
return
objectMapper
.
readValue
(
node
.
toString
(),
objectMapper
.
getTypeFactory
().
constructCollectionType
(
List
.
class
,
ImageContent
.
class
));
}
return
null
;
}
}
common-llm/src/main/java/com/coolook/common/llm/dto/Choices.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
dto
;
import
lombok.Data
;
/**
* @author: Wang Yinuo
* @create: 2025-03-14:PM2:44
*/
@Data
public
class
Choices
{
private
Message
message
;
private
String
logprobs
;
private
String
finish_reason
;
private
Integer
index
;
}
common-llm/src/main/java/com/coolook/common/llm/dto/Usage.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
dto
;
import
lombok.Data
;
/**
* @author: Wang Yinuo
* @create: 2025-03-14:PM2:42
*/
@Data
public
class
Usage
{
private
int
prompt_tokens
;
private
int
completion_tokens
;
private
int
total_tokens
;
}
common-llm/src/main/java/com/coolook/common/llm/request/OpenAiImageRequest.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
request
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-03:PM3:20
*/
@Data
public
class
OpenAiImageRequest
{
private
String
model
;
private
List
<
ImageMessage
>
messages
;
private
double
temperature
;
@JsonProperty
(
"max_tokens"
)
private
int
maxTokens
;
@JsonProperty
(
"top_p"
)
private
double
topP
;
@JsonProperty
(
"frequency_penalty"
)
private
double
frequencyPenalty
;
@JsonProperty
(
"presence_penalty"
)
private
double
presencePenalty
;
}
common-llm/src/main/java/com/coolook/common/llm/request/TextContent.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
request
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
/**
* @author: Wang Yinuo
* @create: 2025-03-03:PM4:11
*/
@Data
public
class
TextContent
{
public
String
type
;
public
String
text
;
}
common-llm/src/main/java/com/coolook/common/llm/request/base/BaseMessage.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
.
base
;
import
com.coolook.common.llm.constant.ContentDeserializer
;
import
com.fasterxml.jackson.databind.annotation.JsonDeserialize
;
import
lombok.Data
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-18:PM2:26
*/
@Data
public
class
BaseMessage
{
private
String
role
;
@JsonDeserialize
(
using
=
ContentDeserializer
.
class
)
private
Object
content
;
}
common-llm/src/main/java/com/coolook/common/llm/request/base/BaseRequest.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
.
base
;
import
lombok.*
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-18:PM2:23
*/
@Data
public
class
BaseRequest
{
private
String
model
;
private
List
<
BaseMessage
>
messages
;
private
Boolean
stream
;
}
common-llm/src/main/java/com/coolook/common/llm/request/ImageContent.java
→
common-llm/src/main/java/com/coolook/common/llm/request/
image/
ImageContent.java
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
;
package
com
.
coolook
.
common
.
llm
.
request
.
image
;
import
com.fasterxml.jackson.annotation.JsonInclude
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
com.fasterxml.jackson.annotation.JsonSetter
;
import
com.fasterxml.jackson.annotation.Nulls
;
import
lombok.Data
;
/**
...
...
@@ -8,9 +11,11 @@ import lombok.Data;
* @create: 2025-03-03:PM4:11
*/
@Data
@JsonInclude
(
JsonInclude
.
Include
.
NON_NULL
)
public
class
ImageContent
{
public
String
type
;
public
String
text
;
private
String
type
;
private
String
text
;
// 使用自定义的 image_url 类型映射
@JsonProperty
(
"image_url"
)
p
ublic
ImageUrl
imageUrl
;
p
rivate
ImageUrl
imageUrl
;
}
common-llm/src/main/java/com/coolook/common/llm/request/ImageMessage.java
→
common-llm/src/main/java/com/coolook/common/llm/request/
image/
ImageMessage.java
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
;
package
com
.
coolook
.
common
.
llm
.
request
.
image
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.List
;
...
...
@@ -10,6 +13,6 @@ import java.util.List;
*/
@Data
public
class
ImageMessage
{
p
ublic
String
role
;
p
ublic
List
<
ImageContent
>
content
;
p
rivate
String
role
;
p
rivate
List
<
ImageContent
>
content
;
}
common-llm/src/main/java/com/coolook/common/llm/request/image/ImageRequest.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
.
image
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
com.coolook.common.llm.request.base.BaseRequest
;
import
com.coolook.common.llm.request.text.TextMessage
;
import
lombok.*
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-03:PM3:20
*/
@Data
public
class
ImageRequest
{
private
String
model
;
private
List
<
ImageMessage
>
messages
;
private
Boolean
stream
;
}
common-llm/src/main/java/com/coolook/common/llm/request/ImageUrl.java
→
common-llm/src/main/java/com/coolook/common/llm/request/
image/
ImageUrl.java
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
;
package
com
.
coolook
.
common
.
llm
.
request
.
image
;
import
lombok.Data
;
...
...
common-llm/src/main/java/com/coolook/common/llm/request/TextMessage.java
→
common-llm/src/main/java/com/coolook/common/llm/request/
text/
TextMessage.java
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
;
package
com
.
coolook
.
common
.
llm
.
request
.
text
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-03:PM3:21
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public
class
TextMessage
{
public
class
TextMessage
extends
BaseMessage
{
private
String
role
;
//private List<TextContent> content;
private
String
content
;
}
common-llm/src/main/java/com/coolook/common/llm/request/
OpenAi
TextRequest.java
→
common-llm/src/main/java/com/coolook/common/llm/request/
text/
TextRequest.java
View file @
cc2771a5
package
com
.
coolook
.
common
.
llm
.
request
;
package
com
.
coolook
.
common
.
llm
.
request
.
text
;
import
lombok.Data
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
com.coolook.common.llm.request.base.BaseRequest
;
import
lombok.*
;
import
java.io.Serializable
;
import
java.util.List
;
/**
...
...
@@ -11,7 +12,9 @@ import java.util.List;
*/
@Data
public
class
OpenAiTextRequest
implements
Serializable
{
public
class
TextRequest
{
private
String
model
;
private
Boolean
stream
;
private
List
<
TextMessage
>
messages
;
}
common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModel.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
response
;
import
com.coolook.common.llm.constant.CommonStatusEnum
;
import
com.coolook.common.llm.dto.Choices
;
import
com.coolook.common.llm.dto.Usage
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
/**
* @author: WangYinuo
* @create: 2025-01-03:PM1:39
*/
@Data
public
class
ResponseStandardModel
{
private
String
id
;
private
String
object
;
private
Long
created
;
private
String
model
;
private
Usage
usage
;
private
List
<
Choices
>
choices
;
}
common-llm/src/main/java/com/coolook/common/llm/response/ResponseStandardModelError.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
common
.
llm
.
response
;
import
com.coolook.common.llm.dto.Choices
;
import
com.coolook.common.llm.dto.Usage
;
import
lombok.Data
;
import
java.util.List
;
/**
* @author: WangYinuo
* @create: 2025-01-03:PM1:39
*/
@Data
public
class
ResponseStandardModelError
{
private
ErrorDetail
error
;
public
ResponseStandardModelError
(
String
message
,
String
type
,
String
param
,
String
code
)
{
this
.
error
=
new
ErrorDetail
(
message
,
type
,
param
,
code
);
}
public
ErrorDetail
getError
()
{
return
error
;
}
public
static
class
ErrorDetail
{
private
String
message
;
private
String
type
;
private
String
param
;
private
String
code
;
public
ErrorDetail
(
String
message
,
String
type
,
String
param
,
String
code
)
{
this
.
message
=
message
;
this
.
type
=
type
;
this
.
param
=
param
;
this
.
code
=
code
;
}
public
String
getMessage
()
{
return
message
;
}
public
String
getType
()
{
return
type
;
}
public
String
getParam
()
{
return
param
;
}
public
String
getCode
()
{
return
code
;
}
}
}
service-llm/src/main/java/com/coolook/service/llm/controller/
Search
ConfigController.java
→
service-llm/src/main/java/com/coolook/service/llm/controller/ConfigController.java
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
controller
;
import
com.coolook.common.llm.response.ResponseResult
;
import
com.coolook.service.llm.service.
Search
ConfigService
;
import
com.coolook.service.llm.service.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
...
...
@@ -13,10 +13,10 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
public
class
Search
ConfigController
{
public
class
ConfigController
{
@Autowired
private
Search
ConfigService
searchConfigService
;
private
ConfigService
searchConfigService
;
@GetMapping
(
"/get-search-config"
)
public
ResponseResult
getSearchConfig
()
{
...
...
service-llm/src/main/java/com/coolook/service/llm/controller/CustomModelController.java
deleted
100644 → 0
View file @
fc19145a
package
com
.
coolook
.
service
.
llm
.
controller
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.response.ResponseResult
;
import
com.coolook.common.llm.request.ModelsRequest
;
import
com.coolook.common.llm.request.OpenAiImageRequest
;
import
com.coolook.common.llm.request.OpenAiTextRequest
;
import
com.coolook.service.llm.service.ModelService
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-02-21:AM11:30
*/
@Slf4j
@RestController
public
class
CustomModelController
{
@Autowired
private
ModelService
llmService
;
@GetMapping
(
"/v1/models"
)
public
HttpEntity
<
List
<
ModelsDto
>>
getAvailableModelList
()
{
HttpEntity
<
List
<
ModelsDto
>>
textModelList
=
llmService
.
getTextModelList
();
// ResponseResult<List<String>> pictureModelList = llmService.getPictureModelList();
return
textModelList
;
}
@PostMapping
(
"/text/v1/chat/completions"
)
public
ResponseEntity
<?>
chat
(
@RequestBody
OpenAiTextRequest
content
)
throws
JsonProcessingException
{
ResponseEntity
<?>
chat
=
llmService
.
chat
(
content
);
ObjectMapper
objectMapper
=
new
ObjectMapper
();
byte
[]
responseBytes
=
objectMapper
.
writeValueAsBytes
(
chat
.
getBody
());
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentLength
(
responseBytes
.
length
);
return
ResponseEntity
.
ok
()
.
headers
(
headers
)
.
body
(
chat
.
getBody
());
}
@PostMapping
(
"/image/v1/chat/completions"
)
public
ResponseEntity
<?>
picture
(
@RequestBody
OpenAiImageRequest
content
)
{
return
llmService
.
picture
(
content
);
}
@PostMapping
(
"/add-model"
)
public
ResponseResult
addModel
(
@RequestBody
ModelsRequest
[]
content
)
{
return
llmService
.
addModel
(
content
);
}
}
\ No newline at end of file
service-llm/src/main/java/com/coolook/service/llm/controller/ModelController.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
controller
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
com.coolook.common.llm.request.base.BaseRequest
;
import
com.coolook.common.llm.request.image.ImageContent
;
import
com.coolook.common.llm.request.image.ImageMessage
;
import
com.coolook.common.llm.request.image.ImageRequest
;
import
com.coolook.common.llm.request.text.TextMessage
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
com.coolook.service.llm.service.IImageModelService
;
import
com.coolook.service.llm.service.ITextModelService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.servlet.mvc.method.annotation.SseEmitter
;
import
java.lang.reflect.Array
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.stream.Collectors
;
/**
* @author: Wang Yinuo
* @create: 2025-02-21:AM11:30
*/
@Slf4j
@RestController
public
class
ModelController
{
@Autowired
private
ITextModelService
textModelService
;
@Autowired
private
IImageModelService
imageModelService
;
private
final
ExecutorService
executorService
=
Executors
.
newCachedThreadPool
();
@GetMapping
(
"/v1/models"
)
public
ResponseEntity
<?>
getAvailableModelList
()
{
List
textModelList
=
textModelService
.
getTextModelList
();
List
pictureModelList
=
imageModelService
.
getPictureModelList
();
ArrayList
<
Object
>
modelList
=
new
ArrayList
<>();
modelList
.
add
(
textModelList
);
modelList
.
add
(
pictureModelList
);
return
ResponseEntity
.
ok
(
modelList
);
}
@PostMapping
(
"/v1/chat/completions"
)
public
Object
chat
(
@RequestBody
BaseRequest
content
)
{
if
(
content
.
getMessages
().
get
(
0
).
getContent
()
instanceof
String
)
{
TextRequest
textRequest
=
new
TextRequest
();
textRequest
.
setModel
(
content
.
getModel
());
textRequest
.
setStream
(
content
.
getStream
());
List
<
BaseMessage
>
messages
=
content
.
getMessages
();
List
<
TextMessage
>
textMessages
=
messages
.
stream
().
map
(
message
->
{
TextMessage
textMessage
=
new
TextMessage
();
textMessage
.
setRole
(
message
.
getRole
());
textMessage
.
setContent
((
String
)
message
.
getContent
());
return
textMessage
;
}).
collect
(
Collectors
.
toList
());
textRequest
.
setMessages
(
textMessages
);
if
(
Boolean
.
TRUE
.
equals
(
textRequest
.
getStream
()))
{
textRequest
.
setStream
(
false
);
return
chatStream
(
textRequest
);
}
else
{
textRequest
.
setStream
(
false
);
return
textModelService
.
chatAndReturnJson
(
textRequest
);
}
}
else
if
(
content
.
getMessages
().
get
(
0
).
getContent
()
instanceof
List
)
{
ImageRequest
imageRequest
=
new
ImageRequest
();
imageRequest
.
setModel
(
content
.
getModel
());
imageRequest
.
setStream
(
content
.
getStream
());
List
<
BaseMessage
>
messages
=
content
.
getMessages
();
List
<
ImageMessage
>
imageMessages
=
messages
.
stream
().
map
(
message
->
{
ImageMessage
imageMessage
=
new
ImageMessage
();
imageMessage
.
setRole
(
message
.
getRole
());
imageMessage
.
setContent
((
List
<
ImageContent
>)
message
.
getContent
());
return
imageMessage
;
}).
collect
(
Collectors
.
toList
());
imageRequest
.
setMessages
(
imageMessages
);
if
(
Boolean
.
TRUE
.
equals
(
imageRequest
.
getStream
()))
{
imageRequest
.
setStream
(
false
);
return
picStream
(
imageRequest
);
}
else
{
imageRequest
.
setStream
(
false
);
return
imageModelService
.
pictureAndReturnJson
(
imageRequest
);
}
}
return
null
;
}
private
SseEmitter
chatStream
(
TextRequest
content
)
{
JSONObject
chat
=
textModelService
.
chatAndReturnStream
(
content
);
SseEmitter
emitter
=
new
SseEmitter
(
0L
);
executorService
.
submit
(()
->
{
try
{
log
.
info
(
"data: {}"
,
chat
+
"\n\n"
);
emitter
.
send
(
chat
.
toString
());
emitter
.
send
(
"[DONE]\n\n"
);
emitter
.
complete
();
}
catch
(
Exception
e
)
{
emitter
.
completeWithError
(
e
);
}
});
return
emitter
;
}
private
SseEmitter
picStream
(
ImageRequest
content
)
{
JSONObject
pic
=
imageModelService
.
pictureAndReturnStream
(
content
);
SseEmitter
emitter
=
new
SseEmitter
(
0L
);
executorService
.
submit
(()
->
{
try
{
log
.
info
(
"data: {}"
,
pic
+
"\n\n"
);
emitter
.
send
(
pic
.
toString
());
emitter
.
send
(
"[DONE]\n\n"
);
emitter
.
complete
();
}
catch
(
Exception
e
)
{
emitter
.
completeWithError
(
e
);
}
});
return
emitter
;
}
}
\ No newline at end of file
service-llm/src/main/java/com/coolook/service/llm/controller/
DataSync
Controller.java
→
service-llm/src/main/java/com/coolook/service/llm/controller/
ModelManager
Controller.java
View file @
cc2771a5
...
...
@@ -17,7 +17,7 @@ import java.util.List;
@RestController
@Slf4j
public
class
DataSync
Controller
{
public
class
ModelManager
Controller
{
@Autowired
private
ModelDataService
modelDataService
;
...
...
@@ -43,4 +43,9 @@ public class DataSyncController {
log
.
info
(
"updateUrl: {}"
,
urlRequestList
);
return
modelDataService
.
saveOrUpdateUrl
(
urlRequestList
);
}
@PostMapping
(
"/add-model"
)
public
ResponseResult
addModel
(
@RequestBody
ModelsRequest
[]
content
)
{
return
modelDataService
.
addModel
(
content
);
}
}
service-llm/src/main/java/com/coolook/service/llm/remote/LLMClient.java
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
remote
;
import
com.alibaba.fastjson2.JSONArray
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.coolook.common.llm.constant.ModelConstant
;
import
com.coolook.common.llm.dto.Models
;
import
com.coolook.common.llm.request.*
;
import
com.coolook.common.llm.response.ResponseStandardModelError
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.coolook.common.llm.request.base.BaseMessage
;
import
com.coolook.common.llm.request.image.ImageRequest
;
import
com.coolook.common.llm.request.text.TextMessage
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -92,7 +92,7 @@ public class LLMClient {
return
checkedModel
;
}
public
ResponseEntity
<
Map
<
String
,
Object
>>
chat
(
Models
model
,
OpenAi
TextRequest
content
)
{
public
JSONObject
chat
(
Models
model
,
TextRequest
content
)
{
try
{
StringBuilder
sb
=
new
StringBuilder
();
...
...
@@ -108,16 +108,17 @@ public class LLMClient {
List
<
Map
<
String
,
Object
>>
messages
=
new
ArrayList
<>();
for
(
TextMessage
message
:
content
.
getMessages
())
{
for
(
BaseMessage
message
:
content
.
getMessages
())
{
TextMessage
msg
=
(
TextMessage
)
message
;
Map
<
String
,
Object
>
messageMap
=
new
HashMap
<>();
messageMap
.
put
(
"role"
,
message
.
getRole
());
//为实现标准协议
// List<TextContent> contentList = message.getContent();
// messageMap.put("content", contentList);
messageMap
.
put
(
"content"
,
message
.
getContent
());
messageMap
.
put
(
"role"
,
msg
.
getRole
());
messageMap
.
put
(
"content"
,
msg
.
getContent
());
messages
.
add
(
messageMap
);
}
requestBody
.
put
(
"messages"
,
messages
);
requestBody
.
put
(
"stream"
,
content
.
getStream
());
// 使用 Jackson 序列化
ObjectMapper
objectMapper
=
new
ObjectMapper
();
...
...
@@ -128,25 +129,21 @@ public class LLMClient {
ResponseEntity
<
String
>
response
=
restTemplate
.
postForEntity
(
sb
.
toString
(),
requestEntity
,
String
.
class
);
log
.
info
(
"body:{}"
,
response
.
getBody
());
// String responseContent = parseResponseEntity(response.getBody());
// log.info("resp:{}", responseContent);
// return ResponseResult.success(responseContent);
Map
<
String
,
Object
>
responseBody
=
objectMapper
.
readValue
(
response
.
getBody
(),
new
TypeReference
<
Map
<
String
,
Object
>>()
{});
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
response
.
getBody
());
return
ResponseEntity
.
ok
(
responseBody
);
// return ResponseEntity.ok(response.getBody());
return
jsonObject
;
}
catch
(
Exception
e
)
{
Map
<
String
,
Object
>
errorResponse
=
new
HashMap
<>
();
errorResponse
.
put
(
"error"
,
"Exception"
);
errorResponse
.
put
(
"message"
,
e
.
getMessage
()
);
errorResponse
.
put
(
"status"
,
500
);
errorResponse
.
put
(
"model
"
,
content
.
getModel
());
JSONObject
jsonObject
=
new
JSONObject
();
jsonObject
.
put
(
"error"
,
e
.
getMessage
()
);
jsonObject
.
put
(
"code"
,
500
);
jsonObject
.
put
(
"type"
,
"error"
);
jsonObject
.
put
(
"param
"
,
content
.
getModel
());
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
errorResponse
)
;
return
jsonObject
;
}
}
public
ResponseEntity
picture
(
Models
model
,
OpenAiImageRequest
reques
t
)
{
public
JSONObject
picture
(
Models
model
,
ImageRequest
conten
t
)
{
try
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
model
.
getUrl
());
...
...
@@ -155,79 +152,26 @@ public class LLMClient {
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
// 构造请求体
Map
<
String
,
Object
>
requestBody
=
new
HashMap
<>();
requestBody
.
put
(
"model"
,
request
.
getModel
());
requestBody
.
put
(
"temperature"
,
request
.
getTemperature
());
requestBody
.
put
(
"max_tokens"
,
request
.
getMaxTokens
());
requestBody
.
put
(
"top_p"
,
request
.
getTopP
());
requestBody
.
put
(
"frequency_penalty"
,
request
.
getFrequencyPenalty
());
requestBody
.
put
(
"presence_penalty"
,
request
.
getPresencePenalty
());
// 将 "messages" 添加到请求体中
List
<
Map
<
String
,
Object
>>
messages
=
new
ArrayList
<>();
for
(
ImageMessage
msg
:
request
.
getMessages
())
{
Map
<
String
,
Object
>
messageMap
=
new
HashMap
<>();
messageMap
.
put
(
"role"
,
msg
.
role
);
List
<
Map
<
String
,
Object
>>
contentList
=
new
ArrayList
<>();
for
(
ImageContent
content
:
msg
.
content
)
{
Map
<
String
,
Object
>
contentMap
=
new
HashMap
<>();
contentMap
.
put
(
"type"
,
content
.
type
);
if
(
"text"
.
equals
(
content
.
type
))
{
contentMap
.
put
(
"text"
,
content
.
text
);
}
else
if
(
"image_url"
.
equals
(
content
.
type
)
&&
content
.
imageUrl
!=
null
)
{
Map
<
String
,
String
>
imageUrlMap
=
new
HashMap
<>();
imageUrlMap
.
put
(
"url"
,
content
.
imageUrl
.
url
);
contentMap
.
put
(
"image_url"
,
imageUrlMap
);
}
contentList
.
add
(
contentMap
);
}
messageMap
.
put
(
"content"
,
contentList
);
messages
.
add
(
messageMap
);
}
requestBody
.
put
(
"messages"
,
messages
);
// 使用 Jackson 序列化
ObjectMapper
objectMapper
=
new
ObjectMapper
();
String
jsonBody
=
objectMapper
.
writeValueAsString
(
requestBody
);
String
jsonBody
=
objectMapper
.
writeValueAsString
(
content
);
log
.
info
(
"body:{}"
,
jsonBody
);
// 创建 HttpEntity
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonBody
,
headers
);
ResponseEntity
<
String
>
response
=
restTemplate
.
postForEntity
(
sb
.
toString
(),
requestEntity
,
String
.
class
);
// return ResponseResult.success(response);
return
ResponseEntity
.
ok
(
response
.
getBody
());
log
.
info
(
"body:{}"
,
response
.
getBody
());
return
JSONObject
.
parseObject
(
response
.
getBody
());
}
catch
(
Exception
e
)
{
ResponseStandardModelError
error
=
new
ResponseStandardModelError
(
e
.
getMessage
(),
"Exception"
,
request
.
getModel
(),
"500"
);
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
error
);
}
}
JSONObject
jsonObject
=
new
JSONObject
();
jsonObject
.
put
(
"error"
,
e
.
getMessage
());
jsonObject
.
put
(
"code"
,
500
);
jsonObject
.
put
(
"type"
,
"error"
);
jsonObject
.
put
(
"param"
,
content
.
getModel
());
public
String
parseResponseEntity
(
String
responseBody
)
{
JSONObject
jsonObject
=
JSONObject
.
parseObject
(
responseBody
);
try
{
if
(
jsonObject
.
containsKey
(
"choices"
))
{
JSONArray
choices
=
jsonObject
.
getJSONArray
(
"choices"
);
for
(
int
i
=
choices
.
size
()
-
1
;
i
>=
0
;
i
--)
{
JSONObject
obj
=
choices
.
getJSONObject
(
i
);
if
(
obj
.
containsKey
(
"message"
))
{
JSONObject
message
=
obj
.
getJSONObject
(
"message"
);
if
(
message
.
containsKey
(
"role"
)
&&
"assistant"
.
equals
(
message
.
getString
(
"role"
)))
{
if
(
message
.
containsKey
(
"content"
))
{
return
message
.
getString
(
"content"
);
}
}
}
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"parseResponseEntity error:{}"
,
e
.
getMessage
());
return
jsonObject
;
}
return
null
;
}
}
service-llm/src/main/java/com/coolook/service/llm/service/
Search
ConfigService.java
→
service-llm/src/main/java/com/coolook/service/llm/service/ConfigService.java
View file @
cc2771a5
...
...
@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
*/
@Service
public
class
Search
ConfigService
{
public
class
ConfigService
{
@Autowired
private
SearchConfig
searchConfig
;
...
...
service-llm/src/main/java/com/coolook/service/llm/service/IImageModelService.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
service
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.coolook.common.llm.request.image.ImageRequest
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.ResponseEntity
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-18:PM12:00
*/
public
interface
IImageModelService
{
public
List
getPictureModelList
();
public
JSONObject
pictureAndReturnStream
(
ImageRequest
content
);
public
ResponseEntity
pictureAndReturnJson
(
ImageRequest
content
);
}
service-llm/src/main/java/com/coolook/service/llm/service/ITextModelService.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
service
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.ResponseEntity
;
import
java.util.List
;
/**
* @author: Wang Yinuo
* @create: 2025-03-18:PM12:00
*/
public
interface
ITextModelService
{
public
List
getTextModelList
();
public
JSONObject
chatAndReturnStream
(
TextRequest
content
);
public
ResponseEntity
chatAndReturnJson
(
TextRequest
content
);
}
service-llm/src/main/java/com/coolook/service/llm/service/Init
ializer
Service.java
→
service-llm/src/main/java/com/coolook/service/llm/service/Init
Task
Service.java
View file @
cc2771a5
...
...
@@ -32,7 +32,7 @@ import org.springframework.core.task.TaskExecutor;
@Slf4j
@Service
@EnableScheduling
public
class
Init
ializer
Service
{
public
class
Init
Task
Service
{
@Autowired
private
ModelMapper
modelMapper
;
...
...
service-llm/src/main/java/com/coolook/service/llm/service/ModelDataService.java
View file @
cc2771a5
...
...
@@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
@@ -135,4 +136,26 @@ public class ModelDataService {
}
return
ResponseResult
.
success
();
}
public
ResponseResult
addModel
(
ModelsRequest
[]
content
)
{
List
<
Models
>
modelList
=
new
ArrayList
<>();
for
(
ModelsRequest
modelRequest
:
content
)
{
Models
models
=
new
Models
();
models
.
setUrl
(
modelRequest
.
getUrl
());
models
.
setModel
(
modelRequest
.
getModel
());
models
.
setModelType
(
modelRequest
.
getModelType
());
models
.
setIsActive
(
ModelConstant
.
MODEL_IS_NOT_ACTIVE
);
models
.
setCreateAt
(
LocalDateTime
.
now
());
models
.
setLastCheckedAt
(
LocalDateTime
.
now
());
models
.
setSuccessCount
(
0
);
models
.
setFailureCount
(
0
);
models
.
setTotalCount
(
0
);
models
.
setConsecutiveFailure
(
0
);
models
.
setLatestSpeed
(
0L
);
modelList
.
add
(
models
);
}
modelMapper
.
insertModelList
(
modelList
);
return
ResponseResult
.
success
();
}
}
service-llm/src/main/java/com/coolook/service/llm/service/
ModelService
.java
→
service-llm/src/main/java/com/coolook/service/llm/service/
impl/ImageModelServiceImpl
.java
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
service
;
package
com
.
coolook
.
service
.
llm
.
service
.
impl
;
import
com.alibaba.fastjson2.JSONArray
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.coolook.common.llm.constant.CommonStatusEnum
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.response.ResponseStandardModel
;
import
com.coolook.common.llm.response.ResponseStandardModelError
;
import
com.coolook.common.llm.utils.RedisUtil
;
import
com.coolook.common.llm.constant.ModelConstant
;
import
com.coolook.common.llm.dto.Models
;
import
com.coolook.common.llm.response.ResponseResult
;
import
com.coolook.common.llm.request.ModelsRequest
;
import
com.coolook.common.llm.request.OpenAiImageRequest
;
import
com.coolook.common.llm.request.OpenAiTextRequest
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.request.image.ImageRequest
;
import
com.coolook.common.llm.utils.RedisUtil
;
import
com.coolook.service.llm.config.SearchConfig
;
import
com.coolook.service.llm.mapper.ModelMapper
;
import
com.coolook.service.llm.remote.LLMClient
;
import
com.coolook.service.llm.service.IImageModelService
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* @author: Wang Yinuo
* @create: 2025-0
2-21:AM11:20
* @create: 2025-0
3-18:PM12:48
*/
@Service
@Slf4j
public
class
ModelService
{
@Service
public
class
ImageModelServiceImpl
implements
IImageModelService
{
@Autowired
private
LLMClient
llmClient
;
...
...
@@ -61,19 +53,22 @@ public class ModelService {
private
static
Map
<
String
,
Object
>
unavailableModel
=
new
ConcurrentHashMap
<>();
public
HttpEntity
<
List
<
ModelsDto
>>
getTextModelList
()
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_TEXT
);
@Override
public
List
getPictureModelList
()
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_IMAGE
);
List
<
ModelsDto
>
nameList
=
new
ArrayList
<>();
Object
obj
=
redisTemplate
.
opsForValue
().
get
(
redisKey
);
if
(
obj
==
null
)
{
QueryWrapper
<
Models
>
queryWrapper
=
new
QueryWrapper
<>();
queryWrapper
.
eq
(
"model_type"
,
ModelConstant
.
MODEL_TYPE_
TEXT
);
queryWrapper
.
eq
(
"model_type"
,
ModelConstant
.
MODEL_TYPE_
IMAGE
);
queryWrapper
.
eq
(
"is_active"
,
ModelConstant
.
MODEL_IS_ACTIVE
);
queryWrapper
.
last
(
"LIMIT
50
0"
);
queryWrapper
.
last
(
"LIMIT
1
0"
);
List
<
Models
>
list
=
modelMapper
.
selectList
(
queryWrapper
);
log
.
info
(
"redis list:{}"
,
list
);
obj
=
list
;
redisTemplate
.
opsForValue
().
set
(
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_
TEXT
),
list
,
1
,
TimeUnit
.
HOURS
);
redisTemplate
.
opsForValue
().
set
(
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_
IMAGE
),
list
,
1
,
TimeUnit
.
HOURS
);
}
if
(
obj
instanceof
List
<?>)
{
...
...
@@ -108,97 +103,37 @@ public class ModelService {
}
}
}
return
ResponseEntity
.
ok
(
nameList
)
;
return
nameList
;
}
public
ResponseResult
<
List
<
String
>>
getPictureModelList
()
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_IMAGE
);
List
<
String
>
nameList
=
new
ArrayList
<>();
Object
obj
=
redisTemplate
.
opsForValue
().
get
(
redisKey
);
if
(
obj
==
null
)
{
QueryWrapper
<
Models
>
queryWrapper
=
new
QueryWrapper
<>();
queryWrapper
.
eq
(
"model_type"
,
ModelConstant
.
MODEL_TYPE_IMAGE
);
queryWrapper
.
eq
(
"is_active"
,
ModelConstant
.
MODEL_IS_ACTIVE
);
queryWrapper
.
last
(
"LIMIT 10"
);
List
<
Models
>
list
=
modelMapper
.
selectList
(
queryWrapper
);
log
.
info
(
"redis list:{}"
,
list
);
obj
=
list
;
redisTemplate
.
opsForValue
().
set
(
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_IMAGE
),
list
,
1
,
TimeUnit
.
HOURS
);
}
if
(
obj
instanceof
List
<?>)
{
List
<?>
rawList
=
(
List
<?>)
obj
;
List
<
Models
>
modelList
=
rawList
.
stream
()
.
map
(
item
->
objectMapper
.
convertValue
(
item
,
Models
.
class
))
.
collect
(
Collectors
.
toList
());
for
(
Models
model
:
modelList
)
{
String
modelName
=
model
.
getModel
();
if
(!
nameList
.
contains
(
modelName
))
{
nameList
.
add
(
modelName
);
@Override
public
JSONObject
pictureAndReturnStream
(
ImageRequest
content
)
{
JSONObject
picture
=
picture
(
content
);
if
(
picture
!=
null
&&
!
picture
.
containsKey
(
"error"
))
{
JSONArray
choicesArray
=
picture
.
getJSONArray
(
"choices"
);
for
(
int
i
=
0
;
i
<
choicesArray
.
size
();
i
++)
{
JSONObject
choiceObj
=
choicesArray
.
getJSONObject
(
i
);
if
(
choiceObj
.
containsKey
(
"message"
))
{
// 将 message 取出
JSONObject
messageNode
=
choiceObj
.
getJSONObject
(
"message"
);
// 强制转换为 ObjectNode,以便修改
choiceObj
.
remove
(
"message"
);
choiceObj
.
put
(
"delta"
,
messageNode
);
}
}
}
return
ResponseResult
.
success
(
nameList
)
;
return
picture
;
}
public
ResponseEntity
<?>
chat
(
OpenAiTextRequest
content
)
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_TEXT
);
String
modelFullName
=
content
.
getModel
();
String
modelName
=
modelFullName
.
split
(
":"
)[
0
];
Object
obj
=
redisTemplate
.
opsForValue
().
get
(
redisKey
);
if
(
obj
instanceof
List
<?>)
{
List
<?>
rawList
=
(
List
<?>)
obj
;
List
<
Models
>
modelList
=
rawList
.
stream
()
.
map
(
item
->
objectMapper
.
convertValue
(
item
,
Models
.
class
))
.
collect
(
Collectors
.
toList
());
for
(
Models
model
:
modelList
)
{
String
name
=
model
.
getModel
().
trim
();
Boolean
flag
=
false
;
// 根据名字寻找合适的模型
if
(
name
.
equals
(
modelName
))
{
flag
=
true
;
}
else
if
(
searchConfig
.
getValue
())
{
if
(
name
.
contains
(
modelName
))
{
flag
=
true
;
}
}
else
{
flag
=
true
;
}
if
(
flag
)
{
if
(
unavailableModel
.
putIfAbsent
(
model
.
getUrl
()
+
model
.
getModel
(),
true
)
==
null
)
{
return
updateAndSendRequestChat
(
model
,
content
);
}
}
}
}
Map
<
String
,
String
>
errorResponse
=
new
HashMap
<>();
errorResponse
.
put
(
"error"
,
"error"
);
errorResponse
.
put
(
"message"
,
"model not found"
);
errorResponse
.
put
(
"status"
,
"500"
);
errorResponse
.
put
(
"model"
,
content
.
getModel
());
// 将错误响应转换为 JSON 字符串并返回
ObjectMapper
objectMapper
=
new
ObjectMapper
();
try
{
String
errorJson
=
objectMapper
.
writeValueAsString
(
errorResponse
);
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
errorJson
);
}
catch
(
Exception
e
)
{
// 如果序列化失败,返回通用错误消息
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
)
.
body
(
"{\"error\": \"Serialization error\",\"message\": \"Unable to process error response\"}"
);
}
@Override
public
ResponseEntity
pictureAndReturnJson
(
ImageRequest
content
)
{
JSONObject
picture
=
picture
(
content
);
return
ResponseEntity
.
ok
(
picture
);
}
public
ResponseEntity
<?>
picture
(
OpenAi
ImageRequest
content
)
{
public
JSONObject
picture
(
ImageRequest
content
)
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_IMAGE
);
String
modelFullName
=
content
.
getModel
();
String
modelName
=
modelFullName
.
split
(
":"
)[
0
];
...
...
@@ -232,26 +167,15 @@ public class ModelService {
}
}
}
ResponseStandardModelError
error
=
new
ResponseStandardModelError
(
"model:"
+
content
.
getModel
()
+
"not found"
,
"model not found"
,
content
.
getModel
(),
"500"
);
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
error
);
JSONObject
errorJson
=
new
JSONObject
();
errorJson
.
put
(
"error"
,
"error"
);
errorJson
.
put
(
"message"
,
"model not found"
);
errorJson
.
put
(
"code"
,
"500"
);
errorJson
.
put
(
"model"
,
content
.
getModel
());
return
errorJson
;
}
public
ResponseEntity
updateAndSendRequestChat
(
Models
model
,
OpenAiTextRequest
content
)
{
String
key
=
model
.
getUrl
()
+
model
.
getModel
();
log
.
info
(
"updateAndSendRequestChat, modelName;{}"
,
key
);
try
{
return
llmClient
.
chat
(
model
,
content
);
}
finally
{
unavailableModel
.
remove
(
key
);
}
}
public
ResponseEntity
updateAndSendRequestPic
(
Models
model
,
OpenAiImageRequest
content
)
{
public
JSONObject
updateAndSendRequestPic
(
Models
model
,
ImageRequest
content
)
{
String
key
=
model
.
getUrl
()
+
model
.
getModel
();
log
.
info
(
"updateAndSendRequestPic, modelName;{}"
,
key
);
try
{
...
...
@@ -260,28 +184,4 @@ public class ModelService {
unavailableModel
.
remove
(
key
);
}
}
public
ResponseResult
addModel
(
ModelsRequest
[]
content
)
{
List
<
Models
>
modelList
=
new
ArrayList
<>();
for
(
ModelsRequest
modelRequest
:
content
)
{
Models
models
=
new
Models
();
models
.
setUrl
(
modelRequest
.
getUrl
());
models
.
setModel
(
modelRequest
.
getModel
());
models
.
setModelType
(
modelRequest
.
getModelType
());
models
.
setIsActive
(
ModelConstant
.
MODEL_IS_NOT_ACTIVE
);
models
.
setCreateAt
(
LocalDateTime
.
now
());
models
.
setLastCheckedAt
(
LocalDateTime
.
now
());
models
.
setSuccessCount
(
0
);
models
.
setFailureCount
(
0
);
models
.
setTotalCount
(
0
);
models
.
setConsecutiveFailure
(
0
);
models
.
setLatestSpeed
(
0L
);
modelList
.
add
(
models
);
}
modelMapper
.
insertModelList
(
modelList
);
return
ResponseResult
.
success
();
}
}
service-llm/src/main/java/com/coolook/service/llm/service/impl/TextModelServiceImpl.java
0 → 100644
View file @
cc2771a5
package
com
.
coolook
.
service
.
llm
.
service
.
impl
;
import
com.alibaba.fastjson2.JSONArray
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.coolook.common.llm.dto.ModelsDto
;
import
com.coolook.common.llm.request.text.TextRequest
;
import
com.coolook.common.llm.utils.RedisUtil
;
import
com.coolook.common.llm.constant.ModelConstant
;
import
com.coolook.common.llm.dto.Models
;
import
com.coolook.service.llm.config.SearchConfig
;
import
com.coolook.service.llm.mapper.ModelMapper
;
import
com.coolook.service.llm.remote.LLMClient
;
import
com.coolook.service.llm.service.ITextModelService
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
java.time.ZoneId
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* @author: Wang Yinuo
* @create: 2025-02-21:AM11:20
*/
@Service
@Slf4j
public
class
TextModelServiceImpl
implements
ITextModelService
{
@Autowired
private
LLMClient
llmClient
;
@Autowired
private
RedisTemplate
redisTemplate
;
@Autowired
private
ObjectMapper
objectMapper
;
@Autowired
private
ModelMapper
modelMapper
;
@Autowired
private
SearchConfig
searchConfig
;
private
static
Map
<
String
,
Object
>
unavailableModel
=
new
ConcurrentHashMap
<>();
@Override
public
List
getTextModelList
()
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_TEXT
);
List
<
ModelsDto
>
nameList
=
new
ArrayList
<>();
Object
obj
=
redisTemplate
.
opsForValue
().
get
(
redisKey
);
if
(
obj
==
null
)
{
QueryWrapper
<
Models
>
queryWrapper
=
new
QueryWrapper
<>();
queryWrapper
.
eq
(
"model_type"
,
ModelConstant
.
MODEL_TYPE_TEXT
);
queryWrapper
.
eq
(
"is_active"
,
ModelConstant
.
MODEL_IS_ACTIVE
);
queryWrapper
.
last
(
"LIMIT 500"
);
List
<
Models
>
list
=
modelMapper
.
selectList
(
queryWrapper
);
obj
=
list
;
redisTemplate
.
opsForValue
().
set
(
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_TEXT
),
list
,
1
,
TimeUnit
.
HOURS
);
}
if
(
obj
instanceof
List
<?>)
{
List
<?>
rawList
=
(
List
<?>)
obj
;
List
<
Models
>
modelList
=
rawList
.
stream
()
.
map
(
item
->
objectMapper
.
convertValue
(
item
,
Models
.
class
))
.
collect
(
Collectors
.
toList
());
for
(
Models
model
:
modelList
)
{
String
modelName
=
model
.
getModel
();
String
[]
modelInfo
=
modelName
.
split
(
":"
);
String
modelType
=
null
;
String
modelVersion
=
null
;
if
(
modelInfo
.
length
>
1
)
{
modelType
=
modelInfo
[
0
];
modelVersion
=
modelInfo
[
1
];
}
else
{
modelType
=
modelName
;
}
if
(
modelVersion
==
null
||
modelVersion
.
contains
(
"-"
)
||
modelVersion
.
contains
(
"_"
))
{
modelVersion
=
""
;
}
modelName
=
modelType
+
":"
+
modelVersion
;
ModelsDto
modelDto
=
new
ModelsDto
();
modelDto
.
setId
(
modelName
);
modelDto
.
setCreated
(
model
.
getCreateAt
().
atZone
(
ZoneId
.
of
(
"UTC"
)).
toInstant
().
toEpochMilli
());
if
(!
nameList
.
stream
().
anyMatch
(
p
->
p
.
getId
().
equals
(
modelDto
.
getId
())))
{
nameList
.
add
(
modelDto
);
}
}
}
return
nameList
;
}
@Override
public
JSONObject
chatAndReturnStream
(
TextRequest
content
)
{
JSONObject
chat
=
chat
(
content
);
if
(
chat
!=
null
&&
!
chat
.
containsKey
(
"error"
))
{
JSONArray
choicesArray
=
chat
.
getJSONArray
(
"choices"
);
for
(
int
i
=
0
;
i
<
choicesArray
.
size
();
i
++)
{
JSONObject
choiceObj
=
choicesArray
.
getJSONObject
(
i
);
if
(
choiceObj
.
containsKey
(
"message"
))
{
// 将 message 取出
JSONObject
messageNode
=
choiceObj
.
getJSONObject
(
"message"
);
// 强制转换为 ObjectNode,以便修改
choiceObj
.
remove
(
"message"
);
choiceObj
.
put
(
"delta"
,
messageNode
);
}
}
}
return
chat
;
}
@Override
public
ResponseEntity
chatAndReturnJson
(
TextRequest
content
)
{
JSONObject
chat
=
chat
(
content
);
return
ResponseEntity
.
ok
(
chat
);
}
public
JSONObject
chat
(
TextRequest
content
)
{
String
redisKey
=
RedisUtil
.
getRedisKey
(
ModelConstant
.
MODEL_TYPE_TEXT
);
String
modelFullName
=
content
.
getModel
();
String
modelName
=
modelFullName
.
split
(
":"
)[
0
];
Object
obj
=
redisTemplate
.
opsForValue
().
get
(
redisKey
);
if
(
obj
instanceof
List
<?>)
{
List
<?>
rawList
=
(
List
<?>)
obj
;
List
<
Models
>
modelList
=
rawList
.
stream
()
.
map
(
item
->
objectMapper
.
convertValue
(
item
,
Models
.
class
))
.
collect
(
Collectors
.
toList
());
for
(
Models
model
:
modelList
)
{
String
name
=
model
.
getModel
().
trim
();
Boolean
flag
=
false
;
// 根据名字寻找合适的模型
if
(
name
.
equals
(
modelName
))
{
flag
=
true
;
}
else
if
(
searchConfig
.
getValue
())
{
if
(
name
.
contains
(
modelName
))
{
flag
=
true
;
}
}
else
{
flag
=
true
;
}
if
(
flag
)
{
if
(
unavailableModel
.
putIfAbsent
(
model
.
getUrl
()
+
model
.
getModel
(),
true
)
==
null
)
{
return
updateAndSendRequestChat
(
model
,
content
);
}
}
}
}
JSONObject
errorJson
=
new
JSONObject
();
errorJson
.
put
(
"error"
,
"error"
);
errorJson
.
put
(
"message"
,
"model not found"
);
errorJson
.
put
(
"code"
,
"500"
);
errorJson
.
put
(
"model"
,
content
.
getModel
());
return
errorJson
;
}
public
JSONObject
updateAndSendRequestChat
(
Models
model
,
TextRequest
content
)
{
String
key
=
model
.
getUrl
()
+
model
.
getModel
();
log
.
info
(
"updateAndSendRequestChat, modelName;{}"
,
key
);
try
{
return
llmClient
.
chat
(
model
,
content
);
}
finally
{
unavailableModel
.
remove
(
key
);
}
}
}
service-llm/src/main/resources/application-global.yml
deleted
100644 → 0
View file @
fc19145a
spring
:
cloud
:
nacos
:
discovery
:
server-addr
:
132.145.115.85:8848
datasource
:
type
:
com.alibaba.druid.pool.DruidDataSource
druid
:
driver-class-name
:
com.mysql.cj.jdbc.Driver
url
:
jdbc:mysql://10.0.20.195:3306/service_llm?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username
:
root
password
:
zwjt123.com
redis
:
host
:
aaaawxqy5yamgkqc5lii6wutfmzocximcbesvikrwqxn6p4i4drafka-p.redis.ap-tokyo-1.oci.oraclecloud.com
port
:
6379
database
:
8
cache
:
type
:
redis
service-llm/src/main/resources/application.yml
View file @
cc2771a5
...
...
@@ -2,7 +2,6 @@
server
:
port
:
8700
spring
:
application
:
name
:
service-llm
...
...
@@ -11,7 +10,6 @@ spring:
profiles
:
active
:
local
search
:
config
:
value
:
false
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