Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [AI] support adding extend LLM #1021

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ project(duc-base)
FILE(GLOB_RECURSE PROJECT_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*/*.cpp"
)

add_library(
Expand Down
11 changes: 11 additions & 0 deletions src/base/ai/abstractllm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "abstractllm.h"

AbstractLLM::AbstractLLM(QObject *parent)
: QObject(parent)
{
qRegisterMetaType<ResponseState>("ResponseState");
}
45 changes: 45 additions & 0 deletions src/base/ai/abstractllm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef ABSTRACTLLM_H
#define ABSTRACTLLM_H

#include "conversation.h"

#include <QObject>
#include <QNetworkReply>

class AbstractLLM : public QObject
{
Q_OBJECT
public:
enum ResponseState {
Receiving,
Success,
CutByLength,
Failed,
Canceled
};

explicit AbstractLLM(QObject *parent = nullptr);
virtual ~AbstractLLM() {}

virtual QString modelPath() const = 0;
virtual bool checkValid(QString *errStr) = 0;
virtual QJsonObject create(const Conversation &conversation) = 0;
virtual void request(const QJsonObject &data) = 0;
virtual void request(const QString &prompt) = 0;
virtual void generate(const QString &prompt, const QString &suffix) = 0;
virtual void setTemperature(double temperature) = 0;
virtual void setStream(bool isStream) = 0;
virtual void processResponse(QNetworkReply *reply) = 0;
virtual void cancel() = 0;
virtual void setMaxTokens(int maxToken) = 0;
virtual Conversation *getCurrentConversation() = 0;

signals:
void dataReceived(const QString &data, ResponseState statu);
};

#endif
149 changes: 149 additions & 0 deletions src/base/ai/conversation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "conversation.h"

#include <QJsonDocument>
#include <QVariant>

Conversation::Conversation()
{
}

Conversation::~Conversation()
{
}

QString Conversation::conversationLastUserData(const QString &conversation)

Check warning on line 18 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'conversationLastUserData' is never used.

Check warning on line 18 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'conversationLastUserData' is never used.
{
const QJsonArray &array = QJsonDocument::fromJson(conversation.toUtf8()).array();
if (!array.isEmpty() && array.last()["role"] == "user") {
return array.last()["content"].toString();
}

return conversation;
}

bool Conversation::setSystemData(const QString &data)
{
if (!data.isEmpty()) {
for (auto iter = conversation.begin(); iter != conversation.end(); iter++) {
if (iter->toObject().value("role").toString() == "system")
return false;
}
conversation.insert(0, QJsonObject({ { "role", "system" }, {"content", data} }));
return true;
}
return false;
}

bool Conversation::popSystemData()

Check warning on line 41 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'popSystemData' is never used.

Check warning on line 41 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'popSystemData' is never used.
{
if (!conversation.isEmpty() && conversation.at(0)["role"].toString() == "system") {
conversation.removeFirst();
return true;
}
return false;
}

bool Conversation::addUserData(const QString &data)
{
if (!data.isEmpty()) {
const QJsonDocument &document = QJsonDocument::fromJson(data.toUtf8());
if (document.isArray()) {
conversation = document.array();
} else {
conversation.push_back(QJsonObject({ { "role", "user" }, {"content", data} }));
}
return true;
}
return false;
}

bool Conversation::popUserData()

Check warning on line 64 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'popUserData' is never used.

Check warning on line 64 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'popUserData' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "user") {
conversation.removeLast();
return true;
}
return false;
}

QString Conversation::getLastResponse() const

Check warning on line 73 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getLastResponse' is never used.

Check warning on line 73 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'getLastResponse' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "assistant") {
return conversation.last()["content"].toString();
}
return QString();
}

QByteArray Conversation::getLastByteResponse() const

Check warning on line 81 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getLastByteResponse' is never used.

Check warning on line 81 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'getLastByteResponse' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "assistant") {
return conversation.last()["content"].toVariant().toByteArray();
}
return QByteArray();
}

bool Conversation::popLastResponse()

Check warning on line 89 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'popLastResponse' is never used.

Check warning on line 89 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'popLastResponse' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "assistant") {
conversation.removeLast();
return true;
}
return false;
}

QJsonObject Conversation::getLastTools() const

Check warning on line 98 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getLastTools' is never used.

Check warning on line 98 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'getLastTools' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "tools") {
return conversation.last()["content"].toObject();
}

return QJsonObject();
}

bool Conversation::popLastTools()

Check warning on line 107 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'popLastTools' is never used.

Check warning on line 107 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'popLastTools' is never used.
{
if (!conversation.isEmpty() && conversation.last()["role"].toString() == "tools") {
conversation.removeLast();
return true;
}
return false;
}

bool Conversation::setFunctions(const QJsonArray &functions)
{
this->functions = functions;
return true;
}

QJsonArray Conversation::getConversions() const
{
return conversation;
}

QJsonArray Conversation::getFunctions() const

Check warning on line 127 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getFunctions' is never used.

Check warning on line 127 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'getFunctions' is never used.
{
return functions;
}

QJsonArray Conversation::getFunctionTools() const

Check warning on line 132 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'getFunctionTools' is never used.

Check warning on line 132 in src/base/ai/conversation.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'getFunctionTools' is never used.
{
QJsonArray tools;
for (const QJsonValue &fun : functions) {
QJsonObject tool;
tool["type"] = "function";
tool["function"] = fun;
tools << tool;
}

return tools;
}

void Conversation::clear()
{
conversation = QJsonArray();
functions = QJsonArray();
}
50 changes: 50 additions & 0 deletions src/base/ai/conversation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef CONVERSATION_H
#define CONVERSATION_H

#include <QJsonObject>
#include <QJsonArray>

class Conversation
{
public:
Conversation();
virtual ~Conversation();

/**
* @brief conversationLastUserData
* @param conversation
* @return
*/
static QString conversationLastUserData(const QString &conversation);

public:
bool setSystemData(const QString &data);
bool popSystemData();

bool addUserData(const QString &data);
bool popUserData();

QString getLastResponse() const;
QByteArray getLastByteResponse() const;
bool popLastResponse();

QJsonObject getLastTools() const;
bool popLastTools();

bool setFunctions(const QJsonArray &functions);
QJsonArray getFunctions() const;
QJsonArray getFunctionTools() const;

QJsonArray getConversions() const;

void clear();
protected:
QJsonArray conversation;
QJsonArray functions;
};

#endif // CONVERSATION_H
1 change: 1 addition & 0 deletions src/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ add_subdirectory(commandproxy)
add_subdirectory(codegeex)
add_subdirectory(git)
add_subdirectory(linglong)
add_subdirectory(aimanager)
54 changes: 54 additions & 0 deletions src/plugins/aimanager/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.0.2)

set(CMAKE_CXX_STANDARD 17)

project(aimanager)

find_package(duc-base REQUIRED)
find_package(duc-common REQUIRED)
find_package(duc-framework REQUIRED)
find_package(duc-services REQUIRED)
find_package(Dtk COMPONENTS Widget REQUIRED)

set(QtFindModules Core Gui Widgets Concurrent)
foreach(QtModule ${QtFindModules})
find_package(Qt5 COMPONENTS ${QtModule} REQUIRED)
# include qt module private include directors
include_directories(${Qt5${QtModule}_PRIVATE_INCLUDE_DIRS})
# can use target_link_libraries(xxx ${QtUseModules})
list(APPEND QtUseModules "Qt5::${QtModule}")
message("QtModule found ${QtModule} OK!")
endforeach()

FILE(GLOB CODEGEEX_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*.json"
)

add_library(${PROJECT_NAME}
SHARED
${CODEGEEX_FILES}
aimanager.qrc
)

target_link_libraries(${PROJECT_NAME}
duc-framework
duc-base
duc-services
duc-common
${QtUseModules}
${PkgUserModules}
${DtkWidget_LIBRARIES}
)


if(NOT PLUGIN_INSTALL_PATH)
set(PLUGIN_INSTALL_PATH "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/deepin-unioncode/plugins")
endif()

install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})


Loading
Loading