feat: Add image support for Claude, OpenAI and Google (#268)

* feat: Add image support for Claude
* feat: Add images support for OpenAI
* feat: Add support images for google ai
* refactor: Separate ImageComponent
* feat: Add attach image button
* feat: Add support image for Mistral provider
* feat: Add support images for OpenAI compatible providers
* feat: Add support images for Ollama
This commit is contained in:
Petr Mironychev
2025-11-20 15:49:39 +01:00
committed by GitHub
parent ce9e2717d6
commit 55b6080273
41 changed files with 860 additions and 93 deletions

View File

@ -39,6 +39,24 @@ void ClaudeMessage::handleContentBlockStart(
if (blockType == "text") {
addCurrentContent<LLMCore::TextContent>();
} else if (blockType == "image") {
QJsonObject source = data["source"].toObject();
QString sourceType = source["type"].toString();
QString imageData;
QString mediaType;
LLMCore::ImageContent::ImageSourceType imgSourceType = LLMCore::ImageContent::ImageSourceType::Base64;
if (sourceType == "base64") {
imageData = source["data"].toString();
mediaType = source["media_type"].toString();
imgSourceType = LLMCore::ImageContent::ImageSourceType::Base64;
} else if (sourceType == "url") {
imageData = source["url"].toString();
imgSourceType = LLMCore::ImageContent::ImageSourceType::Url;
}
addCurrentContent<LLMCore::ImageContent>(imageData, mediaType, imgSourceType);
} else if (blockType == "tool_use") {
QString toolId = data["id"].toString();
QString toolName = data["name"].toString();

View File

@ -257,6 +257,10 @@ bool ClaudeProvider::supportThinking() const {
return true;
};
bool ClaudeProvider::supportImage() const {
return true;
};
void ClaudeProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("ClaudeProvider: Cancelling request %1").arg(requestId));

View File

@ -55,6 +55,7 @@ public:
bool supportsTools() const override;
bool supportThinking() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -273,6 +273,11 @@ bool GoogleAIProvider::supportThinking() const
return true;
}
bool GoogleAIProvider::supportImage() const
{
return true;
}
void GoogleAIProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("GoogleAIProvider: Cancelling request %1").arg(requestId));

View File

@ -54,6 +54,7 @@ public:
bool supportsTools() const override;
bool supportThinking() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -163,6 +163,11 @@ bool LMStudioProvider::supportsTools() const
return true;
}
bool LMStudioProvider::supportImage() const
{
return true;
}
void LMStudioProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("LMStudioProvider: Cancelling request %1").arg(requestId));

View File

@ -53,6 +53,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -206,6 +206,11 @@ bool LlamaCppProvider::supportsTools() const
return true;
}
bool LlamaCppProvider::supportImage() const
{
return true;
}
void LlamaCppProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("LlamaCppProvider: Cancelling request %1").arg(requestId));

View File

@ -53,6 +53,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -184,6 +184,11 @@ bool MistralAIProvider::supportsTools() const
return true;
}
bool MistralAIProvider::supportImage() const
{
return true;
}
void MistralAIProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("MistralAIProvider: Cancelling request %1").arg(requestId));

View File

@ -53,6 +53,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -168,6 +168,7 @@ QList<QString> OllamaProvider::validateRequest(const QJsonObject &request, LLMCo
{"prompt", {}},
{"suffix", {}},
{"system", {}},
{"images", QJsonArray{}},
{"options",
QJsonObject{
{"temperature", {}},
@ -182,7 +183,7 @@ QList<QString> OllamaProvider::validateRequest(const QJsonObject &request, LLMCo
{"keep_alive", {}},
{"model", {}},
{"stream", {}},
{"messages", QJsonArray{{QJsonObject{{"role", {}}, {"content", {}}}}}},
{"messages", QJsonArray{{QJsonObject{{"role", {}}, {"content", {}}, {"images", QJsonArray{}}}}}},
{"tools", QJsonArray{}},
{"options",
QJsonObject{
@ -241,6 +242,11 @@ bool OllamaProvider::supportsTools() const
return true;
}
bool OllamaProvider::supportImage() const
{
return true;
}
void OllamaProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("OllamaProvider: Cancelling request %1").arg(requestId));

View File

@ -54,6 +54,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -192,6 +192,11 @@ bool OpenAICompatProvider::supportsTools() const
return true;
}
bool OpenAICompatProvider::supportImage() const
{
return true;
}
void OpenAICompatProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("OpenAICompatProvider: Cancelling request %1").arg(requestId));

View File

@ -53,6 +53,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots:

View File

@ -248,6 +248,11 @@ bool OpenAIProvider::supportsTools() const
return true;
}
bool OpenAIProvider::supportImage() const
{
return true;
}
void OpenAIProvider::cancelRequest(const LLMCore::RequestID &requestId)
{
LOG_MESSAGE(QString("OpenAIProvider: Cancelling request %1").arg(requestId));

View File

@ -53,6 +53,7 @@ public:
const LLMCore::RequestID &requestId, const QUrl &url, const QJsonObject &payload) override;
bool supportsTools() const override;
bool supportImage() const override;
void cancelRequest(const LLMCore::RequestID &requestId) override;
public slots: