Compare commits

...

8 Commits

Author SHA1 Message Date
crazywoola
d919609059 feat: add zh-Hans 2025-01-08 17:48:56 +08:00
Boris Feld
a881ddd101 Use workflow_run_id as workflow trace ID or message_id if present 2025-01-08 09:42:54 +01:00
Boris Feld
6b79e17eea Remove console.log line 2025-01-08 09:42:54 +01:00
Boris Feld
aa25ec870f Fix spacing between providers in config popup 2025-01-08 09:42:54 +01:00
Boris Feld
a16be9ccb2 Add validation and proper default for Opik URL
Also add better documentation link for Opik configuration in the UI
2025-01-08 09:42:54 +01:00
Boris Feld
e87865be80 Add new dependency at the right place 2025-01-08 09:42:54 +01:00
Boris Feld
8a81e5f2c8 Lint fixes 2025-01-08 09:42:54 +01:00
Boris Feld
9d4890506d Add new integration with Opik Tracking tool 2025-01-08 09:42:50 +01:00
23 changed files with 2383 additions and 1014 deletions

View File

@ -6,6 +6,7 @@ from pydantic import BaseModel, ValidationInfo, field_validator
class TracingProviderEnum(Enum):
LANGFUSE = "langfuse"
LANGSMITH = "langsmith"
OPIK = "opik"
class BaseTracingConfig(BaseModel):
@ -56,5 +57,36 @@ class LangSmithConfig(BaseTracingConfig):
return v
class OpikConfig(BaseTracingConfig):
"""
Model class for Opik tracing config.
"""
api_key: str | None = None
project: str | None = None
workspace: str | None = None
url: str = "https://www.comet.com/opik/api/"
@field_validator("project")
@classmethod
def project_validator(cls, v, info: ValidationInfo):
if v is None or v == "":
v = "Default Project"
return v
@field_validator("url")
@classmethod
def url_validator(cls, v, info: ValidationInfo):
if v is None or v == "":
v = "https://www.comet.com/opik/api/"
if not v.startswith(("https://", "http://")):
raise ValueError("url must start with https:// or http://")
if not v.endswith("/api/"):
raise ValueError("url should ends with /api/")
return v
OPS_FILE_PATH = "ops_trace/"
OPS_TRACE_FAILED_KEY = "FAILED_OPS_TRACE"

View File

View File

@ -0,0 +1,435 @@
import json
import logging
import os
from datetime import datetime, timedelta
from opik import Opik, Trace
from opik.id_helpers import uuid4_to_uuid7
from core.ops.base_trace_instance import BaseTraceInstance
from core.ops.entities.config_entity import OpikConfig
from core.ops.entities.trace_entity import (
BaseTraceInfo,
DatasetRetrievalTraceInfo,
GenerateNameTraceInfo,
MessageTraceInfo,
ModerationTraceInfo,
SuggestedQuestionTraceInfo,
ToolTraceInfo,
TraceTaskName,
WorkflowTraceInfo,
)
from extensions.ext_database import db
from models.model import EndUser, MessageFile
from models.workflow import WorkflowNodeExecution
logger = logging.getLogger(__name__)
def wrap_dict(key_name, data):
"""Make sure that the input data is a dict"""
if not isinstance(data, dict):
return {key_name: data}
return data
def wrap_metadata(metadata, **kwargs):
"""Add common metatada to all Traces and Spans"""
metadata["created_from"] = "dify"
metadata.update(kwargs)
return metadata
class OpikDataTrace(BaseTraceInstance):
def __init__(
self,
opik_config: OpikConfig,
):
super().__init__(opik_config)
self.opik_client = Opik(
project_name=opik_config.project,
workspace=opik_config.workspace,
host=opik_config.url,
api_key=opik_config.api_key,
)
self.project = opik_config.project
self.file_base_url = os.getenv("FILES_URL", "http://127.0.0.1:5001")
def trace(self, trace_info: BaseTraceInfo):
if isinstance(trace_info, WorkflowTraceInfo):
self.workflow_trace(trace_info)
if isinstance(trace_info, MessageTraceInfo):
self.message_trace(trace_info)
if isinstance(trace_info, ModerationTraceInfo):
self.moderation_trace(trace_info)
if isinstance(trace_info, SuggestedQuestionTraceInfo):
self.suggested_question_trace(trace_info)
if isinstance(trace_info, DatasetRetrievalTraceInfo):
self.dataset_retrieval_trace(trace_info)
if isinstance(trace_info, ToolTraceInfo):
self.tool_trace(trace_info)
if isinstance(trace_info, GenerateNameTraceInfo):
self.generate_name_trace(trace_info)
def workflow_trace(self, trace_info: WorkflowTraceInfo):
dify_trace_id = trace_info.workflow_run_id
opik_trace_id = uuid4_to_uuid7(trace_info.start_time, dify_trace_id)
workflow_metadata = wrap_metadata(
trace_info.metadata, message_id=trace_info.message_id, workflow_app_log_id=trace_info.workflow_app_log_id
)
root_span_id = None
if trace_info.message_id:
dify_trace_id = trace_info.message_id
opik_trace_id = uuid4_to_uuid7(trace_info.start_time, dify_trace_id)
trace_data = {
"id": opik_trace_id,
"name": TraceTaskName.MESSAGE_TRACE.value,
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": workflow_metadata,
"input": wrap_dict("input", trace_info.workflow_run_inputs),
"output": wrap_dict("output", trace_info.workflow_run_outputs),
"tags": ["message", "workflow"],
"project_name": self.project,
}
self.add_trace(trace_data)
root_span_id = uuid4_to_uuid7(trace_info.start_time, trace_info.workflow_run_id)
span_data = {
"id": root_span_id,
"parent_span_id": None,
"trace_id": opik_trace_id,
"name": TraceTaskName.WORKFLOW_TRACE.value,
"input": wrap_dict("input", trace_info.workflow_run_inputs),
"output": wrap_dict("output", trace_info.workflow_run_outputs),
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": workflow_metadata,
"tags": ["workflow"],
"project_name": self.project,
}
self.add_span(span_data)
else:
trace_data = {
"id": opik_trace_id,
"name": TraceTaskName.MESSAGE_TRACE.value,
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": workflow_metadata,
"input": wrap_dict("input", trace_info.workflow_run_inputs),
"output": wrap_dict("output", trace_info.workflow_run_outputs),
"tags": ["workflow"],
"project_name": self.project,
}
self.add_trace(trace_data)
# through workflow_run_id get all_nodes_execution
workflow_nodes_execution_id_records = (
db.session.query(WorkflowNodeExecution.id)
.filter(WorkflowNodeExecution.workflow_run_id == trace_info.workflow_run_id)
.all()
)
for node_execution_id_record in workflow_nodes_execution_id_records:
node_execution = (
db.session.query(
WorkflowNodeExecution.id,
WorkflowNodeExecution.tenant_id,
WorkflowNodeExecution.app_id,
WorkflowNodeExecution.title,
WorkflowNodeExecution.node_type,
WorkflowNodeExecution.status,
WorkflowNodeExecution.inputs,
WorkflowNodeExecution.outputs,
WorkflowNodeExecution.created_at,
WorkflowNodeExecution.elapsed_time,
WorkflowNodeExecution.process_data,
WorkflowNodeExecution.execution_metadata,
)
.filter(WorkflowNodeExecution.id == node_execution_id_record.id)
.first()
)
if not node_execution:
continue
node_execution_id = node_execution.id
tenant_id = node_execution.tenant_id
app_id = node_execution.app_id
node_name = node_execution.title
node_type = node_execution.node_type
status = node_execution.status
if node_type == "llm":
inputs = (
json.loads(node_execution.process_data).get("prompts", {}) if node_execution.process_data else {}
)
else:
inputs = json.loads(node_execution.inputs) if node_execution.inputs else {}
outputs = json.loads(node_execution.outputs) if node_execution.outputs else {}
created_at = node_execution.created_at or datetime.now()
elapsed_time = node_execution.elapsed_time
finished_at = created_at + timedelta(seconds=elapsed_time)
execution_metadata = (
json.loads(node_execution.execution_metadata) if node_execution.execution_metadata else {}
)
metadata = execution_metadata.copy()
metadata.update(
{
"workflow_run_id": trace_info.workflow_run_id,
"node_execution_id": node_execution_id,
"tenant_id": tenant_id,
"app_id": app_id,
"app_name": node_name,
"node_type": node_type,
"status": status,
}
)
process_data = json.loads(node_execution.process_data) if node_execution.process_data else {}
provider = None
model = None
total_tokens = 0
completion_tokens = 0
prompt_tokens = 0
if process_data and process_data.get("model_mode") == "chat":
run_type = "llm"
provider = process_data.get("model_provider", None)
model = process_data.get("model_name", "")
metadata.update(
{
"ls_provider": provider,
"ls_model_name": model,
}
)
try:
if outputs.get("usage"):
total_tokens = outputs["usage"].get("total_tokens", 0)
prompt_tokens = outputs["usage"].get("prompt_tokens", 0)
completion_tokens = outputs["usage"].get("completion_tokens", 0)
except Exception:
logger.error("Failed to extract usage", exc_info=True)
else:
run_type = "tool"
parent_span_id = trace_info.workflow_app_log_id or trace_info.workflow_run_id
if not total_tokens:
total_tokens = execution_metadata.get("total_tokens", 0)
span_data = {
"trace_id": opik_trace_id,
"id": uuid4_to_uuid7(created_at, node_execution_id),
"parent_span_id": uuid4_to_uuid7(trace_info.start_time, parent_span_id),
"name": node_type,
"type": run_type,
"start_time": created_at,
"end_time": finished_at,
"metadata": wrap_metadata(metadata),
"input": wrap_dict("input", inputs),
"output": wrap_dict("output", outputs),
"tags": ["node_execution"],
"project_name": self.project,
"usage": {
"total_tokens": total_tokens,
"completion_tokens": completion_tokens,
"prompt_tokens": prompt_tokens,
},
"model": model,
"provider": provider,
}
self.add_span(span_data)
def message_trace(self, trace_info: MessageTraceInfo):
# get message file data
file_list = trace_info.file_list
message_file_data: MessageFile = trace_info.message_file_data
file_url = f"{self.file_base_url}/{message_file_data.url}" if message_file_data else ""
file_list.append(file_url)
metadata = trace_info.metadata
message_data = trace_info.message_data
message_id = trace_info.message_id
user_id = message_data.from_account_id
metadata["user_id"] = user_id
metadata["file_list"] = file_list
if message_data.from_end_user_id:
end_user_data: EndUser = (
db.session.query(EndUser).filter(EndUser.id == message_data.from_end_user_id).first()
)
if end_user_data is not None:
end_user_id = end_user_data.session_id
metadata["end_user_id"] = end_user_id
trace_data = {
"id": uuid4_to_uuid7(trace_info.start_time, message_id),
"name": TraceTaskName.MESSAGE_TRACE.value,
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": wrap_metadata(metadata),
"input": trace_info.inputs,
"output": message_data.answer,
"tags": ["message", str(trace_info.conversation_mode)],
"project_name": self.project,
}
trace = self.add_trace(trace_data)
span_data = {
"trace_id": trace.id,
"name": "llm",
"type": "llm",
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": wrap_metadata(metadata),
"input": {"input": trace_info.inputs},
"output": {"output": message_data.answer},
"tags": ["llm", str(trace_info.conversation_mode)],
"usage": {
"completion_tokens": trace_info.answer_tokens,
"prompt_tokens": trace_info.message_tokens,
"total_tokens": trace_info.total_tokens,
},
"project_name": self.project,
}
self.add_span(span_data)
def moderation_trace(self, trace_info: ModerationTraceInfo):
start_time = trace_info.start_time or trace_info.message_data.created_at
span_data = {
"trace_id": uuid4_to_uuid7(start_time, trace_info.message_id),
"name": TraceTaskName.MODERATION_TRACE.value,
"type": "tool",
"start_time": start_time,
"end_time": trace_info.end_time or trace_info.message_data.updated_at,
"metadata": wrap_metadata(trace_info.metadata),
"input": wrap_dict("input", trace_info.inputs),
"output": {
"action": trace_info.action,
"flagged": trace_info.flagged,
"preset_response": trace_info.preset_response,
"inputs": trace_info.inputs,
},
"tags": ["moderation"],
}
self.add_span(span_data)
def suggested_question_trace(self, trace_info: SuggestedQuestionTraceInfo):
start_time = trace_info.start_time or trace_info.message_data.created_at
span_data = {
"trace_id": uuid4_to_uuid7(start_time, trace_info.message_id),
"name": TraceTaskName.SUGGESTED_QUESTION_TRACE.value,
"type": "tool",
"start_time": start_time,
"end_time": trace_info.end_time or trace_info.message_data.updated_at,
"metadata": wrap_metadata(trace_info.metadata),
"input": wrap_dict("input", trace_info.inputs),
"output": wrap_dict("output", trace_info.suggested_question),
"tags": ["suggested_question"],
}
self.add_span(span_data)
def dataset_retrieval_trace(self, trace_info: DatasetRetrievalTraceInfo):
start_time = trace_info.start_time or trace_info.message_data.created_at
span_data = {
"trace_id": uuid4_to_uuid7(start_time, trace_info.message_id),
"name": TraceTaskName.DATASET_RETRIEVAL_TRACE.value,
"type": "tool",
"start_time": start_time,
"end_time": trace_info.end_time or trace_info.message_data.updated_at,
"metadata": wrap_metadata(trace_info.metadata),
"input": wrap_dict("input", trace_info.inputs),
"output": {"documents": trace_info.documents},
"tags": ["dataset_retrieval"],
}
self.add_span(span_data)
def tool_trace(self, trace_info: ToolTraceInfo):
span_data = {
"trace_id": uuid4_to_uuid7(trace_info.start_time, trace_info.message_id),
"name": trace_info.tool_name,
"type": "tool",
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": wrap_metadata(trace_info.metadata),
"input": wrap_dict("input", trace_info.tool_inputs),
"output": wrap_dict("output", trace_info.tool_outputs),
"tags": ["tool", trace_info.tool_name],
}
self.add_span(span_data)
def generate_name_trace(self, trace_info: GenerateNameTraceInfo):
trace_data = {
"id": uuid4_to_uuid7(trace_info.start_time, trace_info.message_id),
"name": TraceTaskName.GENERATE_NAME_TRACE.value,
"start_time": trace_info.start_time,
"end_time": trace_info.end_time,
"metadata": wrap_metadata(trace_info.metadata),
"input": trace_info.inputs,
"output": trace_info.outputs,
"tags": ["message", str(trace_info.conversation_mode)],
"project_name": self.project,
}
trace = self.add_trace(trace_data)
span_data = {
"trace_id": trace.id,
"name": TraceTaskName.GENERATE_NAME_TRACE.value,
"start_time": trace_info.start_time or trace_info.message_data.created_at,
"end_time": trace_info.end_time or trace_info.message_data.updated_at,
"metadata": wrap_metadata(trace_info.metadata),
"input": wrap_dict("input", trace_info.inputs),
"output": wrap_dict("output", trace_info.outputs),
"tags": ["generate_name"],
}
self.add_span(span_data)
def add_trace(self, opik_trace_data: dict) -> Trace:
try:
trace = self.opik_client.trace(**opik_trace_data)
logger.debug("Opik Trace created successfully")
return trace
except Exception as e:
raise ValueError(f"Opik Failed to create trace: {str(e)}")
def add_span(self, opik_span_data: dict):
try:
self.opik_client.span(**opik_span_data)
logger.debug("Opik Span created successfully")
except Exception as e:
raise ValueError(f"Opik Failed to create span: {str(e)}")
def api_check(self):
try:
self.opik_client.auth_check()
return True
except Exception as e:
logger.info(f"Opik API check failed: {str(e)}", exc_info=True)
raise ValueError(f"Opik API check failed: {str(e)}")
def get_project_url(self):
try:
return self.opik_client.get_project_url(project_name=self.project)
except Exception as e:
logger.info(f"Opik get run url failed: {str(e)}", exc_info=True)
raise ValueError(f"Opik get run url failed: {str(e)}")

View File

@ -17,6 +17,7 @@ from core.ops.entities.config_entity import (
OPS_FILE_PATH,
LangfuseConfig,
LangSmithConfig,
OpikConfig,
TracingProviderEnum,
)
from core.ops.entities.trace_entity import (
@ -32,6 +33,7 @@ from core.ops.entities.trace_entity import (
)
from core.ops.langfuse_trace.langfuse_trace import LangFuseDataTrace
from core.ops.langsmith_trace.langsmith_trace import LangSmithDataTrace
from core.ops.opik_trace.opik_trace import OpikDataTrace
from core.ops.utils import get_message_data
from extensions.ext_database import db
from extensions.ext_storage import storage
@ -52,6 +54,12 @@ provider_config_map: dict[str, dict[str, Any]] = {
"other_keys": ["project", "endpoint"],
"trace_instance": LangSmithDataTrace,
},
TracingProviderEnum.OPIK.value: {
"config_class": OpikConfig,
"secret_keys": ["api_key"],
"other_keys": ["project", "url", "workspace"],
"trace_instance": OpikDataTrace,
},
}

2193
api/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,7 @@ numpy = "~1.26.4"
oci = "~2.135.1"
openai = "~1.52.0"
openpyxl = "~3.1.5"
opik = "~1.2.2"
pandas = { version = "~2.2.2", extras = ["performance", "excel"] }
pandas-stubs = "~2.2.3.241009"
psycogreen = "~1.0.2"

View File

@ -59,6 +59,15 @@ class OpsService:
except Exception:
new_decrypt_tracing_config.update({"project_url": "https://smith.langchain.com/"})
if tracing_provider == "opik" and (
"project_url" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_url")
):
try:
project_url = OpsTraceManager.get_trace_config_project_url(decrypt_tracing_config, tracing_provider)
new_decrypt_tracing_config.update({"project_url": project_url})
except Exception:
new_decrypt_tracing_config.update({"project_url": "https://www.comet.com/opik/"})
trace_config_data.tracing_config = new_decrypt_tracing_config
return trace_config_data.to_dict()
@ -92,7 +101,7 @@ class OpsService:
if tracing_provider == "langfuse":
project_key = OpsTraceManager.get_trace_config_project_key(tracing_config, tracing_provider)
project_url = "{host}/project/{key}".format(host=tracing_config.get("host"), key=project_key)
elif tracing_provider == "langsmith":
elif tracing_provider in ("langsmith", "opik"):
project_url = OpsTraceManager.get_trace_config_project_url(tracing_config, tracing_provider)
else:
project_url = None

View File

@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import TracingIcon from './tracing-icon'
import ProviderPanel from './provider-panel'
import type { LangFuseConfig, LangSmithConfig } from './type'
import type { LangFuseConfig, LangSmithConfig, OpikConfig } from './type'
import { TracingProvider } from './type'
import ProviderConfigModal from './provider-config-modal'
import Indicator from '@/app/components/header/indicator'
@ -23,7 +23,8 @@ export type PopupProps = {
onChooseProvider: (provider: TracingProvider) => void
langSmithConfig: LangSmithConfig | null
langFuseConfig: LangFuseConfig | null
onConfigUpdated: (provider: TracingProvider, payload: LangSmithConfig | LangFuseConfig) => void
opikConfig: OpikConfig | null
onConfigUpdated: (provider: TracingProvider, payload: LangSmithConfig | LangFuseConfig | OpikConfig) => void
onConfigRemoved: (provider: TracingProvider) => void
}
@ -36,6 +37,7 @@ const ConfigPopup: FC<PopupProps> = ({
onChooseProvider,
langSmithConfig,
langFuseConfig,
opikConfig,
onConfigUpdated,
onConfigRemoved,
}) => {
@ -59,7 +61,7 @@ const ConfigPopup: FC<PopupProps> = ({
}
}, [onChooseProvider])
const handleConfigUpdated = useCallback((payload: LangSmithConfig | LangFuseConfig) => {
const handleConfigUpdated = useCallback((payload: LangSmithConfig | LangFuseConfig | OpikConfig) => {
onConfigUpdated(currentProvider!, payload)
hideConfigModal()
}, [currentProvider, hideConfigModal, onConfigUpdated])
@ -69,8 +71,8 @@ const ConfigPopup: FC<PopupProps> = ({
hideConfigModal()
}, [currentProvider, hideConfigModal, onConfigRemoved])
const providerAllConfigured = langSmithConfig && langFuseConfig
const providerAllNotConfigured = !langSmithConfig && !langFuseConfig
const providerAllConfigured = langSmithConfig && langFuseConfig && opikConfig
const providerAllNotConfigured = !langSmithConfig && !langFuseConfig && !opikConfig
const switchContent = (
<Switch
@ -90,6 +92,7 @@ const ConfigPopup: FC<PopupProps> = ({
onConfig={handleOnConfig(TracingProvider.langSmith)}
isChosen={chosenProvider === TracingProvider.langSmith}
onChoose={handleOnChoose(TracingProvider.langSmith)}
key="langSmith-provider-panel"
/>
)
@ -102,9 +105,61 @@ const ConfigPopup: FC<PopupProps> = ({
onConfig={handleOnConfig(TracingProvider.langfuse)}
isChosen={chosenProvider === TracingProvider.langfuse}
onChoose={handleOnChoose(TracingProvider.langfuse)}
key="langfuse-provider-panel"
/>
)
const opikPanel = (
<ProviderPanel
type={TracingProvider.opik}
readOnly={readOnly}
config={opikConfig}
hasConfigured={!!opikConfig}
onConfig={handleOnConfig(TracingProvider.opik)}
isChosen={chosenProvider === TracingProvider.opik}
onChoose={handleOnChoose(TracingProvider.opik)}
key="opik-provider-panel"
/>
)
const configuredProviderPanel = () => {
const configuredPanels: ProviderPanel[] = []
if (langSmithConfig)
configuredPanels.push(langSmithPanel)
if (langFuseConfig)
configuredPanels.push(langfusePanel)
if (opikConfig)
configuredPanels.push(opikPanel)
return configuredPanels
}
const moreProviderPanel = () => {
const notConfiguredPanels: ProviderPanel[] = []
if (!langSmithConfig)
notConfiguredPanels.push(langSmithPanel)
if (!langFuseConfig)
notConfiguredPanels.push(langfusePanel)
if (!opikConfig)
notConfiguredPanels.push(opikPanel)
return notConfiguredPanels
}
const configuredProviderConfig = () => {
if (currentProvider === TracingProvider.langSmith)
return langSmithConfig
if (currentProvider === TracingProvider.langfuse)
return langFuseConfig
return opikConfig
}
return (
<div className='w-[420px] p-4 rounded-2xl bg-white border-[0.5px] border-black/5 shadow-lg'>
<div className='flex justify-between items-center'>
@ -146,18 +201,19 @@ const ConfigPopup: FC<PopupProps> = ({
<div className='mt-2 space-y-2'>
{langSmithPanel}
{langfusePanel}
{opikPanel}
</div>
</>
)
: (
<>
<div className='leading-4 text-xs font-medium text-gray-500 uppercase'>{t(`${I18N_PREFIX}.configProviderTitle.configured`)}</div>
<div className='mt-2'>
{langSmithConfig ? langSmithPanel : langfusePanel}
<div className='mt-2 space-y-2'>
{configuredProviderPanel()}
</div>
<div className='mt-3 leading-4 text-xs font-medium text-gray-500 uppercase'>{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`)}</div>
<div className='mt-2'>
{!langSmithConfig ? langSmithPanel : langfusePanel}
<div className='mt-2 space-y-2'>
{moreProviderPanel()}
</div>
</>
)}
@ -167,7 +223,7 @@ const ConfigPopup: FC<PopupProps> = ({
<ProviderConfigModal
appId={appId}
type={currentProvider!}
payload={currentProvider === TracingProvider.langSmith ? langSmithConfig : langFuseConfig}
payload={configuredProviderConfig()}
onCancel={hideConfigModal}
onSaved={handleConfigUpdated}
onChosen={onChooseProvider}

View File

@ -3,4 +3,5 @@ import { TracingProvider } from './type'
export const docURL = {
[TracingProvider.langSmith]: 'https://docs.smith.langchain.com/',
[TracingProvider.langfuse]: 'https://docs.langfuse.com',
[TracingProvider.opik]: 'https://www.comet.com/docs/opik/tracing/integrations/dify#setup-instructions',
}

View File

@ -9,7 +9,7 @@ import { TracingProvider } from './type'
import TracingIcon from './tracing-icon'
import ConfigButton from './config-button'
import cn from '@/utils/classnames'
import { LangfuseIcon, LangsmithIcon } from '@/app/components/base/icons/src/public/tracing'
import { LangfuseIcon, LangsmithIcon, OpikIcon } from '@/app/components/base/icons/src/public/tracing'
import Indicator from '@/app/components/header/indicator'
import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps'
import type { TracingStatus } from '@/models/app'
@ -70,11 +70,20 @@ const Panel: FC = () => {
})
}
const inUseTracingProvider: TracingProvider | null = tracingStatus?.tracing_provider || null
const InUseProviderIcon = inUseTracingProvider === TracingProvider.langSmith ? LangsmithIcon : LangfuseIcon
const InUseProviderIcon
= inUseTracingProvider === TracingProvider.langSmith
? LangsmithIcon
: inUseTracingProvider === TracingProvider.langfuse
? LangfuseIcon
: inUseTracingProvider === TracingProvider.opik
? OpikIcon
: null
const [langSmithConfig, setLangSmithConfig] = useState<LangSmithConfig | null>(null)
const [langFuseConfig, setLangFuseConfig] = useState<LangFuseConfig | null>(null)
const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig)
const [opikConfig, setOpikConfig] = useState<OpikConfig | null>(null)
const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig || opikConfig)
const fetchTracingConfig = async () => {
const { tracing_config: langSmithConfig, has_not_configured: langSmithHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.langSmith })
@ -83,6 +92,9 @@ const Panel: FC = () => {
const { tracing_config: langFuseConfig, has_not_configured: langFuseHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.langfuse })
if (!langFuseHasNotConfig)
setLangFuseConfig(langFuseConfig as LangFuseConfig)
const { tracing_config: opikConfig, has_not_configured: OpikHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.opik })
if (!OpikHasNotConfig)
setOpikConfig(opikConfig as OpikConfig)
}
const handleTracingConfigUpdated = async (provider: TracingProvider) => {
@ -90,15 +102,19 @@ const Panel: FC = () => {
const { tracing_config } = await doFetchTracingConfig({ appId, provider })
if (provider === TracingProvider.langSmith)
setLangSmithConfig(tracing_config as LangSmithConfig)
else
else if (provider === TracingProvider.langSmith)
setLangFuseConfig(tracing_config as LangFuseConfig)
else if (provider === TracingProvider.opik)
setOpikConfig(tracing_config as OpikConfig)
}
const handleTracingConfigRemoved = (provider: TracingProvider) => {
if (provider === TracingProvider.langSmith)
setLangSmithConfig(null)
else
else if (provider === TracingProvider.langSmith)
setLangFuseConfig(null)
else if (provider === TracingProvider.opik)
setOpikConfig(null)
if (provider === inUseTracingProvider) {
handleTracingStatusChange({
enabled: false,
@ -167,6 +183,7 @@ const Panel: FC = () => {
onChooseProvider={handleChooseProvider}
langSmithConfig={langSmithConfig}
langFuseConfig={langFuseConfig}
opikConfig={opikConfig}
onConfigUpdated={handleTracingConfigUpdated}
onConfigRemoved={handleTracingConfigRemoved}
controlShowPopup={controlShowPopup}

View File

@ -4,7 +4,7 @@ import React, { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import Field from './field'
import type { LangFuseConfig, LangSmithConfig } from './type'
import type { LangFuseConfig, LangSmithConfig, OpikConfig } from './type'
import { TracingProvider } from './type'
import { docURL } from './config'
import {
@ -21,10 +21,10 @@ import Toast from '@/app/components/base/toast'
type Props = {
appId: string
type: TracingProvider
payload?: LangSmithConfig | LangFuseConfig | null
payload?: LangSmithConfig | LangFuseConfig | OpikConfig | null
onRemoved: () => void
onCancel: () => void
onSaved: (payload: LangSmithConfig | LangFuseConfig) => void
onSaved: (payload: LangSmithConfig | LangFuseConfig | OpikConfig) => void
onChosen: (provider: TracingProvider) => void
}
@ -42,6 +42,13 @@ const langFuseConfigTemplate = {
host: '',
}
const opikConfigTemplate = {
api_key: '',
project: '',
url: '',
workspace: '',
}
const ProviderConfigModal: FC<Props> = ({
appId,
type,
@ -55,14 +62,17 @@ const ProviderConfigModal: FC<Props> = ({
const isEdit = !!payload
const isAdd = !isEdit
const [isSaving, setIsSaving] = useState(false)
const [config, setConfig] = useState<LangSmithConfig | LangFuseConfig>((() => {
const [config, setConfig] = useState<LangSmithConfig | LangFuseConfig | OpikConfig>((() => {
if (isEdit)
return payload
if (type === TracingProvider.langSmith)
return langSmithConfigTemplate
return langFuseConfigTemplate
else if (type === TracingProvider.langfuse)
return langFuseConfigTemplate
return opikConfigTemplate
})())
const [isShowRemoveConfirm, {
setTrue: showRemoveConfirm,
@ -111,6 +121,10 @@ const ProviderConfigModal: FC<Props> = ({
errorMessage = t('common.errorMsg.fieldRequired', { field: 'Host' })
}
if (type === TracingProvider.opik) {
const postData = config as OpikConfig
}
return errorMessage
}, [config, t, type])
const handleSave = useCallback(async () => {
@ -215,6 +229,38 @@ const ProviderConfigModal: FC<Props> = ({
/>
</>
)}
{type === TracingProvider.opik && (
<>
<Field
label='API Key'
labelClassName='!text-sm'
value={(config as OpikConfig).api_key}
onChange={handleConfigChange('api_key')}
placeholder={t(`${I18N_PREFIX}.placeholder`, { key: 'API Key' })!}
/>
<Field
label={t(`${I18N_PREFIX}.project`)!}
labelClassName='!text-sm'
value={(config as OpikConfig).project}
onChange={handleConfigChange('project')}
placeholder={t(`${I18N_PREFIX}.placeholder`, { key: t(`${I18N_PREFIX}.project`) })!}
/>
<Field
label='Workspace'
labelClassName='!text-sm'
value={(config as OpikConfig).workspace}
onChange={handleConfigChange('workspace')}
placeholder={'default'}
/>
<Field
label='Url'
labelClassName='!text-sm'
value={(config as OpikConfig).url}
onChange={handleConfigChange('url')}
placeholder={'https://www.comet.com/opik/api/'}
/>
</>
)}
</div>
<div className='my-8 flex justify-between items-center h-8'>

View File

@ -4,7 +4,7 @@ import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { TracingProvider } from './type'
import cn from '@/utils/classnames'
import { LangfuseIconBig, LangsmithIconBig } from '@/app/components/base/icons/src/public/tracing'
import { LangfuseIconBig, LangsmithIconBig, OpikIconBig } from '@/app/components/base/icons/src/public/tracing'
import { Settings04 } from '@/app/components/base/icons/src/vender/line/general'
import { Eye as View } from '@/app/components/base/icons/src/vender/solid/general'
@ -24,6 +24,7 @@ const getIcon = (type: TracingProvider) => {
return ({
[TracingProvider.langSmith]: LangsmithIconBig,
[TracingProvider.langfuse]: LangfuseIconBig,
[TracingProvider.opik]: OpikIconBig,
})[type]
}

View File

@ -1,6 +1,7 @@
export enum TracingProvider {
langSmith = 'langsmith',
langfuse = 'langfuse',
opik = 'opik',
}
export type LangSmithConfig = {
@ -14,3 +15,10 @@ export type LangFuseConfig = {
secret_key: string
host: string
}
export type OpikConfig = {
api_key: string
project: string
workspace: string
url: string
}

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="70.700851"
height="24"
viewBox="0 0 70.700851 24"
fill="none"
version="1.1"
id="svg6"
sodipodi:docname="opik-icon-big.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="18.615088"
inkscape:cx="36.314629"
inkscape:cy="18.989972"
inkscape:window-width="2560"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<rect
width="70.700851"
height="24"
fill="#ffffff"
id="rect1"
x="0"
y="0"
style="stroke-width:0.0683761;fill:none" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 14.463316,5.8949744 C 11.191179,4.456547 7.3065299,5.9932444 5.8118769,9.3932308 4.3172308,12.793231 5.8113846,16.694496 9.0834872,18.132923 c 1.3197948,0.580171 2.7316238,0.676855 4.0492308,0.364923 0.567179,-0.13429 1.135863,0.216684 1.270085,0.783863 0.134291,0.56718 -0.216615,1.135864 -0.783863,1.270154 C 11.873983,20.964923 9.9916581,20.83788 8.2340513,20.065231 3.8540444,18.139761 1.9338872,12.969778 3.8795692,8.5437949 5.8252581,4.1177778 10.932786,2.0372103 15.312752,3.9626667 c 2.672342,1.1747624 4.432069,3.564376 4.952137,6.2470423 0.110974,0.57224 -0.262974,1.126017 -0.835214,1.236992 -0.572171,0.110906 -1.126017,-0.263043 -1.236923,-0.835282 C 17.796308,8.5668376 16.46359,6.7742906 14.463316,5.8949744 Z M 18.01388,17.557812 c 0.20424,0.856752 -0.324786,1.716786 -1.181538,1.921026 -0.856752,0.204171 -1.716855,-0.324787 -1.921026,-1.181539 -0.204239,-0.856752 0.324787,-1.716855 1.181539,-1.921025 0.856752,-0.20424 1.716854,0.324786 1.921025,1.181538 z m 1.329368,-1.216547 c 1.144615,-0.272821 1.85135,-1.42188 1.57853,-2.566427 -0.272821,-1.144616 -1.421881,-1.851351 -2.566428,-1.57853 -1.144615,0.27282 -1.85135,1.421812 -1.578529,2.566427 0.27282,1.144615 1.42188,1.85135 2.566427,1.57853 z"
fill="url(#paint0_linear_3874_31725)"
id="path1"
style="fill:url(#paint0_linear_3874_31725);stroke-width:0.0683761" />
<path
d="m 31.039658,17.805538 c -1.082803,0 -2.046769,-0.231042 -2.891897,-0.693196 -0.84506,-0.475419 -1.511932,-1.122462 -2.000479,-1.941128 -0.488615,-0.818667 -0.732855,-1.749607 -0.732855,-2.792821 0,-1.056342 0.24424,-1.987282 0.732855,-2.7928204 0.488547,-0.8186666 1.155419,-1.4590769 2.000479,-1.9212991 0.845128,-0.4621538 1.809094,-0.6931966 2.891897,-0.6931966 1.096,0 2.06653,0.2310428 2.911658,0.6931966 0.858257,0.4622222 1.525128,1.096 2.000479,1.9015385 0.488615,0.80547 0.732855,1.742974 0.732855,2.812581 0,1.043214 -0.24424,1.974154 -0.732855,2.792821 -0.475351,0.818666 -1.142222,1.465709 -2.000479,1.941128 -0.845128,0.462154 -1.815658,0.693196 -2.911658,0.693196 z m 0,-2.119316 c 0.607385,0 1.148786,-0.132102 1.624137,-0.396171 0.475419,-0.264068 0.845128,-0.647042 1.109196,-1.148786 0.277334,-0.501812 0.416,-1.089436 0.416,-1.762872 0,-0.686632 -0.138666,-1.274256 -0.416,-1.762803 -0.264068,-0.501812 -0.633777,-0.8847182 -1.109196,-1.148855 -0.475351,-0.2640683 -1.01012,-0.3961025 -1.604376,-0.3961025 -0.607385,0 -1.148787,0.1320342 -1.624137,0.3961025 -0.462222,0.2641368 -0.831932,0.647043 -1.109265,1.148855 -0.277265,0.488547 -0.415932,1.076171 -0.415932,1.762803 0,0.673436 0.138667,1.26106 0.415932,1.762872 0.277333,0.501744 0.647043,0.884718 1.109265,1.148786 0.47535,0.264069 1.01012,0.396171 1.604376,0.396171 z"
fill="#3a3a3a"
id="path2"
style="stroke-width:0.0683761" />
<path
d="m 44.915145,17.805538 c -0.858256,0 -1.643966,-0.198017 -2.35706,-0.594188 -0.699829,-0.396171 -1.261059,-0.990359 -1.683555,-1.782632 -0.409368,-0.805539 -0.614017,-1.822291 -0.614017,-3.050325 0,-1.241231 0.198017,-2.257983 0.594188,-3.0503246 0.409367,-0.7922735 0.963966,-1.3798975 1.663795,-1.7628034 0.699829,-0.396171 1.498735,-0.5941881 2.396649,-0.5941881 1.043214,0 1.960958,0.2244787 2.753231,0.6734359 0.80547,0.4489573 1.439316,1.076171 1.90147,1.881641 0.475351,0.8055382 0.713026,1.7562392 0.713026,2.8522392 0,1.096 -0.237675,2.053333 -0.713026,2.872069 -0.462154,0.80547 -1.096,1.432683 -1.90147,1.881641 -0.792273,0.448957 -1.710017,0.673435 -2.753231,0.673435 z m -4.714598,3.703932 c -0.634188,0 -1.148308,-0.514051 -1.148308,-1.148239 V 8.2381538 c 0,-0.634188 0.51412,-1.1482393 1.148308,-1.1482393 h 0.06044 c 0.634188,0 1.148308,0.5140513 1.148308,1.1482393 v 1.3474188 l -0.07925,2.8126494 0.198086,2.812581 v 5.150428 c 0,0.634188 -0.51412,1.148239 -1.148308,1.148239 z m 4.437333,-5.823248 c 0.594188,0 1.122394,-0.132102 1.584547,-0.396171 0.475351,-0.264068 0.851693,-0.647042 1.129026,-1.148786 0.277265,-0.501812 0.415932,-1.089436 0.415932,-1.762872 0,-0.686632 -0.138667,-1.274256 -0.415932,-1.762803 C 47.07412,10.113778 46.697778,9.7308718 46.222427,9.466735 45.760274,9.2026667 45.232068,9.0706325 44.63788,9.0706325 c -0.594256,0 -1.129025,0.1320342 -1.604376,0.3961025 -0.475419,0.2641368 -0.85176,0.647043 -1.129025,1.148855 -0.277334,0.488547 -0.415932,1.076171 -0.415932,1.762803 0,0.673436 0.138598,1.26106 0.415932,1.762872 0.277265,0.501744 0.653606,0.884718 1.129025,1.148786 0.475351,0.264069 1.01012,0.396171 1.604376,0.396171 z"
fill="#3a3a3a"
id="path3"
style="stroke-width:0.0683761" />
<path
d="m 53.779282,17.66694 c -0.634188,0 -1.148308,-0.514119 -1.148308,-1.148308 V 8.2381538 c 0,-0.634188 0.51412,-1.1482393 1.148308,-1.1482393 h 0.179282 c 0.634188,0 1.148308,0.5140513 1.148308,1.1482393 v 8.2804782 c 0,0.634189 -0.51412,1.148308 -1.148308,1.148308 z m 0.09956,-12.3200819 c -0.462154,0 -0.845129,-0.1452513 -1.148855,-0.4357607 -0.290462,-0.2905025 -0.435692,-0.6404307 -0.435692,-1.0497777 0,-0.4225505 0.14523,-0.7724787 0.435692,-1.0497778 0.303726,-0.2905026 0.686701,-0.4357607 1.148855,-0.4357607 0.462153,0 0.838495,0.138653 1.129025,0.4159521 0.303658,0.2640958 0.455522,0.6008205 0.455522,1.0101676 0,0.4357538 -0.145231,0.8054906 -0.435761,1.1091965 -0.290462,0.2905094 -0.673436,0.4357607 -1.148786,0.4357607 z"
fill="#3a3a3a"
id="path4"
style="stroke-width:0.0683761" />
<path
d="m 60.376821,15.30988 0.05942,-3.109743 5.22106,-4.8280344 c 0.196169,-0.1814701 0.453537,-0.2821881 0.72075,-0.2821881 v 0 c 0.944752,0 1.41894,1.141265 0.752274,1.8107351 l -2.891077,2.9033164 -1.307282,1.089436 z m -0.872069,2.35706 c -0.634188,0 -1.148239,-0.514119 -1.148239,-1.148308 V 4.1182838 c 0,-0.6341812 0.514051,-1.1482872 1.148239,-1.1482872 h 0.179351 c 0.634188,0 1.148307,0.514106 1.148307,1.1482872 V 16.518632 c 0,0.634189 -0.514119,1.148308 -1.148307,1.148308 z m 7.382017,0 c -0.346598,0 -0.674666,-0.156581 -0.892718,-0.426051 l -3.517675,-4.347487 1.564786,-1.980718 3.848206,4.89641 c 0.592,0.753368 0.05538,1.857846 -0.902838,1.857846 z"
fill="#3a3a3a"
id="path5"
style="stroke-width:0.0683761" />
<defs
id="defs6">
<linearGradient
id="paint0_linear_3874_31725"
x1="258.13101"
y1="269.78299"
x2="88.645203"
y2="75.4571"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(0.06837607)">
<stop
stop-color="#FB9341"
id="stop5" />
<stop
offset="1"
stop-color="#E30D3E"
id="stop6" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="47.133904"
height="16"
viewBox="0 0 47.133904 16"
fill="none"
version="1.1"
id="svg6"
sodipodi:docname="opik-icon.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview6"
pagecolor="#b95d5d"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="18.615087"
inkscape:cx="34.541874"
inkscape:cy="18.882533"
inkscape:window-width="2560"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<rect
width="47.119099"
height="15.98219"
fill="#ffffff"
id="rect1"
x="0"
y="0"
style="stroke-width:0.0455515;fill:none"
inkscape:label="rect1" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 9.6391824,3.9256084 C 7.4584431,2.9677242 4.8694901,3.9910489 3.8733677,6.2551834 2.8772499,8.519327 3.8730396,11.117275 6.0537561,12.075159 c 0.8795869,0.38635 1.8205107,0.450735 2.6986394,0.243012 0.3780009,-0.08943 0.7570043,0.144295 0.8464576,0.521993 0.089499,0.377699 -0.1443649,0.7564 -0.5224113,0.845827 C 7.9135024,13.961058 6.6590133,13.876457 5.4876434,13.361931 2.568556,12.079712 1.2888532,8.636894 2.5855671,5.6895232 3.8822857,2.7421295 7.286235,1.3566284 10.205295,2.6388372 11.986296,3.4211403 13.15908,5.0124429 13.505682,6.7988966 13.579642,7.1799648 13.330421,7.548739 12.949049,7.6226396 12.567721,7.6964947 12.198606,7.447473 12.124692,7.0664048 11.860478,5.7048679 10.972279,4.5111667 9.6391824,3.9256084 Z m 2.3662996,7.7665706 c 0.136116,0.570532 -0.216457,1.14325 -0.787445,1.279258 -0.570989,0.135962 -1.14421,-0.216283 -1.2802814,-0.786816 -0.1361171,-0.570532 0.2164564,-1.143295 0.7874454,-1.279258 0.570987,-0.136008 1.14421,0.216283 1.280281,0.786816 z m 0.885967,-0.810128 c 0.762836,-0.181679 1.233846,-0.9468664 1.052022,-1.7090479 -0.181824,-0.7622275 -0.947622,-1.2328598 -1.710414,-1.0511819 -0.762838,0.1816779 -1.233846,0.9468196 -1.052023,1.7090471 0.181823,0.7622277 0.947623,1.2328597 1.710415,1.0511827 z"
fill="url(#paint0_linear_3874_31725)"
id="path1"
style="fill:url(#paint0_linear_3874_31725);stroke-width:0.0455515" />
<path
d="m 20.686606,11.857146 c -0.721642,0 -1.364084,-0.153857 -1.927326,-0.461616 -0.563197,-0.316594 -1.007638,-0.747475 -1.333234,-1.292646 -0.325641,-0.54517 -0.488416,-1.165106 -0.488416,-1.8598076 0,-0.703444 0.162775,-1.32338 0.488416,-1.8598079 0.325596,-0.5451702 0.770037,-0.9716351 1.333234,-1.2794403 0.563242,-0.3077596 1.205684,-0.4616167 1.927326,-0.4616167 0.730437,0 1.377254,0.1538571 1.940495,0.4616167 0.571992,0.3078052 1.016434,0.7298533 1.333234,1.2662813 0.325641,0.5363823 0.488417,1.1606894 0.488417,1.8729669 0,0.6947016 -0.162776,1.3146376 -0.488417,1.8598076 -0.3168,0.545171 -0.761242,0.976052 -1.333234,1.292646 -0.563241,0.307759 -1.210058,0.461616 -1.940495,0.461616 z m 0,-1.411304 c 0.404796,0 0.765617,-0.08797 1.082418,-0.263821 0.316846,-0.17585 0.563242,-0.4308815 0.739232,-0.7650049 0.184831,-0.3341689 0.277246,-0.7254822 0.277246,-1.1739397 0,-0.4572454 -0.09241,-0.8485586 -0.277246,-1.1738941 C 22.332266,6.7350133 22.08587,6.4800268 21.769024,6.3041317 21.452223,6.1282821 21.095822,6.0403572 20.699776,6.0403572 c -0.404796,0 -0.765617,0.087925 -1.082418,0.2637745 -0.308051,0.1758951 -0.554446,0.4308816 -0.739277,0.7650506 -0.184786,0.3253355 -0.277201,0.7166487 -0.277201,1.1738941 0,0.4484575 0.09241,0.8397708 0.277201,1.1739397 0.184831,0.3341234 0.431226,0.5891549 0.739277,0.7650049 0.316801,0.17585 0.673201,0.263821 1.069248,0.263821 z"
fill="#3a3a3a"
id="path2"
style="stroke-width:0.0455515" />
<path
d="m 29.934026,11.857146 c -0.571992,0 -1.095634,-0.131865 -1.57088,-0.395684 -0.466407,-0.26382 -0.840442,-0.659504 -1.122018,-1.1871 -0.272826,-0.5364272 -0.409217,-1.2135074 -0.409217,-2.0312856 0,-0.826566 0.131971,-1.5036463 0.396002,-2.0312862 0.272826,-0.5275944 0.642442,-0.9189077 1.108848,-1.1738942 0.466406,-0.26382 0.998843,-0.3956845 1.597265,-0.3956845 0.695257,0 1.306893,0.1494859 1.83491,0.4484576 0.536811,0.2989717 0.959243,0.7166486 1.267248,1.253031 0.316801,0.5364279 0.475202,1.169523 0.475202,1.8993763 0,0.7298534 -0.158401,1.3673652 -0.475202,1.9125806 -0.308005,0.536383 -0.730437,0.95406 -1.267248,1.253031 -0.528017,0.298972 -1.139653,0.448458 -1.83491,0.448458 z m -3.142079,2.466539 c -0.422659,0 -0.765298,-0.342319 -0.765298,-0.764641 V 5.4859892 c 0,-0.4223213 0.342639,-0.7646408 0.765298,-0.7646408 h 0.04028 c 0.42266,0 0.765299,0.3423195 0.765299,0.7646408 v 0.8972793 l -0.05281,1.8730126 0.132016,1.8729669 v 3.429796 c 0,0.422322 -0.342639,0.764641 -0.765298,0.764641 z m 2.957293,-3.877843 c 0.396001,0 0.748027,-0.08797 1.056033,-0.263821 0.316801,-0.17585 0.567616,-0.4308815 0.752447,-0.7650049 0.184786,-0.3341689 0.277201,-0.7254822 0.277201,-1.1739397 0,-0.4572454 -0.09241,-0.8485586 -0.277201,-1.1738941 C 31.372889,6.7350133 31.122074,6.4800268 30.805273,6.3041317 30.497267,6.1282821 30.145241,6.0403572 29.74924,6.0403572 c -0.396046,0 -0.752447,0.087925 -1.069248,0.2637745 -0.316846,0.1758951 -0.567662,0.4308816 -0.752447,0.7650506 -0.184831,0.3253355 -0.277201,0.7166487 -0.277201,1.1738941 0,0.4484575 0.09237,0.8397708 0.277201,1.1739397 0.184785,0.3341234 0.435601,0.5891549 0.752447,0.7650049 0.316801,0.17585 0.673202,0.263821 1.069248,0.263821 z"
fill="#3a3a3a"
id="path3"
style="stroke-width:0.0455515" />
<path
d="m 35.841594,11.76485 c -0.422659,0 -0.765298,-0.342365 -0.765298,-0.764686 V 5.4859892 c 0,-0.4223213 0.342639,-0.7646408 0.765298,-0.7646408 h 0.119484 c 0.422659,0 0.765298,0.3423195 0.765298,0.7646408 v 5.5141748 c 0,0.422321 -0.342639,0.764686 -0.765298,0.764686 z m 0.06635,-8.2042457 c -0.308006,0 -0.563241,-0.096726 -0.765662,-0.2901837 -0.19358,-0.1934528 -0.290371,-0.4264787 -0.290371,-0.6990729 0,-0.2813867 0.0968,-0.5144125 0.290371,-0.6990728 0.202421,-0.1934528 0.457656,-0.2901838 0.765662,-0.2901838 0.308006,0 0.558822,0.092332 0.752448,0.2769928 0.202375,0.1758678 0.303585,0.4001011 0.303585,0.6726954 0,0.2901792 -0.0968,0.536396 -0.290415,0.7386413 -0.19358,0.1934573 -0.448817,0.2901837 -0.765618,0.2901837 z"
fill="#3a3a3a"
id="path4"
style="stroke-width:0.0455515" />
<path
d="m 40.238571,10.195226 0.0396,-2.0708549 3.479613,-3.2151067 c 0.130739,-0.1208454 0.302264,-0.187916 0.480351,-0.187916 v 0 c 0.629636,0 0.945662,0.7599964 0.501357,1.2058131 l -1.926779,1.9333896 -0.871247,0.7254822 z m -0.581195,1.569624 c -0.42266,0 -0.765253,-0.342365 -0.765253,-0.764686 V 2.7424664 c 0,-0.4223168 0.342593,-0.7646726 0.765253,-0.7646726 h 0.119528 c 0.42266,0 0.765298,0.3423558 0.765298,0.7646726 v 8.2576976 c 0,0.422321 -0.342638,0.764686 -0.765298,0.764686 z m 4.919799,0 c -0.230994,0 -0.449637,-0.104271 -0.594959,-0.283718 l -2.34438,-2.8950987 1.042863,-1.3190088 2.564664,3.2606405 c 0.394542,0.501685 0.03692,1.237185 -0.601702,1.237185 z"
fill="#3a3a3a"
id="path5"
style="stroke-width:0.0455515" />
<defs
id="defs6">
<linearGradient
id="paint0_linear_3874_31725"
x1="258.13101"
y1="269.78299"
x2="88.645203"
y2="75.4571"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(0.04556973,0.04553331)">
<stop
stop-color="#FB9341"
id="stop5" />
<stop
offset="1"
stop-color="#E30D3E"
id="stop6" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,163 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "47.133904",
"height": "16",
"viewBox": "0 0 47.133904 16",
"fill": "none",
"version": "1.1",
"id": "svg6",
"sodipodi:docname": "opik-icon.svg",
"inkscape:version": "1.3.2 (091e20ef0f, 2023-11-25)",
"xmlns:inkscape": "http://www.inkscape.org/namespaces/inkscape",
"xmlns:sodipodi": "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd",
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:svg": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "sodipodi:namedview",
"attributes": {
"id": "namedview6",
"pagecolor": "#b95d5d",
"bordercolor": "#666666",
"borderopacity": "1.0",
"inkscape:showpageshadow": "2",
"inkscape:pageopacity": "0.0",
"inkscape:pagecheckerboard": "0",
"inkscape:deskcolor": "#d1d1d1",
"inkscape:zoom": "18.615087",
"inkscape:cx": "34.541874",
"inkscape:cy": "18.882533",
"inkscape:window-width": "2560",
"inkscape:window-height": "1371",
"inkscape:window-x": "0",
"inkscape:window-y": "0",
"inkscape:window-maximized": "1",
"inkscape:current-layer": "svg6"
},
"children": []
},
{
"type": "element",
"name": "rect",
"attributes": {
"width": "47.119099",
"height": "15.98219",
"fill": "#ffffff",
"id": "rect1",
"x": "0",
"y": "0",
"style": "stroke-width:0.0455515;fill:none",
"inkscape:label": "rect1"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M 9.6391824,3.9256084 C 7.4584431,2.9677242 4.8694901,3.9910489 3.8733677,6.2551834 2.8772499,8.519327 3.8730396,11.117275 6.0537561,12.075159 c 0.8795869,0.38635 1.8205107,0.450735 2.6986394,0.243012 0.3780009,-0.08943 0.7570043,0.144295 0.8464576,0.521993 0.089499,0.377699 -0.1443649,0.7564 -0.5224113,0.845827 C 7.9135024,13.961058 6.6590133,13.876457 5.4876434,13.361931 2.568556,12.079712 1.2888532,8.636894 2.5855671,5.6895232 3.8822857,2.7421295 7.286235,1.3566284 10.205295,2.6388372 11.986296,3.4211403 13.15908,5.0124429 13.505682,6.7988966 13.579642,7.1799648 13.330421,7.548739 12.949049,7.6226396 12.567721,7.6964947 12.198606,7.447473 12.124692,7.0664048 11.860478,5.7048679 10.972279,4.5111667 9.6391824,3.9256084 Z m 2.3662996,7.7665706 c 0.136116,0.570532 -0.216457,1.14325 -0.787445,1.279258 -0.570989,0.135962 -1.14421,-0.216283 -1.2802814,-0.786816 -0.1361171,-0.570532 0.2164564,-1.143295 0.7874454,-1.279258 0.570987,-0.136008 1.14421,0.216283 1.280281,0.786816 z m 0.885967,-0.810128 c 0.762836,-0.181679 1.233846,-0.9468664 1.052022,-1.7090479 -0.181824,-0.7622275 -0.947622,-1.2328598 -1.710414,-1.0511819 -0.762838,0.1816779 -1.233846,0.9468196 -1.052023,1.7090471 0.181823,0.7622277 0.947623,1.2328597 1.710415,1.0511827 z",
"fill": "url(#paint0_linear_3874_31725)",
"id": "path1",
"style": "fill:url(#paint0_linear_3874_31725);stroke-width:0.0455515"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 20.686606,11.857146 c -0.721642,0 -1.364084,-0.153857 -1.927326,-0.461616 -0.563197,-0.316594 -1.007638,-0.747475 -1.333234,-1.292646 -0.325641,-0.54517 -0.488416,-1.165106 -0.488416,-1.8598076 0,-0.703444 0.162775,-1.32338 0.488416,-1.8598079 0.325596,-0.5451702 0.770037,-0.9716351 1.333234,-1.2794403 0.563242,-0.3077596 1.205684,-0.4616167 1.927326,-0.4616167 0.730437,0 1.377254,0.1538571 1.940495,0.4616167 0.571992,0.3078052 1.016434,0.7298533 1.333234,1.2662813 0.325641,0.5363823 0.488417,1.1606894 0.488417,1.8729669 0,0.6947016 -0.162776,1.3146376 -0.488417,1.8598076 -0.3168,0.545171 -0.761242,0.976052 -1.333234,1.292646 -0.563241,0.307759 -1.210058,0.461616 -1.940495,0.461616 z m 0,-1.411304 c 0.404796,0 0.765617,-0.08797 1.082418,-0.263821 0.316846,-0.17585 0.563242,-0.4308815 0.739232,-0.7650049 0.184831,-0.3341689 0.277246,-0.7254822 0.277246,-1.1739397 0,-0.4572454 -0.09241,-0.8485586 -0.277246,-1.1738941 C 22.332266,6.7350133 22.08587,6.4800268 21.769024,6.3041317 21.452223,6.1282821 21.095822,6.0403572 20.699776,6.0403572 c -0.404796,0 -0.765617,0.087925 -1.082418,0.2637745 -0.308051,0.1758951 -0.554446,0.4308816 -0.739277,0.7650506 -0.184786,0.3253355 -0.277201,0.7166487 -0.277201,1.1738941 0,0.4484575 0.09241,0.8397708 0.277201,1.1739397 0.184831,0.3341234 0.431226,0.5891549 0.739277,0.7650049 0.316801,0.17585 0.673201,0.263821 1.069248,0.263821 z",
"fill": "#3a3a3a",
"id": "path2",
"style": "stroke-width:0.0455515"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 29.934026,11.857146 c -0.571992,0 -1.095634,-0.131865 -1.57088,-0.395684 -0.466407,-0.26382 -0.840442,-0.659504 -1.122018,-1.1871 -0.272826,-0.5364272 -0.409217,-1.2135074 -0.409217,-2.0312856 0,-0.826566 0.131971,-1.5036463 0.396002,-2.0312862 0.272826,-0.5275944 0.642442,-0.9189077 1.108848,-1.1738942 0.466406,-0.26382 0.998843,-0.3956845 1.597265,-0.3956845 0.695257,0 1.306893,0.1494859 1.83491,0.4484576 0.536811,0.2989717 0.959243,0.7166486 1.267248,1.253031 0.316801,0.5364279 0.475202,1.169523 0.475202,1.8993763 0,0.7298534 -0.158401,1.3673652 -0.475202,1.9125806 -0.308005,0.536383 -0.730437,0.95406 -1.267248,1.253031 -0.528017,0.298972 -1.139653,0.448458 -1.83491,0.448458 z m -3.142079,2.466539 c -0.422659,0 -0.765298,-0.342319 -0.765298,-0.764641 V 5.4859892 c 0,-0.4223213 0.342639,-0.7646408 0.765298,-0.7646408 h 0.04028 c 0.42266,0 0.765299,0.3423195 0.765299,0.7646408 v 0.8972793 l -0.05281,1.8730126 0.132016,1.8729669 v 3.429796 c 0,0.422322 -0.342639,0.764641 -0.765298,0.764641 z m 2.957293,-3.877843 c 0.396001,0 0.748027,-0.08797 1.056033,-0.263821 0.316801,-0.17585 0.567616,-0.4308815 0.752447,-0.7650049 0.184786,-0.3341689 0.277201,-0.7254822 0.277201,-1.1739397 0,-0.4572454 -0.09241,-0.8485586 -0.277201,-1.1738941 C 31.372889,6.7350133 31.122074,6.4800268 30.805273,6.3041317 30.497267,6.1282821 30.145241,6.0403572 29.74924,6.0403572 c -0.396046,0 -0.752447,0.087925 -1.069248,0.2637745 -0.316846,0.1758951 -0.567662,0.4308816 -0.752447,0.7650506 -0.184831,0.3253355 -0.277201,0.7166487 -0.277201,1.1738941 0,0.4484575 0.09237,0.8397708 0.277201,1.1739397 0.184785,0.3341234 0.435601,0.5891549 0.752447,0.7650049 0.316801,0.17585 0.673202,0.263821 1.069248,0.263821 z",
"fill": "#3a3a3a",
"id": "path3",
"style": "stroke-width:0.0455515"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 35.841594,11.76485 c -0.422659,0 -0.765298,-0.342365 -0.765298,-0.764686 V 5.4859892 c 0,-0.4223213 0.342639,-0.7646408 0.765298,-0.7646408 h 0.119484 c 0.422659,0 0.765298,0.3423195 0.765298,0.7646408 v 5.5141748 c 0,0.422321 -0.342639,0.764686 -0.765298,0.764686 z m 0.06635,-8.2042457 c -0.308006,0 -0.563241,-0.096726 -0.765662,-0.2901837 -0.19358,-0.1934528 -0.290371,-0.4264787 -0.290371,-0.6990729 0,-0.2813867 0.0968,-0.5144125 0.290371,-0.6990728 0.202421,-0.1934528 0.457656,-0.2901838 0.765662,-0.2901838 0.308006,0 0.558822,0.092332 0.752448,0.2769928 0.202375,0.1758678 0.303585,0.4001011 0.303585,0.6726954 0,0.2901792 -0.0968,0.536396 -0.290415,0.7386413 -0.19358,0.1934573 -0.448817,0.2901837 -0.765618,0.2901837 z",
"fill": "#3a3a3a",
"id": "path4",
"style": "stroke-width:0.0455515"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 40.238571,10.195226 0.0396,-2.0708549 3.479613,-3.2151067 c 0.130739,-0.1208454 0.302264,-0.187916 0.480351,-0.187916 v 0 c 0.629636,0 0.945662,0.7599964 0.501357,1.2058131 l -1.926779,1.9333896 -0.871247,0.7254822 z m -0.581195,1.569624 c -0.42266,0 -0.765253,-0.342365 -0.765253,-0.764686 V 2.7424664 c 0,-0.4223168 0.342593,-0.7646726 0.765253,-0.7646726 h 0.119528 c 0.42266,0 0.765298,0.3423558 0.765298,0.7646726 v 8.2576976 c 0,0.422321 -0.342638,0.764686 -0.765298,0.764686 z m 4.919799,0 c -0.230994,0 -0.449637,-0.104271 -0.594959,-0.283718 l -2.34438,-2.8950987 1.042863,-1.3190088 2.564664,3.2606405 c 0.394542,0.501685 0.03692,1.237185 -0.601702,1.237185 z",
"fill": "#3a3a3a",
"id": "path5",
"style": "stroke-width:0.0455515"
},
"children": []
},
{
"type": "element",
"name": "defs",
"attributes": {
"id": "defs6"
},
"children": [
{
"type": "element",
"name": "linearGradient",
"attributes": {
"id": "paint0_linear_3874_31725",
"x1": "258.13101",
"y1": "269.78299",
"x2": "88.645203",
"y2": "75.4571",
"gradientUnits": "userSpaceOnUse",
"gradientTransform": "scale(0.04556973,0.04553331)"
},
"children": [
{
"type": "element",
"name": "stop",
"attributes": {
"stop-color": "#FB9341",
"id": "stop5"
},
"children": []
},
{
"type": "element",
"name": "stop",
"attributes": {
"offset": "1",
"stop-color": "#E30D3E",
"id": "stop6"
},
"children": []
}
]
}
]
}
]
},
"name": "OpikIcon"
}

View File

@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './OpikIcon.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'OpikIcon'
export default Icon

View File

@ -0,0 +1,162 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "70.700851",
"height": "24",
"viewBox": "0 0 70.700851 24",
"fill": "none",
"version": "1.1",
"id": "svg6",
"sodipodi:docname": "opik-icon-big.svg",
"inkscape:version": "1.3.2 (091e20ef0f, 2023-11-25)",
"xmlns:inkscape": "http://www.inkscape.org/namespaces/inkscape",
"xmlns:sodipodi": "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd",
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:svg": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "sodipodi:namedview",
"attributes": {
"id": "namedview6",
"pagecolor": "#ffffff",
"bordercolor": "#666666",
"borderopacity": "1.0",
"inkscape:showpageshadow": "2",
"inkscape:pageopacity": "0.0",
"inkscape:pagecheckerboard": "0",
"inkscape:deskcolor": "#d1d1d1",
"inkscape:zoom": "18.615088",
"inkscape:cx": "36.314629",
"inkscape:cy": "18.989972",
"inkscape:window-width": "2560",
"inkscape:window-height": "1371",
"inkscape:window-x": "0",
"inkscape:window-y": "0",
"inkscape:window-maximized": "1",
"inkscape:current-layer": "svg6"
},
"children": []
},
{
"type": "element",
"name": "rect",
"attributes": {
"width": "70.700851",
"height": "24",
"fill": "#ffffff",
"id": "rect1",
"x": "0",
"y": "0",
"style": "stroke-width:0.0683761;fill:none"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M 14.463316,5.8949744 C 11.191179,4.456547 7.3065299,5.9932444 5.8118769,9.3932308 4.3172308,12.793231 5.8113846,16.694496 9.0834872,18.132923 c 1.3197948,0.580171 2.7316238,0.676855 4.0492308,0.364923 0.567179,-0.13429 1.135863,0.216684 1.270085,0.783863 0.134291,0.56718 -0.216615,1.135864 -0.783863,1.270154 C 11.873983,20.964923 9.9916581,20.83788 8.2340513,20.065231 3.8540444,18.139761 1.9338872,12.969778 3.8795692,8.5437949 5.8252581,4.1177778 10.932786,2.0372103 15.312752,3.9626667 c 2.672342,1.1747624 4.432069,3.564376 4.952137,6.2470423 0.110974,0.57224 -0.262974,1.126017 -0.835214,1.236992 -0.572171,0.110906 -1.126017,-0.263043 -1.236923,-0.835282 C 17.796308,8.5668376 16.46359,6.7742906 14.463316,5.8949744 Z M 18.01388,17.557812 c 0.20424,0.856752 -0.324786,1.716786 -1.181538,1.921026 -0.856752,0.204171 -1.716855,-0.324787 -1.921026,-1.181539 -0.204239,-0.856752 0.324787,-1.716855 1.181539,-1.921025 0.856752,-0.20424 1.716854,0.324786 1.921025,1.181538 z m 1.329368,-1.216547 c 1.144615,-0.272821 1.85135,-1.42188 1.57853,-2.566427 -0.272821,-1.144616 -1.421881,-1.851351 -2.566428,-1.57853 -1.144615,0.27282 -1.85135,1.421812 -1.578529,2.566427 0.27282,1.144615 1.42188,1.85135 2.566427,1.57853 z",
"fill": "url(#paint0_linear_3874_31725)",
"id": "path1",
"style": "fill:url(#paint0_linear_3874_31725);stroke-width:0.0683761"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 31.039658,17.805538 c -1.082803,0 -2.046769,-0.231042 -2.891897,-0.693196 -0.84506,-0.475419 -1.511932,-1.122462 -2.000479,-1.941128 -0.488615,-0.818667 -0.732855,-1.749607 -0.732855,-2.792821 0,-1.056342 0.24424,-1.987282 0.732855,-2.7928204 0.488547,-0.8186666 1.155419,-1.4590769 2.000479,-1.9212991 0.845128,-0.4621538 1.809094,-0.6931966 2.891897,-0.6931966 1.096,0 2.06653,0.2310428 2.911658,0.6931966 0.858257,0.4622222 1.525128,1.096 2.000479,1.9015385 0.488615,0.80547 0.732855,1.742974 0.732855,2.812581 0,1.043214 -0.24424,1.974154 -0.732855,2.792821 -0.475351,0.818666 -1.142222,1.465709 -2.000479,1.941128 -0.845128,0.462154 -1.815658,0.693196 -2.911658,0.693196 z m 0,-2.119316 c 0.607385,0 1.148786,-0.132102 1.624137,-0.396171 0.475419,-0.264068 0.845128,-0.647042 1.109196,-1.148786 0.277334,-0.501812 0.416,-1.089436 0.416,-1.762872 0,-0.686632 -0.138666,-1.274256 -0.416,-1.762803 -0.264068,-0.501812 -0.633777,-0.8847182 -1.109196,-1.148855 -0.475351,-0.2640683 -1.01012,-0.3961025 -1.604376,-0.3961025 -0.607385,0 -1.148787,0.1320342 -1.624137,0.3961025 -0.462222,0.2641368 -0.831932,0.647043 -1.109265,1.148855 -0.277265,0.488547 -0.415932,1.076171 -0.415932,1.762803 0,0.673436 0.138667,1.26106 0.415932,1.762872 0.277333,0.501744 0.647043,0.884718 1.109265,1.148786 0.47535,0.264069 1.01012,0.396171 1.604376,0.396171 z",
"fill": "#3a3a3a",
"id": "path2",
"style": "stroke-width:0.0683761"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 44.915145,17.805538 c -0.858256,0 -1.643966,-0.198017 -2.35706,-0.594188 -0.699829,-0.396171 -1.261059,-0.990359 -1.683555,-1.782632 -0.409368,-0.805539 -0.614017,-1.822291 -0.614017,-3.050325 0,-1.241231 0.198017,-2.257983 0.594188,-3.0503246 0.409367,-0.7922735 0.963966,-1.3798975 1.663795,-1.7628034 0.699829,-0.396171 1.498735,-0.5941881 2.396649,-0.5941881 1.043214,0 1.960958,0.2244787 2.753231,0.6734359 0.80547,0.4489573 1.439316,1.076171 1.90147,1.881641 0.475351,0.8055382 0.713026,1.7562392 0.713026,2.8522392 0,1.096 -0.237675,2.053333 -0.713026,2.872069 -0.462154,0.80547 -1.096,1.432683 -1.90147,1.881641 -0.792273,0.448957 -1.710017,0.673435 -2.753231,0.673435 z m -4.714598,3.703932 c -0.634188,0 -1.148308,-0.514051 -1.148308,-1.148239 V 8.2381538 c 0,-0.634188 0.51412,-1.1482393 1.148308,-1.1482393 h 0.06044 c 0.634188,0 1.148308,0.5140513 1.148308,1.1482393 v 1.3474188 l -0.07925,2.8126494 0.198086,2.812581 v 5.150428 c 0,0.634188 -0.51412,1.148239 -1.148308,1.148239 z m 4.437333,-5.823248 c 0.594188,0 1.122394,-0.132102 1.584547,-0.396171 0.475351,-0.264068 0.851693,-0.647042 1.129026,-1.148786 0.277265,-0.501812 0.415932,-1.089436 0.415932,-1.762872 0,-0.686632 -0.138667,-1.274256 -0.415932,-1.762803 C 47.07412,10.113778 46.697778,9.7308718 46.222427,9.466735 45.760274,9.2026667 45.232068,9.0706325 44.63788,9.0706325 c -0.594256,0 -1.129025,0.1320342 -1.604376,0.3961025 -0.475419,0.2641368 -0.85176,0.647043 -1.129025,1.148855 -0.277334,0.488547 -0.415932,1.076171 -0.415932,1.762803 0,0.673436 0.138598,1.26106 0.415932,1.762872 0.277265,0.501744 0.653606,0.884718 1.129025,1.148786 0.475351,0.264069 1.01012,0.396171 1.604376,0.396171 z",
"fill": "#3a3a3a",
"id": "path3",
"style": "stroke-width:0.0683761"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 53.779282,17.66694 c -0.634188,0 -1.148308,-0.514119 -1.148308,-1.148308 V 8.2381538 c 0,-0.634188 0.51412,-1.1482393 1.148308,-1.1482393 h 0.179282 c 0.634188,0 1.148308,0.5140513 1.148308,1.1482393 v 8.2804782 c 0,0.634189 -0.51412,1.148308 -1.148308,1.148308 z m 0.09956,-12.3200819 c -0.462154,0 -0.845129,-0.1452513 -1.148855,-0.4357607 -0.290462,-0.2905025 -0.435692,-0.6404307 -0.435692,-1.0497777 0,-0.4225505 0.14523,-0.7724787 0.435692,-1.0497778 0.303726,-0.2905026 0.686701,-0.4357607 1.148855,-0.4357607 0.462153,0 0.838495,0.138653 1.129025,0.4159521 0.303658,0.2640958 0.455522,0.6008205 0.455522,1.0101676 0,0.4357538 -0.145231,0.8054906 -0.435761,1.1091965 -0.290462,0.2905094 -0.673436,0.4357607 -1.148786,0.4357607 z",
"fill": "#3a3a3a",
"id": "path4",
"style": "stroke-width:0.0683761"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "m 60.376821,15.30988 0.05942,-3.109743 5.22106,-4.8280344 c 0.196169,-0.1814701 0.453537,-0.2821881 0.72075,-0.2821881 v 0 c 0.944752,0 1.41894,1.141265 0.752274,1.8107351 l -2.891077,2.9033164 -1.307282,1.089436 z m -0.872069,2.35706 c -0.634188,0 -1.148239,-0.514119 -1.148239,-1.148308 V 4.1182838 c 0,-0.6341812 0.514051,-1.1482872 1.148239,-1.1482872 h 0.179351 c 0.634188,0 1.148307,0.514106 1.148307,1.1482872 V 16.518632 c 0,0.634189 -0.514119,1.148308 -1.148307,1.148308 z m 7.382017,0 c -0.346598,0 -0.674666,-0.156581 -0.892718,-0.426051 l -3.517675,-4.347487 1.564786,-1.980718 3.848206,4.89641 c 0.592,0.753368 0.05538,1.857846 -0.902838,1.857846 z",
"fill": "#3a3a3a",
"id": "path5",
"style": "stroke-width:0.0683761"
},
"children": []
},
{
"type": "element",
"name": "defs",
"attributes": {
"id": "defs6"
},
"children": [
{
"type": "element",
"name": "linearGradient",
"attributes": {
"id": "paint0_linear_3874_31725",
"x1": "258.13101",
"y1": "269.78299",
"x2": "88.645203",
"y2": "75.4571",
"gradientUnits": "userSpaceOnUse",
"gradientTransform": "scale(0.06837607)"
},
"children": [
{
"type": "element",
"name": "stop",
"attributes": {
"stop-color": "#FB9341",
"id": "stop5"
},
"children": []
},
{
"type": "element",
"name": "stop",
"attributes": {
"offset": "1",
"stop-color": "#E30D3E",
"id": "stop6"
},
"children": []
}
]
}
]
}
]
},
"name": "OpikIconBig"
}

View File

@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './OpikIconBig.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'OpikIconBig'
export default Icon

View File

@ -2,4 +2,6 @@ export { default as LangfuseIconBig } from './LangfuseIconBig'
export { default as LangfuseIcon } from './LangfuseIcon'
export { default as LangsmithIconBig } from './LangsmithIconBig'
export { default as LangsmithIcon } from './LangsmithIcon'
export { default as OpikIconBig } from './OpikIconBig'
export { default as OpikIcon } from './OpikIcon'
export { default as TracingIcon } from './TracingIcon'

View File

@ -157,6 +157,10 @@ const translation = {
title: 'Langfuse',
description: 'Traces, evals, prompt management and metrics to debug and improve your LLM application.',
},
opik: {
title: 'Opik',
description: 'Opik is an open-source platform for evaluating, testing, and monitoring LLM applications.',
},
inUse: 'In use',
configProvider: {
title: 'Config ',

View File

@ -157,6 +157,10 @@ const translation = {
title: 'Langfuse',
description: '跟踪、评估、提示管理和指标,以调试和改进您的 LLM 应用程序。',
},
opik: {
title: 'Opik',
description: '一个全方位的开发者平台,适用于 LLM 驱动应用程序生命周期的每个步骤。',
},
inUse: '使用中',
configProvider: {
title: '配置 ',

View File

@ -1,4 +1,4 @@
import type { LangFuseConfig, LangSmithConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
import type { LangFuseConfig, LangSmithConfig, OpikConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
import type { App, AppSSO, AppTemplate, SiteConfig } from '@/types/app'
/* export type App = {
@ -165,5 +165,5 @@ export type TracingStatus = {
export type TracingConfig = {
tracing_provider: TracingProvider
tracing_config: LangSmithConfig | LangFuseConfig
tracing_config: LangSmithConfig | LangFuseConfig | OpikConfig
}