通義靈碼企業(yè)過濾器配置 - 安全策略優(yōu)化指南

2025-04-21 16:43 更新

9.4.1. 企業(yè)過濾器配置

通義靈碼靈碼企業(yè)版的管理員、組織內(nèi)全局管理員(專屬版)可以為企業(yè)的開發(fā)者配置智能問答、行間生成、知識庫上傳時的安全過濾策略。

適用版本

企業(yè)標(biāo)準(zhǔn)版、企業(yè)專屬版

功能入口

  1. 使用通義靈碼靈碼管理員、組織內(nèi)全局管理員(僅適用于企業(yè)專屬版)賬號登錄通義靈碼靈碼控制臺,在左側(cè)導(dǎo)航欄選擇策略配置 > 過濾器配置

  2. 根據(jù)過濾器應(yīng)用的場景,在頂部標(biāo)簽頁選擇智能問答行間生成知識庫上傳(僅適用于企業(yè)專屬版)。

  3. 根據(jù)需求開啟相應(yīng)過濾器的開關(guān),然后配置相關(guān)參數(shù)。各場景支持的過濾器類型如下:

場景

過濾器類型

說明

智能問答

智能問答前置過濾器

使用通義靈碼靈碼IDE插件的智能問答功能時,用戶輸入給大模型的內(nèi)容將通過前置過濾器,大模型輸出的內(nèi)容將通過后置過濾器。

智能問答后置過濾器

行間生成

行間生成前置過濾器

使用通義靈碼靈碼IDE插件的行間生成功能時,用戶輸入給大模型的內(nèi)容將通過前置過濾器,大模型輸出的內(nèi)容將通過后置過濾器。

行間生成后置過濾器

知識庫上傳

知識庫上傳前置過濾器

上傳至通義靈碼靈碼知識庫的文件須先通過該過濾器的審核后,方可上傳成功。

重要
  • 請確保將開發(fā)者的通義靈碼靈碼 IDE 插件升級到 V1.4.0 及以上,配置的過濾器方可生效。
  • 智能問答過濾器、行間生成過濾器啟用或修改后,預(yù)計需要 5~10 分鐘才對開發(fā)者使用的通義靈碼靈碼 IDE 插件生效。
  • 知識庫上傳過濾器啟用或修改后,立即生效,上傳企業(yè)知識庫文件時會進(jìn)行過濾。

智能問答、行間生成的前置過濾器配置

方式一:正則表達(dá)式配置

說明

管理員在配置正則表達(dá)式時需要充分驗(yàn)證,以避免開發(fā)者使用IDE 插件時性能下降或產(chǎn)生其他異常問題。

  • 處理方式:支持通過正則表達(dá)式的方式配置過濾器,且支持 3 種模式。

匹配規(guī)則時不處理

匹配到正則后,不做任何處理。

匹配規(guī)則時攔截

匹配到正則后,直接攔截請求,阻斷模型請求。

匹配規(guī)則時替換內(nèi)容

匹配到正則后,按照配置替換內(nèi)容。

  • 消息通知:支持開啟消息通知,通過 webhook 的方式,推送到所需要的消息接收平臺。

  • 執(zhí)行順序:按照配置的排序執(zhí)行。

  • 正則數(shù)量限制:最多可添加10條。

  • 正則表達(dá)式標(biāo)準(zhǔn):正則配置遵循 ECMAScript 標(biāo)準(zhǔn),支持i(不區(qū)分大小寫)、g(全局匹配)、s(DOTALL 模式)等常用標(biāo)志位。

  • 正則配置示例

規(guī)則名稱

正則表達(dá)式

替換內(nèi)容

原文

替換后

身份證號

?(?<pre>.*)(\d{15})((\d{2})([0-9Xx]))(?<post>.*)?

?$<pre>***$<post>?

身份證號:?330204197709022312?。

身份證號:?***?。

郵箱

?\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*?

?***?

我的郵箱是 ?lin***@aliyunmail.com?

我的郵箱是 ?***?

密碼

?(.*password=)([\w\d]+)(.*)?

?$1***$3?

?{password=1213213}?

?{password=***}?

方式二:自定義腳本配置(僅適用于企業(yè)專屬版)

企業(yè)專屬版中支持通過自定義腳本的方式進(jìn)行過濾器配置,以實(shí)現(xiàn)對復(fù)雜場景下的前置過濾的需求。步驟如下:

步驟一:腳本開發(fā)

目前支持使用 TypeScript 語言進(jìn)行腳本開發(fā),可以參考樣例進(jìn)行代碼開發(fā),操作步驟如下:

  1. 下載模板代碼庫:單擊倉庫地址:lingma-extension-template,該模板倉庫集成了開發(fā)腳本所需的腳手架,請仔細(xì)閱讀README.md文件和代碼示例。

  2. 實(shí)現(xiàn)“前置處理”接口:實(shí)現(xiàn)接口?RequestPreHandler?,API 可參考自定義腳本 API,以下為一個示例片段SensitiveContentFilter.ts的實(shí)現(xiàn)。


/**
 * 敏感內(nèi)容過濾器,通過該過濾器可以實(shí)現(xiàn)對發(fā)送給模型的數(shù)據(jù)進(jìn)行敏感信息預(yù)處理
 */
export const sensitiveContentFilter: RequestPreHandler = {
  handle: async (request: RawRequest, SDKTool: LingmaSDKTool) => {
    const dataMap = PayloadUtil.getPayloadData(request.payload);
    for (const [key, value] of dataMap.entries()) {
      if (value.includes('password')) {
        return ResultUtil.buildBlockResult('內(nèi)容包含password');
      }
    }
    // 如果需要針對不同的 action 做差異化處理,則參考如下實(shí)現(xiàn)
    switch (request.action) {
      case ActionEnum.COMPLETION:
        // do something
        break;
      case ActionEnum.CODE_PROBLEM_SOLVE:
        // do something
        break;
      default:
        return ResultUtil.buildNoOpsResult();
    }
    return ResultUtil.buildNoOpsResult();
  },
};
  1. 運(yùn)行調(diào)試代碼,通過運(yùn)行main方法來測試腳本是否符合預(yù)期,操作步驟如下:

步驟一

編輯src/index.ts文件,修改main函數(shù),調(diào)整實(shí)際需要調(diào)試代碼,如下示例:


async function main() {
  const value1 = ['password=123', 'abc'];
  const value2 = 'hello world';
  const dataMap = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
  dataMap.set(PayloadDataKeyEnum.SELECTED_CODE, value1);
  dataMap.set(PayloadDataKeyEnum.USER_INPUT, value2);

  const mockRequest: RawRequest = {
    action: ActionEnum.CODE_GENERATE_COMMENT,
    payload: {
      associatedContexts: [],
      data: dataMap,
    },
    requestId: '123',
  };
  const response = await sensitiveContentFilter.handle(mockRequest, SDKTool);
  console.log(response);
}

步驟二

在 VS Code 中打開想要調(diào)試的代碼文件并設(shè)置斷點(diǎn),然后從調(diào)試視圖中選擇“啟動程序”并單擊運(yùn)行按鈕即可。

image

步驟二:編譯構(gòu)建

將運(yùn)行調(diào)試完成的 ts 文件編譯為 js 文件,如將?SensitiveContentFilter.ts?文件編譯為?SensitiveContentFilter.js?文件,編譯構(gòu)建步驟如下:

  1. 打開配置文件?src/build.js?,修改?entryPoints?和?outfile?兩個配置參數(shù),并在?entryPoints?參數(shù)中指定需要編譯構(gòu)建的 ts 文件路徑,在?outfile?中指定構(gòu)建后的產(chǎn)物輸出路徑。

  2. 在代碼庫根目錄下執(zhí)行命令?node build.js?,執(zhí)行成功后對應(yīng)的 js 文件將輸出到outfile指定的產(chǎn)物輸出路徑。

步驟三:本地測試

在腳本上傳企業(yè)配置后臺之前,可在本地完成調(diào)試,以確保腳本能夠與通義靈碼靈碼的 IDE 插件集成,并對補(bǔ)全或問答場景的行為進(jìn)行正確的安全過濾處理。具體調(diào)試步驟如下:

  1. 將構(gòu)建好的 js 文件拷貝到通義靈碼靈碼本地存儲路徑的?/extension/local/script/?目錄下。

  2. 修改?config.json?文件:該文件所在目錄為通義靈碼靈碼本地存儲路徑的?/extension/local/?,打開?config.json?文件,并找到?contentHandlerScripts?,在對應(yīng)的內(nèi)容里增加該腳本的配置信息,如果沒有?contentHandlerScripts?,可以新增一個數(shù)組類型的配置,參考示例如下:


{
  "contentHandlerScripts": [
    {
      "identifier": "SensitiveContentFilter", 
      "name": "敏感內(nèi)容過濾",
      "version": "1.0.0",
      "scriptPath": "~/.lingma/extension/local/script/SensitiveContentFilter.js",
      "state": "enabled",
      "bizType": "completion"
    }
  ]
}

配置參數(shù)說明:

參數(shù)

說明

identifier

腳本 ID,需確保唯一性。

name

腳本名稱。

version

腳本的版本號,如果修改了腳本內(nèi)容,需要升級版本號,否則腳本無法生效。

scriptPath

腳本存放的路徑,請注意:

  • 腳本一定要存放在本地存儲路徑的?/extension/local/script/?目錄下。

  • 腳本的 js 文件名稱(如:?SensitiveContentFilter.js?)一定要與?identifier?的值保持一致。

state

腳本狀態(tài),enabled表示啟用、disabled表示禁用。

bizType

腳本應(yīng)用的業(yè)務(wù)場景,?completion?表示行間代碼生成補(bǔ)全、?chat?表示智能問答。

步驟四:腳本上傳

經(jīng)過本地調(diào)試并通過驗(yàn)證后,可進(jìn)行腳本上傳,操作步驟如下:

  1. 前往通義靈碼靈碼控制臺-策略管理,選擇需要開通安全過濾器的場景。

  2. 選擇過濾器選項為:自定義腳本。

  3. 將構(gòu)建后的 js文件上傳。

  4. 上傳后單擊保存配置,約5分鐘內(nèi)會下發(fā)到插件端生效。

自定義腳本 API

目前自定義腳本支持三種處理方式,如下:

  • 阻斷處理:即阻斷后續(xù)流程,一旦阻斷,則不會請求大模型進(jìn)行推理,中斷本次請求。

  • 過濾處理:對發(fā)送處理的數(shù)據(jù)進(jìn)行了修改(如:混淆、刪除、替換等),然后繼續(xù)后續(xù)流程。

  • 無處理:對發(fā)送的數(shù)據(jù)沒有做任何處理,原樣返回,然后繼續(xù)后續(xù)流程。

接口定義


/**
 * 靈碼編程助手前置處理接口
 */
export interface RequestPreHandler {
  // 處理請求
  handle: (request: RawRequest, SDKTool: LingmaSDKTool) => Promise<HandlerResponse>;
}

入?yún)⒍x


/**
 * 請求對象定義,請求包括觸發(fā)的行為和待發(fā)送給 LLM 的原始數(shù)據(jù)
 */
export interface RawRequest {
  // 當(dāng)前請求唯一標(biāo)識,可用于追蹤請求執(zhí)行
  action: ActionEnum;
  // 觸發(fā)請求的行為枚舉
  payload: ContentPayload;
  // 封裝原始數(shù)據(jù)內(nèi)容的payload
  requestId: string;
}

// ContentPayload.data 中 value 類型
export type PayloadDataValueType = string | number | string[];
/**
 * 封裝發(fā)送給 LLM 的原始數(shù)據(jù)內(nèi)容
 */
export class ContentPayload {
  // 待處理的數(shù)據(jù)集合,對應(yīng)的 key 參考 ContextValueKeyEnum 定義
  data: Map<PayloadDataKeyEnum, PayloadDataValueType>;
  // 與處理關(guān)聯(lián)的上下文
  associatedContexts: ContextItem[];

  constructor() {
    this.data = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
    this.associatedContexts = [];
  }
}

/**
 * ContentPayload.data 中 key 枚舉
 */
export enum PayloadDataKeyEnum {
  // 用戶圈選的代碼片段
  SELECTED_CODE ='lingma:code',
  // 用戶輸入的文本
  USER_INPUT = 'lingma:text',
  // 報錯信息
  ERROR_MESSAGES = 'lingma:error_messages',
  // 終端打印的日志信息
  TERMINAL_CONTENT = 'lingma:terminal_content',
  // 代碼補(bǔ)全時,當(dāng)前光標(biāo)所在行的前文代碼片段
  PREFIX_CODE = 'lingma:code_prefix',
  // 代碼補(bǔ)全時,當(dāng)前光標(biāo)所在行的后文代碼片段
  SUFFIX_CODE = 'lingma:code_suffix',
  // 相似代碼片段
  SIMILAR_CODE = 'lingma:similar_code',
}

/**
 * 觸發(fā)請求的行為枚舉
 */
export enum ActionEnum {
    // 單元測試
    GENERATE_TESTCASE           = 'GENERATE_TESTCASE',
    // 生成注釋
    CODE_GENERATE_COMMENT       = 'CODE_GENERATE_COMMENT',
    // 代碼解釋
    EXPLAIN_CODE                = 'EXPLAIN_CODE',
    // 代碼優(yōu)化
    OPTIMIZE_CODE               = 'OPTIMIZE_CODE',
    // 自由問答(即在問答輸入框中直接輸入文本的行為)
    FREE_INPUT                  = 'FREE_INPUT',
    // 代碼問題快捷修復(fù)
    CODE_PROBLEM_SOLVE          = 'CODE_PROBLEM_SOLVE',
    // shell命令生成
    TERMINAL_COMMAND_GENERATION = 'TERMINAL_COMMAND_GENERATION',
    // 終端報錯修復(fù)
    TERMINAL_EXPLAIN_FIX        = 'TERMINAL_EXPLAIN_FIX',
    // 代碼補(bǔ)全
    COMPLETION                  = 'COMPLETION',
}

出參定義


/**
 * 預(yù)處理結(jié)果
 */
export class HandlerResponse {
  // 處理策略,通過該策略可以控制后續(xù)的處理邏輯
  handlePolicy: HandlePolicy;
  // 原因描述
  reason?: string;
  // 當(dāng)handlePolicy=FILTER時,需要設(shè)置該屬性,其值為經(jīng)過過濾后的數(shù)據(jù)(必須與ContentRequest.payload的內(nèi)容保持一致)
  payload?: ContentPayload;
  constructor() {
    // 默認(rèn)值
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    this.handlePolicy = HandlePolicy.NO_OPS;
    this.reason = '';
    this.payload = new ContentPayload();
  }
}

/**
 * 處理策略枚舉
 */
export enum HandlePolicy {
  // 阻斷策略,直接阻斷請求
  BLOCK = 'BLOCK',
  // 過濾策略,攔截請求并對payload內(nèi)容進(jìn)行修改
  FILTER = 'FILTER',
  // 忽略策略,不處理請求
  NO_OPS = 'NO_OPS',
}

智能問答、行間生成的后置過濾器配置

方式一:正則表達(dá)式配置

說明
管理員在配置正則表達(dá)式時需要充分驗(yàn)證,以避免開發(fā)者使用IDE 插件時性能下降或產(chǎn)生其他異常問題。
  • 處理方式:支持通過正則表達(dá)式的方式配置過濾器,僅支持一種模式,如下:

匹配規(guī)則時不處理

匹配到正則后,不做任何處理。

  • 消息通知:支持開啟消息通知,通過 webhook 的方式,推送到所需要的消息接收平臺。

  • 執(zhí)行順序:按照配置的排序執(zhí)行。

  • 正則數(shù)量限制:最多可添加10條。

  • 正則表達(dá)式標(biāo)準(zhǔn):正則配置遵循 ECMAScript 標(biāo)準(zhǔn),支持i(不區(qū)分大小寫)、g(全局匹配)、s(DOTALL 模式)等常用標(biāo)志位。

  • 正則配置示例

規(guī)則名稱

正則表達(dá)式

原文

身份證號

?(?<pre>.*)(\d{15})((\d{2})([0-9Xx]))(?<post>.*)?

身份證號:?330204197709022312?。

郵箱

?\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*?

我的郵箱是 ?lin***@aliyunmail.com?

密碼

?(.*password=)([\w\d]+)(.*)?

?{password=1213213}?

方式二:自定義腳本配置(僅適用于企業(yè)專屬版)

企業(yè)專屬版中支持通過自定義腳本的方式進(jìn)行過濾器配置,以實(shí)現(xiàn)對復(fù)雜場景下的后置過濾的需求。步驟如下:

步驟一:腳本開發(fā)

目前支持使用 TypeScript 語言進(jìn)行腳本開發(fā),可以參考樣例進(jìn)行代碼開發(fā),操作步驟如下:

  1. 下載模板代碼庫:單擊倉庫地址:lingma-extension-template,該模板倉庫集成了開發(fā)腳本所需的腳手架,請仔細(xì)閱讀README.md文件和代碼示例。

  2. 實(shí)現(xiàn)“后置處理”接口:實(shí)現(xiàn)接口RequestPostHandler,API 可參考自定義腳本 API,以下為一個示例片段?LLMChatAuditHandler.ts?的實(shí)現(xiàn),實(shí)現(xiàn)的功能為對通義靈碼靈碼的AIChat操作進(jìn)行審計,將審計內(nèi)容上報至阿里云SLS。

    import {ResultUtil} from '../common/HandlerRespUtil';
    import { JsonUtil } from '../common/JsonUtil';
    import {PayloadUtil} from '../common/PayloadUtil';
    import {Config} from '../sdk/ConfigManager';
    import {LingmaSDKTool} from '../sdk/LingmaSDKTool';
    import axios from "axios";
    import moment from "moment";
    import os from "os";
    import {
      ActionEnum, AIResponse,
      HandlePolicy,
      RawRequest,
      RequestPostHandler,
      RequestPreHandler
    } from '../sdk/RequestHandleSDK';
    
    /**
     * 自定義腳本后置過濾器,通過該腳本可以完成將請求內(nèi)容發(fā)送到遠(yuǎn)程服務(wù)器進(jìn)行處理(如代碼掃描、內(nèi)容審計等)
     */
    export const llmResultAuditHandler: RequestPostHandler = {
      handle: async (request: RawRequest, response: AIResponse,SDKTool: LingmaSDKTool) => {
         // 操作人名稱
         let userName = SDKTool.user.name;
         // 操作人id
         let userId = SDKTool.user.uid;
         // ide
         let ide = SDKTool.idePlatform;
         // ide
         let ideVersion = SDKTool.ideVersion;     
         // 操作時間
         let operationTime = moment().format("YYYY-MM-DD HH:mm:ss");
         // 操作ip
         let opeartionIp = getIpAddress();
         // 操作業(yè)務(wù)場景(補(bǔ)全 or 問答場景)
         let bizType = "chat";
         // 操作的請求id
         let requestId = request.requestId;
         // 操作action
         let action = request.action;
         // 操作內(nèi)容(此處建議參考自身審計需求選取合適字段,避免上報內(nèi)容過大(超過16k)導(dǎo)致上報失敗)
         let inferredResult = response.inferredResult.text;
        
         // 上報sls
         // sls的Project名稱
         let slsProject = "xxx";
         // sls的LogStore名稱
         let slsLogStore = "xxx";
         // sls實(shí)例所在地域的endPoint
         let endPoint = "cn-hangzhou.log.aliyuncs.com";
         let slsWebTrackingUrl = `http://${slsProject}.${endPoint}/logstores/${slsLogStore}/track?APIVersion=0.6.0&request_id=${requestId}&action=${action}&biz_type=${bizType}&user_name=${userName}&user_id=${userId}&ide=${ide}&ide_version=${ideVersion}&operation_time=${operationTime}&opeartion_ip=${opeartionIp}&inferredResult=${inferredResult}`;
         axios.get(slsWebTrackingUrl).catch((error) => {
           console.error(error);
         });
    
         // 返回過濾結(jié)果
        return ResultUtil.buildPostHandlerResponse(HandlePolicy.NO_OPS, response.inferredResult,'無需處理');
      },
    };
    
    /**
     * 將自定義腳本過濾器添加到配置中
     * @param config LingmaExtensionSDK提供的統(tǒng)一管理配置的對象
     */
    export function modifyConfig(config: Config) {
      config.postContentHandlers.push(llmResultAuditHandler);
      return config;
    }
    
    function getIpAddress() {
      const interfaces = os.networkInterfaces();
      for (let devName in interfaces) {
        let iface = interfaces[devName];
    
        for (let i = 0; i < iface.length; i++) {
          let alias = iface[i];
          if (
            alias.family === "IPv4" &&
            alias.address !== "127.0.0.1" &&
            !alias.internal
          )
            return alias.address;
        }
      }
    
      return "No IP address found";
    }
  1. 運(yùn)行調(diào)試代碼,通過運(yùn)行?main?方法來測試腳本是否符合預(yù)期,操作步驟如下:

步驟一

編輯?src/index.ts?文件,修改?main?函數(shù),調(diào)整實(shí)際需要被調(diào)試的代碼,如下示例:


async function main() {
  const value2 = 'hello world';
  const dataMap = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
  dataMap.set(PayloadDataKeyEnum.USER_INPUT, value2);

  const request: RawRequest = {
    action: ActionEnum.CODE_GENERATE_COMMENT,
    payload: {
      associatedContexts: [],
      data: dataMap,
    },
    requestId: 'test-request-id',
  };

  const aiResponse: AIResponse = {
    inferredResult: {
      text: 'reply hello world',
    },
  };

  const response = await llmResultAuditHandler.handle(request, aiResponse, SDKTool);
  console.log(response);
}

步驟二

在 VS Code 中打開想要調(diào)試的代碼文件并設(shè)置斷點(diǎn),然后從調(diào)試視圖中選擇“啟動程序”并單擊運(yùn)行按鈕即可。

image

步驟二:編譯構(gòu)建

將運(yùn)行調(diào)試完成的 ts 文件編譯為 js 文件,如將?LLMChatAuditHandler.ts?文件編譯為?LLMChatAuditHandler.js?文件,編譯構(gòu)建步驟如下:

  1. 打開配置文件?src/build.js?,修改?entryPoints?和?outfile?兩個配置參數(shù),并在?entryPoints?參數(shù)中指定需要編譯構(gòu)建的 ts 文件路徑,在?outfile?中指定構(gòu)建后的產(chǎn)物輸出路徑。

  2. 在代碼庫根目錄下執(zhí)行命令?node build.js?,執(zhí)行成功后對應(yīng)的 js 文件將輸出到?outfile?指定的產(chǎn)物輸出路徑。

步驟三:本地測試

在腳本上傳企業(yè)配置后臺之前,可在本地完成調(diào)試,以確保腳本能夠與通義靈碼靈碼的 IDE 插件集成,并對補(bǔ)全或問答場景的行為進(jìn)行正確的安全過濾處理。具體調(diào)試步驟如下:

  1. 將構(gòu)建好的 js 文件拷貝到通義靈碼靈碼本地存儲路徑的?/extension/local/script/?目錄下。

  2. 修改?config.json?文件:該文件所在目錄為通義靈碼靈碼本地存儲路徑的?/extension/local/?,打開?config.json?文件,并找到?contentHandlerScript?s,在對應(yīng)的內(nèi)容里增加該腳本的配置信息,如果沒有?contentHandlerScripts?,可以新增一個數(shù)組類型的配置,參考示例如下:


{
  "contentHandlerScripts": [
    {
      "identifier": "LLMChatAuditHandler", 
      "name": "AIChat審計",
      "version": "1.0.0",
      "scriptPath": "~/.lingma/extension/local/script/LLMChatAuditHandler.js",
      "state": "enabled",
      "stage":"post",
      "bizType": "completion"
    }
  ]
}

配置參數(shù)說明:

參數(shù)

說明

identifier

腳本 ID,需確保唯一性。

name

腳本名稱。

version

腳本的版本號,如果修改了腳本內(nèi)容,需要升級版本號,否則腳本無法生效。

scriptPath

腳本存放的路徑,請注意:

  • 腳本一定要存放在本地存儲路徑的?/extension/local/script/?目錄下。

  • 腳本的 js 文件名稱(如:?LLMChatAuditHandler.js?)一定要與?identifier?的值保持一致。

state

腳本狀態(tài),?enabled?表示啟用、?disabled?表示禁用。

stage

腳本作用階段,?post?表示后置過濾、?pre?表示前置過濾,默認(rèn)值為?pre?前置過濾。

bizType

腳本應(yīng)用的業(yè)務(wù)場景,?completion?表示行間代碼生成補(bǔ)全、?chat?表示智能問答。

步驟四:腳本上傳

經(jīng)過本地調(diào)試并通過驗(yàn)證后,可進(jìn)行腳本上傳,操作步驟如下:

  1. 前往通義靈碼靈碼控制臺-策略管理,選擇需要開通安全過濾器的場景。

  2. 選擇過濾器選項為:自定義腳本。

  3. 將構(gòu)建后的 js文件上傳。

  4. 上傳后單擊保存配置,約5分鐘內(nèi)會下發(fā)到插件端生效。

自定義腳本 API

目前自定義腳本僅支持一種處理方式,如下:

  • 無處理:對發(fā)送的數(shù)據(jù)沒有做任何處理,原樣返回,然后繼續(xù)后續(xù)流程。

接口定義


/**
 * 靈碼編程助手后置處理接口
 * @param request 用戶發(fā)送的請求
 * @param response LLM返回的推理內(nèi)容
 * @param SDKTool SDK工具類,通過該工具類可以獲取與IDE、Plugin相關(guān)的信息
 * @returns 經(jīng)過后置處理器處理后的返回結(jié)果
 */
export interface RequestPostHandler {
  // 后置處理方法
  handle: (request: RawRequest, response: AIResponse, SDKTool: LingmaSDKTool) => Promise<PostHandlerResponse>;
}

入?yún)⒍x


/**
 * 請求對象定義,請求包括觸發(fā)的行為和待發(fā)送給 LLM 的原始數(shù)據(jù)
 */
export interface RawRequest {
  // 當(dāng)前請求唯一標(biāo)識,可用于追蹤請求執(zhí)行
  action: ActionEnum;
  // 觸發(fā)請求的行為枚舉
  payload: ContentPayload;
  // 封裝原始數(shù)據(jù)內(nèi)容的payload
  requestId: string;
}

/**
 * 模型推理生成的結(jié)果數(shù)據(jù)
 */
export class InferredResult {
  //LLM生成的文本內(nèi)容
  text: string;
  constructor() {
    this.text = '';
  }
}

// ContentPayload.data 中 value 類型
export type PayloadDataValueType = string | number | string[];
/**
 * 封裝發(fā)送給 LLM 的原始數(shù)據(jù)內(nèi)容
 */
export class ContentPayload {
  // 待處理的數(shù)據(jù)集合,對應(yīng)的 key 參考 ContextValueKeyEnum 定義
  data: Map<PayloadDataKeyEnum, PayloadDataValueType>;
  // 與處理關(guān)聯(lián)的上下文
  associatedContexts: ContextItem[];

  constructor() {
    this.data = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
    this.associatedContexts = [];
  }
}

/**
 * ContentPayload.data 中 key 枚舉
 */
export enum PayloadDataKeyEnum {
  // 用戶圈選的代碼片段
  SELECTED_CODE ='lingma:code',
  // 用戶輸入的文本
  USER_INPUT = 'lingma:text',
  // 報錯信息
  ERROR_MESSAGES = 'lingma:error_messages',
  // 終端打印的日志信息
  TERMINAL_CONTENT = 'lingma:terminal_content',
  // 代碼補(bǔ)全時,當(dāng)前光標(biāo)所在行的前文代碼片段
  PREFIX_CODE = 'lingma:code_prefix',
  // 代碼補(bǔ)全時,當(dāng)前光標(biāo)所在行的后文代碼片段
  SUFFIX_CODE = 'lingma:code_suffix',
  // 相似代碼片段
  SIMILAR_CODE = 'lingma:similar_code',
  // 補(bǔ)全場景執(zhí)行補(bǔ)全的文件路徑
  FILE_PATH = 'lingma:file_path',
}

/**
 * 觸發(fā)請求的行為枚舉
 */
export enum ActionEnum {
    // 單元測試
    GENERATE_TESTCASE           = 'GENERATE_TESTCASE',
    // 生成注釋
    CODE_GENERATE_COMMENT       = 'CODE_GENERATE_COMMENT',
    // 代碼解釋
    EXPLAIN_CODE                = 'EXPLAIN_CODE',
    // 代碼優(yōu)化
    OPTIMIZE_CODE               = 'OPTIMIZE_CODE',
    // 自由問答(即在問答輸入框中直接輸入文本的行為)
    FREE_INPUT                  = 'FREE_INPUT',
    // 代碼問題快捷修復(fù)
    CODE_PROBLEM_SOLVE          = 'CODE_PROBLEM_SOLVE',
    // shell命令生成
    TERMINAL_COMMAND_GENERATION = 'TERMINAL_COMMAND_GENERATION',
    // 終端報錯修復(fù)
    TERMINAL_EXPLAIN_FIX        = 'TERMINAL_EXPLAIN_FIX',
    // 代碼補(bǔ)全
    COMPLETION                  = 'COMPLETION',
}

出參定義


/**
 * 后置處理結(jié)果
 */
export class PostHandlerResponse {
  // 處理策略,通過該策略可以控制后續(xù)的處理邏輯
  handlePolicy: HandlePolicy;
  // 原因描述
  reason?: string;
  // 經(jīng)過后置處理器處理過的模型返回結(jié)果
  processedResult: InferredResult;
  constructor() {
    // 默認(rèn)值
    this.handlePolicy = HandlePolicy.NO_OPS;
    this.reason = '';
    this.processedResult = new InferredResult();
  }
}

/**
 * 封裝大模型返回結(jié)果
 */
export class AIResponse {
  // 模型推理結(jié)果
  inferredResult: InferredResult;
  constructor() {
    this.inferredResult = new InferredResult();
  }
}

/**
 * 模型推理生成的結(jié)果數(shù)據(jù)
 */
export class InferredResult {
  //LLM生成的文本內(nèi)容
  text: string;
  constructor() {
    this.text = '';
  }
}

/**
 * 處理策略枚舉(后置過濾器當(dāng)前只支持NO_OPS)
 */
export enum HandlePolicy {
  // 阻斷策略,直接阻斷請求
  BLOCK = 'BLOCK',
  // 過濾策略,攔截請求并對payload內(nèi)容進(jìn)行修改
  FILTER = 'FILTER',
  // 忽略策略,不處理請求
  NO_OPS = 'NO_OPS',
}

知識庫上傳過濾器配置(僅適用于企業(yè)專屬版)

企業(yè)專屬版中,支持通義靈碼靈碼管理員、全局管理員通過在策略配置中配置知識庫過濾器,配置完成后,在知識庫文件上傳前對其進(jìn)行審查,從而滿足在特定場景下對知識庫內(nèi)容前置過濾的需求。

過濾器配置說明

步驟一:開啟并編輯知識庫過濾器

  1. 在左側(cè)導(dǎo)航欄,單擊策略配置,在右側(cè)頁面,單擊知識庫過濾器頁簽。

  2. 在知識庫過濾器配置頁面,您可以打開開關(guān)開啟/關(guān)閉知識庫上傳前置過濾器,進(jìn)行參數(shù)配置編輯。

URL 地址

必填

企業(yè)提供的第三方掃描服務(wù)的接口地址。要求此接口必須使用 POST 請求。

Token 字段名

必填

指定請求頭中用于存放 Token 的字段名。

Secret 密鑰

必填

生成訪問 Token 所需的密鑰。Token 會被放入指定的請求頭字段中,用于驗(yàn)證請求的合法性。詳情請參考“安全 Token”章節(jié)。

image

步驟二:測試過濾器連通性

填寫正確后,進(jìn)行連通性測試,單擊測試連接按鈕。當(dāng)?shù)谌竭^濾接口返回2xx狀態(tài)碼時,測試成功。

image

如果返回其它狀態(tài)碼,測試則會失敗,您需要檢查填寫信息后再重現(xiàn)測試連接。

image

步驟三:保存知識庫過濾器

單擊保存配置按鈕,保存您的過濾器配置。保存成功后,過濾器將立即生效。

第三方掃描服務(wù)接口規(guī)范

企業(yè)需提供第三方掃描服務(wù),以便知識庫過濾器可以使用該服務(wù)對上傳的知識內(nèi)容進(jìn)行掃描,通過掃描后方可上傳。為了確保您配置的過濾器正常運(yùn)行,掃描服務(wù)的接口應(yīng)符合以下設(shè)計要求:

請求頭

參數(shù)名

是否必填

參數(shù)說明

參數(shù)示例

X-Auth-Raw

接口鑒權(quán)參數(shù),參數(shù)名為您在過濾器配置頁面中配置的 Token 字段名。參數(shù)值應(yīng)為Secret 密鑰通過加密算法生成的 最終密鑰,具體生成邏輯詳見“安全 Token”章節(jié)。

6c3baa76c62550eab864e6f75c4bb

Content-Type

表示請求和響應(yīng)中的媒體類型信息。

multipart/form-data

  • 安全Token:是阿里云設(shè)計的一種安全簽名,旨在防止惡意攻擊者盜用您的云服務(wù)權(quán)限。生成 Token 需要以下要素:Secret 密鑰、當(dāng)前時間、其他信息 和 加密算法。

  • Token生成:通義靈碼靈碼調(diào)用第三方掃描服務(wù)接口時,將在請求頭內(nèi)攜帶安全Token 用于身份鑒權(quán)驗(yàn)證。 根據(jù)如下參數(shù)計算生成 Token 值:


token = sha256Hex(method + url + timestamp + tokenSecret) + timestampHex

method

為POST 方法。

url

為配置知識庫過濾器填寫的掃描服務(wù)接口 URL 地址。

timestamp

為當(dāng)前時間。

tokenSecret

為配置知識庫過濾器時填寫的 Secret 密鑰。

timestampHex

將時間戳轉(zhuǎn)換成十六進(jìn)制。

  • Token驗(yàn)證:您的第三方掃描服務(wù)在驗(yàn)證請求的Token鑒權(quán)時,可以參考以下代碼進(jìn)行合法性校驗(yàn)。

重要
  • 時間戳:確??蛻舳撕头?wù)端的時間同步,避免因時間偏差導(dǎo)致Token驗(yàn)證失敗。
  • 密鑰管理:妥善保管tokenSecret,不要泄露給未經(jīng)授權(quán)的用戶。
  • 過期時間:根據(jù)業(yè)務(wù)需求調(diào)整 Token 的有效時間,示例中設(shè)置為60秒,可根據(jù)實(shí)際情況調(diào)整。


/*
 *  方法參數(shù)說明:
 *  receivedHash:接收到的哈希值,包含了時間戳信息。
 *  tokenSecret:用于生成哈希的密鑰。
 *  url:請求的URL。
 */
public boolean validateAuthRaw(String receivedHash, String tokenSecret, String url) {
    final String method = "POST";
    
    // 從 receivedHash 中提取時間戳部分
    String tsHex = receivedHash.substring(receivedHash.length() - 8);
    long tsSec = Long.parseLong(tsHex, 16);
    
    // 計算當(dāng)前時間與接收時間的差異,假設(shè)允許的最大時間差為60秒
    long now = System.currentTimeMillis() / 1000L;
    if (Math.abs(now - tsSec) > 60) {
        return false; // 超過允許的時間范圍
    }
    
    // 構(gòu)建待簽名的字符串
    String plain = method + url + tsSec + tokenSecret;
    
    // 生成預(yù)期的哈希值
    String expectedHash = org.apache.commons.codec.digest.DigestUtils.sha256Hex(plain);
    
    // 比較接收到的哈希值與預(yù)期的哈希值
    return expectedHash.equals(receivedHash.substring(0, receivedHash.length() - 8));
}

請求參數(shù)

參數(shù)名

參數(shù)類型

是否必填

參數(shù)解釋

參數(shù)示例

metadata

string

業(yè)務(wù)元數(shù)據(jù),Content-Type: application/json

{"user": "user0000001",

"queryId": "cd2fd109-c4d4-489f-9b27-53752f7827d6"}

file

file

送檢的文件

請求示例。


Content-Type: multipart/form-data; boundary=${bound}
--${bound}

Content-Disposition: form-data; name="metadata"

Content-Type: application/json
{
"user":"user0000001",
"queryID":"cd2fd109-c4d4-489f-9b27-53752f7827d6"
}

--${bound}
Content-Disposition: form-data; name="file"; filename="test-file.pdf"

Content-Type: application/pdf

%binary-file-content-here%

響應(yīng)結(jié)構(gòu)

接口應(yīng)返回 HTTP 狀態(tài)碼 200,并包含以下格式的響應(yīng)體。

參數(shù)名

參數(shù)類型

是否必填

參數(shù)解釋

參數(shù)示例

forbidden

boolean

安全檢測結(jié)果。true表示檢測失敗。

false

errorMsg

string

錯誤信息,說明檢測失敗的原因。

"文件包含惡意內(nèi)容,請修改后再上傳"

queryId

string

請求 ID,需與請求 metadata 中的 queryId 字段對應(yīng)。

"cd2fd109-c4d4-489f-9b27-53752f7827d6"

user

string

用戶 ID,需與請求 metadata 中的 user 字段對應(yīng)。

"user0001"


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號