Przeglądaj źródła

Merge branch 'alpha' into refactor_relay

# Conflicts:
#	dto/openai_image.go
CaIon 4 miesięcy temu
rodzic
commit
edeb4791c9

+ 13 - 10
dto/openai_image.go

@@ -9,19 +9,22 @@ import (
 )
 
 type ImageRequest struct {
-	Model          string          `json:"model"`
-	Prompt         string          `json:"prompt" binding:"required"`
-	N              uint            `json:"n,omitempty"`
+	Model             string          `json:"model"`
+	Prompt            string          `json:"prompt" binding:"required"`
+	N                 uint            `json:"n,omitempty"`
 	Size           string          `json:"size,omitempty"`
 	Quality        string          `json:"quality,omitempty"`
 	ResponseFormat string          `json:"response_format,omitempty"`
-	Style          string          `json:"style,omitempty"`
-	User           string          `json:"user,omitempty"`
-	ExtraFields    json.RawMessage `json:"extra_fields,omitempty"`
-	Background     string          `json:"background,omitempty"`
-	Moderation     string          `json:"moderation,omitempty"`
-	OutputFormat   string          `json:"output_format,omitempty"`
-	Watermark      *bool           `json:"watermark,omitempty"`
+	Style          json.RawMessage `json:"style,omitempty"`
+	User              json.RawMessage `json:"user,omitempty"`
+	ExtraFields       json.RawMessage `json:"extra_fields,omitempty"`
+	Background        json.RawMessage `json:"background,omitempty"`
+	Moderation        json.RawMessage `json:"moderation,omitempty"`
+	OutputFormat      json.RawMessage `json:"output_format,omitempty"`
+	OutputCompression json.RawMessage `json:"output_compression,omitempty"`
+	PartialImages     json.RawMessage `json:"partial_images,omitempty"`
+	// Stream            bool            `json:"stream,omitempty"`
+	Watermark *bool `json:"watermark,omitempty"`
 }
 
 func (i *ImageRequest) GetTokenCountMeta() *types.TokenCountMeta {

+ 4 - 2
middleware/auth.go

@@ -197,8 +197,10 @@ func TokenAuth() func(c *gin.Context) {
 		// 或者是否 x-api-key 不为空且存在anthropic-version
 		// 谁知道有多少不符合规范没写anthropic-version的
 		// 所以就这样随它去吧(
-		if strings.Contains(c.Request.URL.Path, "/v1/messages") || (anthropicKey != "" && c.Request.Header.Get("anthropic-version") != "") {
-			c.Request.Header.Set("Authorization", "Bearer "+anthropicKey)
+		if strings.Contains(c.Request.URL.Path, "/v1/messages") {
+			if anthropicKey != "" {
+				c.Request.Header.Set("Authorization", "Bearer "+anthropicKey)
+			}
 		}
 		// gemini api 从query中获取key
 		if strings.HasPrefix(c.Request.URL.Path, "/v1beta/models") ||

+ 3 - 1
web/src/components/table/model-pricing/layout/header/PricingTopSection.jsx

@@ -35,6 +35,7 @@ const PricingTopSection = ({
   models,
   filteredModels,
   loading,
+  searchValue,
   t
 }) => {
   const [showFilterModal, setShowFilterModal] = useState(false);
@@ -46,6 +47,7 @@ const PricingTopSection = ({
         <Input
           prefix={<IconSearch />}
           placeholder={t('模糊搜索模型名称')}
+          value={searchValue}
           onCompositionStart={handleCompositionStart}
           onCompositionEnd={handleCompositionEnd}
           onChange={handleChange}
@@ -78,7 +80,7 @@ const PricingTopSection = ({
         </Button>
       )}
     </div>
-  ), [selectedRowKeys, t, handleCompositionStart, handleCompositionEnd, handleChange, copyText, isMobile]);
+  ), [selectedRowKeys, t, handleCompositionStart, handleCompositionEnd, handleChange, copyText, isMobile, searchValue]);
 
   return (
     <>

+ 11 - 15
web/src/components/table/model-pricing/view/card/PricingCardView.jsx

@@ -128,19 +128,6 @@ const PricingCardView = ({
     return record.description || '';
   };
 
-  // 渲染价格信息
-  const renderPriceInfo = (record) => {
-    const priceData = calculateModelPrice({
-      record,
-      selectedGroup,
-      groupRatio,
-      tokenUnit,
-      displayPrice,
-      currency,
-    });
-    return formatPriceInfo(priceData, t);
-  };
-
   // 渲染标签
   const renderTags = (record) => {
     // 计费类型标签(左边)
@@ -221,6 +208,15 @@ const PricingCardView = ({
           const modelKey = getModelKey(model);
           const isSelected = selectedRowKeys.includes(modelKey);
 
+          const priceData = calculateModelPrice({
+            record: model,
+            selectedGroup,
+            groupRatio,
+            tokenUnit,
+            displayPrice,
+            currency,
+          });
+
           return (
             <Card
               key={modelKey || index}
@@ -238,7 +234,7 @@ const PricingCardView = ({
                         {model.model_name}
                       </h3>
                       <div className="flex items-center gap-3 text-xs mt-1">
-                        {renderPriceInfo(model)}
+                        {formatPriceInfo(priceData, t)}
                       </div>
                     </div>
                   </div>
@@ -313,7 +309,7 @@ const PricingCardView = ({
                           {t('补全')}: {model.quota_type === 0 ? parseFloat(model.completion_ratio.toFixed(3)) : t('无')}
                         </div>
                         <div>
-                          {t('分组')}: {priceData.usedGroupRatio}
+                          {t('分组')}: {priceData?.usedGroupRatio ?? '-'}
                         </div>
                       </div>
                     </div>

+ 25 - 13
web/src/components/table/model-pricing/view/table/PricingTableColumns.js

@@ -98,6 +98,25 @@ export const getPricingTableColumns = ({
   displayPrice,
   showRatio,
 }) => {
+
+  const priceDataCache = new WeakMap();
+
+  const getPriceData = (record) => {
+    let cache = priceDataCache.get(record);
+    if (!cache) {
+      cache = calculateModelPrice({
+        record,
+        selectedGroup,
+        groupRatio,
+        tokenUnit,
+        displayPrice,
+        currency,
+      });
+      priceDataCache.set(record, cache);
+    }
+    return cache;
+  };
+
   const endpointColumn = {
     title: t('可用端点类型'),
     dataIndex: 'supported_endpoint_types',
@@ -167,21 +186,21 @@ export const getPricingTableColumns = ({
     dataIndex: 'model_ratio',
     render: (text, record, index) => {
       const completionRatio = parseFloat(record.completion_ratio.toFixed(3));
-      const content = (
+      const priceData = getPriceData(record);
+
+      return (
         <div className="space-y-1">
           <div className="text-gray-700">
             {t('模型倍率')}:{record.quota_type === 0 ? text : t('无')}
           </div>
           <div className="text-gray-700">
-            {t('补全倍率')}:
-            {record.quota_type === 0 ? completionRatio : t('无')}
+            {t('补全倍率')}:{record.quota_type === 0 ? completionRatio : t('无')}
           </div>
           <div className="text-gray-700">
-            {t('分组倍率')}:{groupRatio[selectedGroup]}
+            {t('分组倍率')}:{priceData?.usedGroupRatio ?? '-'}
           </div>
         </div>
       );
-      return content;
     },
   };
 
@@ -190,14 +209,7 @@ export const getPricingTableColumns = ({
     dataIndex: 'model_price',
     fixed: 'right',
     render: (text, record, index) => {
-      const priceData = calculateModelPrice({
-        record,
-        selectedGroup,
-        groupRatio,
-        tokenUnit,
-        displayPrice,
-        currency
-      });
+      const priceData = getPriceData(record);
 
       if (priceData.isPerToken) {
         return (

+ 3 - 5
web/src/components/table/tokens/TokensColumnDefs.js

@@ -305,6 +305,7 @@ const renderOperations = (text, record, onOpenLink, setEditingToken, setShowEdit
           node: 'item',
           key: i,
           name,
+          value: item[name],
           onClick: () => onOpenLink(name, item[name], record),
         });
       }
@@ -326,11 +327,8 @@ const renderOperations = (text, record, onOpenLink, setEditingToken, setShowEdit
             if (chatsArray.length === 0) {
               showError(t('请联系管理员配置聊天链接'));
             } else {
-              onOpenLink(
-                'default',
-                chatsArray[0].name ? (parsed => parsed)(localStorage.getItem('chats')) : '',
-                record,
-              );
+              const first = chatsArray[0];
+              onOpenLink(first.name, first.value, record);
             }
           }}
         >

+ 0 - 5
web/src/hooks/model-pricing/useModelPricingData.js

@@ -211,9 +211,6 @@ export const useModelPricingData = () => {
   };
 
   const handleChange = (value) => {
-    if (compositionRef.current.isComposition) {
-      return;
-    }
     const newSearchValue = value ? value : '';
     setSearchValue(newSearchValue);
   };
@@ -231,9 +228,7 @@ export const useModelPricingData = () => {
 
   const handleGroupClick = (group) => {
     setSelectedGroup(group);
-    // 同时将分组过滤设置为该分组
     setFilterGroup(group);
-
     if (group === 'all') {
       showInfo(t('已切换至最优倍率视图,每个模型使用其最低倍率分组'));
     } else {

+ 5 - 12
web/src/hooks/model-pricing/usePricingFilterCounts.js

@@ -104,34 +104,27 @@ export const usePricingFilterCounts = ({
   // 生成不同视图所需的模型集合
   const quotaTypeModels = useMemo(
     () => allModels.filter((m) => matchesFilters(m, ['quota'])),
-    [allModels, filterGroup, filterEndpointType, filterVendor, filterTag]
+    [allModels, filterGroup, filterEndpointType, filterVendor, filterTag, searchValue]
   );
 
   const endpointTypeModels = useMemo(
     () => allModels.filter((m) => matchesFilters(m, ['endpoint'])),
-    [allModels, filterGroup, filterQuotaType, filterVendor, filterTag]
+    [allModels, filterGroup, filterQuotaType, filterVendor, filterTag, searchValue]
   );
 
   const vendorModels = useMemo(
     () => allModels.filter((m) => matchesFilters(m, ['vendor'])),
-    [allModels, filterGroup, filterQuotaType, filterEndpointType, filterTag]
+    [allModels, filterGroup, filterQuotaType, filterEndpointType, filterTag, searchValue]
   );
 
   const tagModels = useMemo(
     () => allModels.filter((m) => matchesFilters(m, ['tag'])),
-    [allModels, filterGroup, filterQuotaType, filterEndpointType, filterVendor]
+    [allModels, filterGroup, filterQuotaType, filterEndpointType, filterVendor, searchValue]
   );
 
   const groupCountModels = useMemo(
     () => allModels.filter((m) => matchesFilters(m, ['group'])),
-    [
-      allModels,
-      filterQuotaType,
-      filterEndpointType,
-      filterVendor,
-      filterTag,
-      searchValue,
-    ]
+    [allModels, filterQuotaType, filterEndpointType, filterVendor, filterTag, searchValue]
   );
 
   return {