mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-04 17:45:07 +08:00
Compare commits
7 Commits
3fcf2ee54c
...
0db00f70b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 0db00f70b2 | |||
| 701761d119 | |||
| 2993fc666b | |||
| 8a6d205df0 | |||
| 912b6b023e | |||
| 89e8818dda | |||
| 1dba6b5bf9 |
@ -378,7 +378,7 @@ class AdminCLI(Cmd):
|
|||||||
self.session.headers.update({
|
self.session.headers.update({
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': response.headers['Authorization'],
|
'Authorization': response.headers['Authorization'],
|
||||||
'User-Agent': 'RAGFlow-CLI/0.22.0'
|
'User-Agent': 'RAGFlow-CLI/0.22.1'
|
||||||
})
|
})
|
||||||
print("Authentication successful.")
|
print("Authentication successful.")
|
||||||
return True
|
return True
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ragflow-cli"
|
name = "ragflow-cli"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
description = "Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring. "
|
description = "Admin Service's client of [RAGFlow](https://github.com/infiniflow/ragflow). The Admin Service provides user management and system monitoring. "
|
||||||
authors = [{ name = "Lynn", email = "lynn_inf@hotmail.com" }]
|
authors = [{ name = "Lynn", email = "lynn_inf@hotmail.com" }]
|
||||||
license = { text = "Apache License, Version 2.0" }
|
license = { text = "Apache License, Version 2.0" }
|
||||||
|
|||||||
@ -918,6 +918,6 @@ def check_embedding():
|
|||||||
}
|
}
|
||||||
if summary["avg_cos_sim"] > 0.9:
|
if summary["avg_cos_sim"] > 0.9:
|
||||||
return get_json_result(data={"summary": summary, "results": results})
|
return get_json_result(data={"summary": summary, "results": results})
|
||||||
return get_json_result(code=RetCode.NOT_EFFECTIVE, message="failed", data={"summary": summary, "results": results})
|
return get_json_result(code=RetCode.NOT_EFFECTIVE, message="Embedding model switch failed: the average similarity between old and new vectors is below 0.9, indicating incompatible vector spaces.", data={"summary": summary, "results": results})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,13 @@ class BlobStorageConnector(LoadConnector, PollConnector):
|
|||||||
):
|
):
|
||||||
raise ConnectorMissingCredentialError("Oracle Cloud Infrastructure")
|
raise ConnectorMissingCredentialError("Oracle Cloud Infrastructure")
|
||||||
|
|
||||||
|
elif self.bucket_type == BlobType.S3_COMPATIBLE:
|
||||||
|
if not all(
|
||||||
|
credentials.get(key)
|
||||||
|
for key in ["endpoint_url", "aws_access_key_id", "aws_secret_access_key"]
|
||||||
|
):
|
||||||
|
raise ConnectorMissingCredentialError("S3 Compatible Storage")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported bucket type: {self.bucket_type}")
|
raise ValueError(f"Unsupported bucket type: {self.bucket_type}")
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class BlobType(str, Enum):
|
|||||||
R2 = "r2"
|
R2 = "r2"
|
||||||
GOOGLE_CLOUD_STORAGE = "google_cloud_storage"
|
GOOGLE_CLOUD_STORAGE = "google_cloud_storage"
|
||||||
OCI_STORAGE = "oci_storage"
|
OCI_STORAGE = "oci_storage"
|
||||||
|
S3_COMPATIBLE = "s3_compatible"
|
||||||
|
|
||||||
|
|
||||||
class DocumentSource(str, Enum):
|
class DocumentSource(str, Enum):
|
||||||
@ -47,6 +48,7 @@ class DocumentSource(str, Enum):
|
|||||||
GOOGLE_DRIVE = "google_drive"
|
GOOGLE_DRIVE = "google_drive"
|
||||||
GMAIL = "gmail"
|
GMAIL = "gmail"
|
||||||
DISCORD = "discord"
|
DISCORD = "discord"
|
||||||
|
S3_COMPATIBLE = "s3_compatible"
|
||||||
|
|
||||||
|
|
||||||
class FileOrigin(str, Enum):
|
class FileOrigin(str, Enum):
|
||||||
|
|||||||
@ -311,6 +311,13 @@ def create_s3_client(bucket_type: BlobType, credentials: dict[str, Any], europea
|
|||||||
aws_secret_access_key=credentials["secret_access_key"],
|
aws_secret_access_key=credentials["secret_access_key"],
|
||||||
region_name=credentials["region"],
|
region_name=credentials["region"],
|
||||||
)
|
)
|
||||||
|
elif bucket_type == BlobType.S3_COMPATIBLE:
|
||||||
|
return boto3.client(
|
||||||
|
"s3",
|
||||||
|
endpoint_url=credentials["endpoint_url"],
|
||||||
|
aws_access_key_id=credentials["aws_access_key_id"],
|
||||||
|
aws_secret_access_key=credentials["aws_secret_access_key"],
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported bucket type: {bucket_type}")
|
raise ValueError(f"Unsupported bucket type: {bucket_type}")
|
||||||
|
|||||||
@ -71,7 +71,7 @@ for arg in "$@"; do
|
|||||||
ENABLE_TASKEXECUTOR=0
|
ENABLE_TASKEXECUTOR=0
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--disable-datasyn)
|
--disable-datasync)
|
||||||
ENABLE_DATASYNC=0
|
ENABLE_DATASYNC=0
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -32,7 +33,6 @@ from rag.nlp import is_english
|
|||||||
from rag.prompts.generator import vision_llm_describe_prompt
|
from rag.prompts.generator import vision_llm_describe_prompt
|
||||||
from common.token_utils import num_tokens_from_string, total_token_count_from_response
|
from common.token_utils import num_tokens_from_string, total_token_count_from_response
|
||||||
|
|
||||||
|
|
||||||
class Base(ABC):
|
class Base(ABC):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
# Configure retry parameters
|
# Configure retry parameters
|
||||||
@ -208,6 +208,7 @@ class GptV4(Base):
|
|||||||
model=self.model_name,
|
model=self.model_name,
|
||||||
messages=self.prompt(b64),
|
messages=self.prompt(b64),
|
||||||
extra_body=self.extra_body,
|
extra_body=self.extra_body,
|
||||||
|
unused = None,
|
||||||
)
|
)
|
||||||
return res.choices[0].message.content.strip(), total_token_count_from_response(res)
|
return res.choices[0].message.content.strip(), total_token_count_from_response(res)
|
||||||
|
|
||||||
@ -324,6 +325,122 @@ class Zhipu4V(GptV4):
|
|||||||
Base.__init__(self, **kwargs)
|
Base.__init__(self, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_conf(self, gen_conf):
|
||||||
|
if "max_tokens" in gen_conf:
|
||||||
|
del gen_conf["max_tokens"]
|
||||||
|
gen_conf = self._clean_conf_plealty(gen_conf)
|
||||||
|
return gen_conf
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_conf_plealty(self, gen_conf):
|
||||||
|
if "presence_penalty" in gen_conf:
|
||||||
|
del gen_conf["presence_penalty"]
|
||||||
|
if "frequency_penalty" in gen_conf:
|
||||||
|
del gen_conf["frequency_penalty"]
|
||||||
|
return gen_conf
|
||||||
|
|
||||||
|
|
||||||
|
def _request(self, msg, stream, gen_conf={}):
|
||||||
|
response = requests.post(
|
||||||
|
self.base_url,
|
||||||
|
json={
|
||||||
|
"model": self.model_name,
|
||||||
|
"messages": msg,
|
||||||
|
"stream": stream,
|
||||||
|
**gen_conf
|
||||||
|
},
|
||||||
|
headers= {
|
||||||
|
"Authorization": f"Bearer {self.api_key}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
|
||||||
|
def chat(self, system, history, gen_conf, images=None, stream=False, **kwargs):
|
||||||
|
if system and history and history[0].get("role") != "system":
|
||||||
|
history.insert(0, {"role": "system", "content": system})
|
||||||
|
|
||||||
|
gen_conf = self._clean_conf(gen_conf)
|
||||||
|
|
||||||
|
logging.info(json.dumps(history, ensure_ascii=False, indent=2))
|
||||||
|
response = self.client.chat.completions.create(model=self.model_name, messages=self._form_history(system, history, images), stream=False, **gen_conf)
|
||||||
|
content = response.choices[0].message.content.strip()
|
||||||
|
|
||||||
|
cleaned = re.sub(r"<\|(begin_of_box|end_of_box)\|>", "", content).strip()
|
||||||
|
return cleaned, total_token_count_from_response(response)
|
||||||
|
|
||||||
|
|
||||||
|
def chat_streamly(self, system, history, gen_conf, images=None, **kwargs):
|
||||||
|
from rag.llm.chat_model import LENGTH_NOTIFICATION_CN, LENGTH_NOTIFICATION_EN
|
||||||
|
from rag.nlp import is_chinese
|
||||||
|
|
||||||
|
if system and history and history[0].get("role") != "system":
|
||||||
|
history.insert(0, {"role": "system", "content": system})
|
||||||
|
gen_conf = self._clean_conf(gen_conf)
|
||||||
|
ans = ""
|
||||||
|
tk_count = 0
|
||||||
|
try:
|
||||||
|
logging.info(json.dumps(history, ensure_ascii=False, indent=2))
|
||||||
|
response = self.client.chat.completions.create(model=self.model_name, messages=self._form_history(system, history, images), stream=True, **gen_conf)
|
||||||
|
for resp in response:
|
||||||
|
if not resp.choices[0].delta.content:
|
||||||
|
continue
|
||||||
|
delta = resp.choices[0].delta.content
|
||||||
|
ans = delta
|
||||||
|
if resp.choices[0].finish_reason == "length":
|
||||||
|
if is_chinese(ans):
|
||||||
|
ans += LENGTH_NOTIFICATION_CN
|
||||||
|
else:
|
||||||
|
ans += LENGTH_NOTIFICATION_EN
|
||||||
|
tk_count = total_token_count_from_response(resp)
|
||||||
|
if resp.choices[0].finish_reason == "stop":
|
||||||
|
tk_count = total_token_count_from_response(resp)
|
||||||
|
yield ans
|
||||||
|
except Exception as e:
|
||||||
|
yield ans + "\n**ERROR**: " + str(e)
|
||||||
|
|
||||||
|
yield tk_count
|
||||||
|
|
||||||
|
|
||||||
|
def describe(self, image):
|
||||||
|
return self.describe_with_prompt(image)
|
||||||
|
|
||||||
|
|
||||||
|
def describe_with_prompt(self, image, prompt=None):
|
||||||
|
b64 = self.image2base64(image)
|
||||||
|
if prompt is None:
|
||||||
|
prompt = "Describe this image."
|
||||||
|
|
||||||
|
# Chat messages
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": { "url": b64 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": prompt
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
resp = self.client.chat.completions.create(
|
||||||
|
model=self.model_name,
|
||||||
|
messages=messages,
|
||||||
|
stream=False
|
||||||
|
)
|
||||||
|
|
||||||
|
content = resp.choices[0].message.content.strip()
|
||||||
|
cleaned = re.sub(r"<\|(begin_of_box|end_of_box)\|>", "", content).strip()
|
||||||
|
|
||||||
|
return cleaned, num_tokens_from_string(cleaned)
|
||||||
|
|
||||||
|
|
||||||
class StepFunCV(GptV4):
|
class StepFunCV(GptV4):
|
||||||
_FACTORY_NAME = "StepFun"
|
_FACTORY_NAME = "StepFun"
|
||||||
|
|
||||||
|
|||||||
@ -67,6 +67,7 @@ export interface FormFieldConfig {
|
|||||||
) => string | boolean | Promise<string | boolean>;
|
) => string | boolean | Promise<string | boolean>;
|
||||||
dependencies?: string[];
|
dependencies?: string[];
|
||||||
schema?: ZodSchema;
|
schema?: ZodSchema;
|
||||||
|
shouldRender?: (formValues: any) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component props interface
|
// Component props interface
|
||||||
@ -654,6 +655,9 @@ const DynamicForm = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Watch all form values to re-render when they change (for shouldRender checks)
|
||||||
|
const formValues = form.watch();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
@ -664,11 +668,19 @@ const DynamicForm = {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{fields.map((field) => (
|
{fields.map((field) => {
|
||||||
<div key={field.name} className={cn({ hidden: field.hidden })}>
|
const shouldShow = field.shouldRender
|
||||||
{renderField(field)}
|
? field.shouldRender(formValues)
|
||||||
</div>
|
: true;
|
||||||
))}
|
return (
|
||||||
|
<div
|
||||||
|
key={field.name}
|
||||||
|
className={cn({ hidden: field.hidden || !shouldShow })}
|
||||||
|
>
|
||||||
|
{renderField(field)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
{children}
|
{children}
|
||||||
</>
|
</>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -169,3 +169,13 @@ export const SwitchOperatorOptions = [
|
|||||||
icon: <CircleSlash2 className="size-4" />,
|
icon: <CircleSlash2 className="size-4" />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const AgentStructuredOutputField = 'structured';
|
||||||
|
|
||||||
|
export enum JsonSchemaDataType {
|
||||||
|
String = 'string',
|
||||||
|
Number = 'number',
|
||||||
|
Boolean = 'boolean',
|
||||||
|
Array = 'array',
|
||||||
|
Object = 'object',
|
||||||
|
}
|
||||||
|
|||||||
@ -705,6 +705,8 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s
|
|||||||
'The base URL of your Confluence instance (e.g., https://your-domain.atlassian.net/wiki)',
|
'The base URL of your Confluence instance (e.g., https://your-domain.atlassian.net/wiki)',
|
||||||
s3PrefixTip: `Specify the folder path within your S3 bucket to fetch files from.
|
s3PrefixTip: `Specify the folder path within your S3 bucket to fetch files from.
|
||||||
Example: general/v2/`,
|
Example: general/v2/`,
|
||||||
|
S3CompatibleEndpointUrlTip: `Required for S3 compatible Storage Box. Specify the S3-compatible endpoint URL.
|
||||||
|
Example: https://fsn1.your-objectstorage.com`,
|
||||||
addDataSourceModalTital: 'Create your {{name}} connector',
|
addDataSourceModalTital: 'Create your {{name}} connector',
|
||||||
deleteSourceModalTitle: 'Delete data source',
|
deleteSourceModalTitle: 'Delete data source',
|
||||||
deleteSourceModalContent: `
|
deleteSourceModalContent: `
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
AgentGlobals,
|
AgentGlobals,
|
||||||
AgentGlobalsSysQueryWithBrace,
|
AgentGlobalsSysQueryWithBrace,
|
||||||
|
AgentStructuredOutputField,
|
||||||
CodeTemplateStrMap,
|
CodeTemplateStrMap,
|
||||||
ComparisonOperator,
|
ComparisonOperator,
|
||||||
Operator,
|
Operator,
|
||||||
@ -12,7 +13,11 @@ import {
|
|||||||
SwitchOperatorOptions,
|
SwitchOperatorOptions,
|
||||||
initialLlmBaseValues,
|
initialLlmBaseValues,
|
||||||
} from '@/constants/agent';
|
} from '@/constants/agent';
|
||||||
export { Operator } from '@/constants/agent';
|
export {
|
||||||
|
AgentStructuredOutputField,
|
||||||
|
JsonSchemaDataType,
|
||||||
|
Operator,
|
||||||
|
} from '@/constants/agent';
|
||||||
|
|
||||||
export * from './pipeline';
|
export * from './pipeline';
|
||||||
|
|
||||||
@ -441,8 +446,6 @@ export const initialCodeValues = {
|
|||||||
|
|
||||||
export const initialWaitingDialogueValues = {};
|
export const initialWaitingDialogueValues = {};
|
||||||
|
|
||||||
export const AgentStructuredOutputField = 'structured';
|
|
||||||
|
|
||||||
export const initialAgentValues = {
|
export const initialAgentValues = {
|
||||||
...initialLlmBaseValues,
|
...initialLlmBaseValues,
|
||||||
description: '',
|
description: '',
|
||||||
@ -839,14 +842,6 @@ export const DROPDOWN_HORIZONTAL_OFFSET = 28;
|
|||||||
export const DROPDOWN_VERTICAL_OFFSET = 74;
|
export const DROPDOWN_VERTICAL_OFFSET = 74;
|
||||||
export const PREVENT_CLOSE_DELAY = 300;
|
export const PREVENT_CLOSE_DELAY = 300;
|
||||||
|
|
||||||
export enum JsonSchemaDataType {
|
|
||||||
String = 'string',
|
|
||||||
Number = 'number',
|
|
||||||
Boolean = 'boolean',
|
|
||||||
Array = 'array',
|
|
||||||
Object = 'object',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum VariableAssignerLogicalOperator {
|
export enum VariableAssignerLogicalOperator {
|
||||||
Overwrite = 'overwrite',
|
Overwrite = 'overwrite',
|
||||||
Clear = 'clear',
|
Clear = 'clear',
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { Editor } from '@monaco-editor/react';
|
import Editor, { loader } from '@monaco-editor/react';
|
||||||
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { ReactNode, useCallback } from 'react';
|
import { ReactNode, useCallback } from 'react';
|
||||||
@ -23,6 +23,8 @@ import { DynamicFormHeader } from '../components/dynamic-fom-header';
|
|||||||
import { QueryVariable } from '../components/query-variable';
|
import { QueryVariable } from '../components/query-variable';
|
||||||
import { useBuildLogicalOptions } from './use-build-logical-options';
|
import { useBuildLogicalOptions } from './use-build-logical-options';
|
||||||
|
|
||||||
|
loader.config({ paths: { vs: '/vs' } });
|
||||||
|
|
||||||
type SelectKeysProps = {
|
type SelectKeysProps = {
|
||||||
name: string;
|
name: string;
|
||||||
label: ReactNode;
|
label: ReactNode;
|
||||||
@ -70,7 +72,7 @@ const EmptyValueMap = {
|
|||||||
[JsonSchemaDataType.String]: '',
|
[JsonSchemaDataType.String]: '',
|
||||||
[JsonSchemaDataType.Number]: 0,
|
[JsonSchemaDataType.Number]: 0,
|
||||||
[JsonSchemaDataType.Boolean]: 'yes',
|
[JsonSchemaDataType.Boolean]: 'yes',
|
||||||
[JsonSchemaDataType.Object]: {},
|
[JsonSchemaDataType.Object]: '{}',
|
||||||
[JsonSchemaDataType.Array]: [],
|
[JsonSchemaDataType.Array]: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ export function DynamicVariables({
|
|||||||
const { getType } = useGetVariableLabelOrTypeByValue();
|
const { getType } = useGetVariableLabelOrTypeByValue();
|
||||||
const isDarkTheme = useIsDarkTheme();
|
const isDarkTheme = useIsDarkTheme();
|
||||||
|
|
||||||
const { fields, remove, append, update } = useFieldArray({
|
const { fields, remove, append } = useFieldArray({
|
||||||
name: name,
|
name: name,
|
||||||
control: form.control,
|
control: form.control,
|
||||||
});
|
});
|
||||||
@ -102,15 +104,7 @@ export function DynamicVariables({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderParameter = useCallback(
|
const renderParameter = useCallback(
|
||||||
(
|
(keyFieldName: string, operatorFieldName: string) => {
|
||||||
keyFieldName: string,
|
|
||||||
operatorFieldName: string,
|
|
||||||
valueFieldAlias: string,
|
|
||||||
) => {
|
|
||||||
console.log(
|
|
||||||
'🚀 ~ DynamicVariables ~ valueFieldAlias:',
|
|
||||||
form.getValues(valueFieldAlias),
|
|
||||||
);
|
|
||||||
const logicalOperator = form.getValues(operatorFieldName);
|
const logicalOperator = form.getValues(operatorFieldName);
|
||||||
const type = getVariableType(keyFieldName);
|
const type = getVariableType(keyFieldName);
|
||||||
|
|
||||||
@ -169,10 +163,6 @@ export function DynamicVariables({
|
|||||||
|
|
||||||
const handleVariableChange = useCallback(
|
const handleVariableChange = useCallback(
|
||||||
(operatorFieldAlias: string, valueFieldAlias: string) => {
|
(operatorFieldAlias: string, valueFieldAlias: string) => {
|
||||||
console.log(
|
|
||||||
'🚀 ~ DynamicVariables ~ operatorFieldAlias:',
|
|
||||||
operatorFieldAlias,
|
|
||||||
);
|
|
||||||
return () => {
|
return () => {
|
||||||
form.setValue(
|
form.setValue(
|
||||||
operatorFieldAlias,
|
operatorFieldAlias,
|
||||||
@ -190,14 +180,8 @@ export function DynamicVariables({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleOperatorChange = useCallback(
|
const handleOperatorChange = useCallback(
|
||||||
(
|
(valueFieldAlias: string, keyFieldAlias: string, value: string) => {
|
||||||
valueFieldAlias: string,
|
|
||||||
keyFieldAlias: string,
|
|
||||||
value: string,
|
|
||||||
index: number,
|
|
||||||
) => {
|
|
||||||
const type = getVariableType(keyFieldAlias);
|
const type = getVariableType(keyFieldAlias);
|
||||||
console.log('🚀 ~ DynamicVariables ~ type:', type);
|
|
||||||
|
|
||||||
let parameter = EmptyValueMap[type as keyof typeof EmptyValueMap];
|
let parameter = EmptyValueMap[type as keyof typeof EmptyValueMap];
|
||||||
|
|
||||||
@ -210,10 +194,6 @@ export function DynamicVariables({
|
|||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// form.trigger(valueFieldAlias);
|
|
||||||
|
|
||||||
// update(index, { [valueField]: parameter });
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[form, getVariableType],
|
[form, getVariableType],
|
||||||
@ -258,7 +238,6 @@ export function DynamicVariables({
|
|||||||
valueFieldAlias,
|
valueFieldAlias,
|
||||||
keyFieldAlias,
|
keyFieldAlias,
|
||||||
val,
|
val,
|
||||||
index,
|
|
||||||
);
|
);
|
||||||
onChange(val);
|
onChange(val);
|
||||||
}}
|
}}
|
||||||
@ -270,11 +249,7 @@ export function DynamicVariables({
|
|||||||
</RAGFlowFormItem>
|
</RAGFlowFormItem>
|
||||||
</div>
|
</div>
|
||||||
<RAGFlowFormItem name={valueFieldAlias} className="w-full">
|
<RAGFlowFormItem name={valueFieldAlias} className="w-full">
|
||||||
{renderParameter(
|
{renderParameter(keyFieldAlias, operatorFieldAlias)}
|
||||||
keyFieldAlias,
|
|
||||||
operatorFieldAlias,
|
|
||||||
valueFieldAlias,
|
|
||||||
)}
|
|
||||||
</RAGFlowFormItem>
|
</RAGFlowFormItem>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,6 @@ function VariableAssignerForm({ node }: INextOperatorForm) {
|
|||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
shouldUnregister: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
useWatchFormChange(node?.id, form, true);
|
useWatchFormChange(node?.id, form, true);
|
||||||
|
|||||||
@ -15,27 +15,30 @@ export const useHandleForm = () => {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSubmit = useCallback(async (fieldValue: FieldValues) => {
|
const handleSubmit = useCallback(
|
||||||
const param = {
|
async (fieldValue: FieldValues) => {
|
||||||
...(data.dsl?.variables || {}),
|
const param = {
|
||||||
[fieldValue.name]: {
|
...(data.dsl?.variables || {}),
|
||||||
...fieldValue,
|
[fieldValue.name]: {
|
||||||
value:
|
...fieldValue,
|
||||||
fieldValue.type === TypesWithArray.Object ||
|
value:
|
||||||
fieldValue.type === TypesWithArray.ArrayObject
|
fieldValue.type === TypesWithArray.Object ||
|
||||||
? handleObjectData(fieldValue.value)
|
fieldValue.type === TypesWithArray.ArrayObject
|
||||||
: fieldValue.value,
|
? handleObjectData(fieldValue.value)
|
||||||
},
|
: fieldValue.value,
|
||||||
} as Record<string, GlobalVariableType>;
|
},
|
||||||
|
} as Record<string, GlobalVariableType>;
|
||||||
|
|
||||||
const res = await saveGraph(undefined, {
|
const res = await saveGraph(undefined, {
|
||||||
globalVariables: param,
|
globalVariables: param,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
refetch();
|
refetch();
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[data.dsl?.variables, refetch, saveGraph],
|
||||||
|
);
|
||||||
|
|
||||||
return { handleSubmit, loading };
|
return { handleSubmit, loading };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { AgentGlobals } from '@/constants/agent';
|
import { AgentGlobals, AgentStructuredOutputField } from '@/constants/agent';
|
||||||
import { useFetchAgent } from '@/hooks/use-agent-request';
|
import { useFetchAgent } from '@/hooks/use-agent-request';
|
||||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||||
import { buildNodeOutputOptions } from '@/utils/canvas-util';
|
import { buildNodeOutputOptions, isAgentStructured } from '@/utils/canvas-util';
|
||||||
import { DefaultOptionType } from 'antd/es/select';
|
import { DefaultOptionType } from 'antd/es/select';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { isEmpty, toLower } from 'lodash';
|
import { isEmpty, toLower } from 'lodash';
|
||||||
@ -236,7 +236,11 @@ export function useFilterQueryVariableOptionsByTypes(
|
|||||||
toLower(x).startsWith('array')
|
toLower(x).startsWith('array')
|
||||||
? toLower(y.type).includes(toLower(x))
|
? toLower(y.type).includes(toLower(x))
|
||||||
: toLower(y.type) === toLower(x),
|
: toLower(y.type) === toLower(x),
|
||||||
) || y.type === undefined, // agent structured output
|
) ||
|
||||||
|
isAgentStructured(
|
||||||
|
y.value,
|
||||||
|
y.value.slice(-AgentStructuredOutputField.length),
|
||||||
|
), // agent structured output
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
@ -105,9 +105,21 @@ export const DataSourceFormFields = {
|
|||||||
{ label: 'R2', value: 'r2' },
|
{ label: 'R2', value: 'r2' },
|
||||||
{ label: 'Google Cloud Storage', value: 'google_cloud_storage' },
|
{ label: 'Google Cloud Storage', value: 'google_cloud_storage' },
|
||||||
{ label: 'OCI Storage', value: 'oci_storage' },
|
{ label: 'OCI Storage', value: 'oci_storage' },
|
||||||
|
{ label: 'S3 Compatible', value: 's3_compatible' },
|
||||||
],
|
],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Endpoint URL',
|
||||||
|
name: 'config.credentials.endpoint_url',
|
||||||
|
type: FormFieldType.Text,
|
||||||
|
required: false,
|
||||||
|
placeholder: 'https://fsn1.your-objectstorage.com',
|
||||||
|
tooltip: t('setting.S3CompatibleEndpointUrlTip'),
|
||||||
|
shouldRender: (formValues) => {
|
||||||
|
return formValues?.config?.bucket_type === 's3_compatible';
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Prefix',
|
label: 'Prefix',
|
||||||
name: 'config.prefix',
|
name: 'config.prefix',
|
||||||
@ -483,6 +495,7 @@ export const DataSourceFormDefaultValues = {
|
|||||||
credentials: {
|
credentials: {
|
||||||
aws_access_key_id: '',
|
aws_access_key_id: '',
|
||||||
aws_secret_access_key: '',
|
aws_secret_access_key: '',
|
||||||
|
endpoint_url: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
|
import {
|
||||||
|
AgentStructuredOutputField,
|
||||||
|
JsonSchemaDataType,
|
||||||
|
Operator,
|
||||||
|
} from '@/constants/agent';
|
||||||
import { BaseNode } from '@/interfaces/database/agent';
|
import { BaseNode } from '@/interfaces/database/agent';
|
||||||
|
|
||||||
import { Edge } from '@xyflow/react';
|
import { Edge } from '@xyflow/react';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { ComponentType, ReactNode } from 'react';
|
import { ComponentType, ReactNode } from 'react';
|
||||||
@ -23,6 +29,12 @@ export function filterAllUpstreamNodeIds(edges: Edge[], nodeIds: string[]) {
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isAgentStructured(id?: string, label?: string) {
|
||||||
|
return (
|
||||||
|
label === AgentStructuredOutputField && id?.startsWith(`${Operator.Agent}:`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function buildOutputOptions(
|
export function buildOutputOptions(
|
||||||
outputs: Record<string, any> = {},
|
outputs: Record<string, any> = {},
|
||||||
nodeId?: string,
|
nodeId?: string,
|
||||||
@ -34,7 +46,9 @@ export function buildOutputOptions(
|
|||||||
value: `${nodeId}@${x}`,
|
value: `${nodeId}@${x}`,
|
||||||
parentLabel,
|
parentLabel,
|
||||||
icon,
|
icon,
|
||||||
type: outputs[x]?.type,
|
type: isAgentStructured(nodeId, x)
|
||||||
|
? JsonSchemaDataType.Object
|
||||||
|
: outputs[x]?.type,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user