SEO技术

SEO技术

Products

当前位置:首页 > SEO技术 >

前端AI工程化(六):如何实现Function Calling与RAG前端应用?

96SEO 2026-08-02 04:20 2


👤 关于作者

JavaAgent架构师 — 十年 Java 分布式架构老兵,专注 AI Agent 公司级落地。

前端AI工程化(六):如何实现Function Calling与RAG前端应用?

主导过数字员工、SOP 智能引擎等项目,开发过 RPC 框架、消息中间件、ORM 框架。按理说,

专栏:

  • 专栏一这方面,《前端 AI 工程化》10 期,适合前端 SSE/流式渲染/公司级 AI 架构/AI 前端面试详细说明
  • 至于专栏二。《Java 程序也能玩转 AI》24 期加急中,适合 Java 深度玩家
  • 说到专栏三,《从 0 建立 Agent 程序》15 期加急中,适合所有玩家

让 Java 开发者不转 Python 也能建立公司级 AI 应用。


点赞+关注+评论 走一波。

Function Calling 前端全流程解析

前端从“展示层”变成“执行层”

使用者痛点:

  • 传统前后端模型只能展示 LLM 输出,无法直接响应 LLM 的工具调用指令。
  • L​LM 返回的 arguments 为 JSON 字符串,很多团队在前端直接当对象使用导致解析错误。
  • 缺少统一的工具注册、权限校验、超时控制等机制,导致代码散落各处、难以维护。

传统的交互模型是:使用者操作 → 前端发请求 → 后端处理 → 前端展示结果。Function Calling 将模型改为:

  1. LLM 决定调用工具 → 前端解析指令并执行 → 将结果回传给 LLM → LLM 基于结果生成最终回复。

一、Function Calling 协议详解

完整流程示意图


↓ 请求带 tools 定义
← LLM 返回 function_call
↓ 前端解析 + 执行函数
← 将执行结果回传给 LLM
→ 最终文本回复

再看请求格式。tools 定义


interface ChatCompletionRequest {
model的观点是,string;messages: ChatMessage;tools,: ToolDefinition;tool_choice,: 'auto' | 'none' | { type: 'function';function: { name: string } };}
interface ToolDefinition {
从type来看,'function';老实说,function: {
至于name,string;description: string;// LLM 靠描述决定何时调用
parameters: {
type这方面,'object';properties: Record;required,: string;},};}
interface PropertyDefinition {
type的观点是,string;description: string;enum,: string;// 枚举约束
}
// 示例:天气查询工具
const wearTool: ToolDefinition = {
再看type,'function',function: {
至于name,'get_wear',description: '获取指定城市的当前天气信息',parameters: {
再看type。'object',properties: {
说到city,{ type: 'string',description: '城市名称,如"北京","上海"' },unit: { type: 'string',description: '温度单位',enum: },},required:,},},};

响应格式这方面。function_call 解码


// 当 LLM 决定调用工具时的响应结构
interface FunctionCallResponse {
至于id,string;// chatcmpl-xxx
choices:;},finish_reason:'tool_calls';// 因工具调用而停止
}];}

关键细节:arguments 必须先使用 JSON.parse 转为对象。否则会出现类型错误,这是最常见的 bug 源头。

二、Function Calling 执行器设计

整体架构图


┌───────────────────────────────────────┐
│ FunctionCallingExecutor │
├───────────────────────────────────────┤
│ 工具注册层 │
│ ├─ registerTool│
│ └─ 工具元数据 │
├───────────────────────────────────────┤
│ 参数校验层 │
│ ├─ Schema 校验 │
│ └─ 安全过滤 │
├───────────────────────────────────────┤
│ 执行层 │
│ ├─ 权限检查 │
│ ├─ 沙箱执行 │
│ ├─ 超时控制 │
│ └─ 并发并行执行 │
├───────────────────────────────────────┤
│ 결과处理层 │
│ ├─ 序列化 │
│ ├─ 错误捕获与格式化 │
│ └─ 构造回传消息 │
└───────────────────────────────────────┘

工具注册 & 权限分级


type ToolPermission = 'read' | 'write' | 'dangerous';怎么说呢,interface ToolRegistration {
说到name。string,description:string;parameters:any;// JSON Schema
handler:=>Promise;permission:ToolPermission;老实说,_timeout?:number,_maxRetries?:number,}
class FunctionCallingExecutor {
private tools = new Map;private permissionLevel : ToolPermission = 'read';怎么说呢,// 当前允许最高权限
/** 注册单个工具 */
registerTool:void{
if{
throw new Error;}
this.tools.set;}
/** 批量注册 */
registerTools:void{
regs.forEach);}
/** 注销 */
unregisterTool:void{
this.tools.delete;}
/** 获取当前可见的 tool 定义,用于发送给 LLM */
getToolDefinitions:ToolDefinition{
return Array.from)
.filter)
.map(t=>({
从type来看。'function',// @ts-ignore
function:{name:t.name,description:t.description,parameters:t.parameters}
}));}
// 权限判断逻辑
private isPermissionAllowed:boolean{const levels:{:number}={read:1。width:2,risk:3};return levels<=levels;};话说回来,setPermissionLevel:void{this.permissionLevel=level;}

参数校验 & 安全过滤


import {z} from 'zod';class FunctionCallingExecutor {/* ... 前面的代码 ... */
async execute:Promise{
const {name,arguments:argsStr}=toolCall.function;const tool=this.tools.get;if{
return{tool_call_id:toolCall.id。role:'tool',content:JSON.stringify};}
if){
return{tool_call_id:toolCall.id。role:'tool',content:
JSON.stringify};}
let args:any;说起来,try{args=JSON.parse;}catch{
return{tool_call_id:。role:'tool',content:
JSON.stringify};按理说,}
if{
const result=tool.parameterSchema.safeParse;不过,if{
return{tool_call_id:。role:'tool',content:
JSON.stringify};其实,}
args=result.data;}
args=this.sanitizeArgs;try{
const res=await this.executeWithTimeout,tool.timeout?,3000);return{tool_call_id:,role:'tool'。content:
JSON.stringify)};怎么说呢,}catch{
return{tool_call_id:。role:'tool',content:
JSON.stringify};说起来,}
}
private sanitizeArgs:any{
if return this.sanitizeString;if{
const out=Array.isArray?:{},for){
out=this.sanitizeArgs;}
return out;其实,}
return v;}
private sanitizeString:string{
return s.replace
.replace
.replace;}
private sanitizeResult:any{/* 敏感信息过滤 */}

三、并行工具调用的并发执行


async executeAll(
toolCalls:Array<{id:string,type:'function',function:{name:string,arguments:string}}>
):Promise{
const results=await Promise.allSettled(
toolCalls.map)
);return results.map=>">
r.status==='fulfilled'?r.value:{
tool_call_id : toolCalls.id。role:'tool',content : JSON.stringify
};}),}

四、完整多轮 Function Calling 流程


class AIFunctionCallingOrchestrator{
private executor : FunctionCallingExecutor;private sseClient : SSEClient;private maxRounds =5;constructor{ this.executor=exec,this.sseClient=sse;其实,}
async chat : Promise{
let hist=;for{
const resp=await this.sendRequest;if{
return resp.content?,'';}
hist.push,const toolsRes=await this.executor.executeAll;toolsRes.forEach(r=>
hist.push);if throw new Error;}
}
private async sendRequest : Promise{
const r=await fetch('/api/chat'。{method:'POST',headers:{'Content-Type':'application/json'},body : JSON.stringify({
& nbsp;model:'gpt-4o-mini',& nbsp;messages,& nbsp;tools:this.executor.getToolDefinitions,& nbsp;tool_choice:'auto'
})});const d=await r.json;return d.choices.message;}
}

五、前端可注册的典型工具示例


// 天气查询
executor.registerTool({
name的观点是,'get_wear',description:'获取指定城市的当前天气',parameters:{
type这方面。'object',properties:{
至于city,{type:'string',description:'城市名称'},unit:{type:'string',description:'温度单位',enum:}
},required:
},parameterSchema:z.object.min}),handler : async =>{
const res=await fetch}`);return res.json;},permission:'read'
});// 网页搜索
executor.registerTool({
再看name,'web_search',description:'在互联网上搜索信息',parameters:{
再看type,'object',properties:{
query这方面,{type:'string',description:'搜索关键词'},count:{type:'number'。description:'返回数量'}
},required:
},parameterSchema:z.object,count:z.number.min.max.optional}),handler : async =>{
const r=await fetch('/api/search',{method:'POST',body:
JSON.stringify});return r.json;},permission :'read'
});// 危险代码执行
executor.registerTool({
name :'execute_code',description :'在沙箱中执行 JavaScript代码',parameters:{
type :'object',properties:{ code:{type :'string'。description :'JS代码'}},required:
},parameterSchema:z.object.max}),handler : async =>executeInSandbox,permission :'dangerous',timeout :5000,});老实说,

RAG 前端调整实战

RAG 不只是后端的事

  • L​LM 检索到的不相关文档直接返回。使用者无法看到依据,导致信任度低。
  • 高频相同查询每次都走向量检索和网络请求,延迟和成本居高不下。
  • 检索结果只做文字堆砌,没有可视化方便使用者定位关键信息。其实,
  • User Feedback 缺失——后端无法感知哪些 chunk 真正有价值。难以迭代排序模型,不过,
  • L​LM 在模糊查询上表现差。需要在前端对查询进行 召回率。话说回来,

一、RAG 链路中的前端调整点


使用者输入查询 → → 向量检索 → → 排序
↓ ↓
使用者反馈 ← ← 最终回答 ←

  • :基于对话上下文 或消歧。提高检索命中率,
  • :利用 IndexedDB 本地缓存高频向量检索及其返回;按理说,
  • :展示每个 chunk 的来源、相似度还有摘要;其实,
  • :记录点击/展开/忽略等交互。为后续 Rerank 提供监督信号。

二、查询 :前端侧的使用者意图

Pain Point:L​LM 对简短或含指代的问题检索效果差,需要在前置阶段补全上下文。说起来,


class QueryRewriter{
private ctx:Array;constructor { this.ctx=context;}
/** 主入口 */
rewrite:string{
let r=q;r=this.resolveReferences;r=this.expandWithContext;r=this.enhanceKeywords;不过,return r,}
private resolveReferences:string{
const recent=this.ctx.slice;
话说回来,const entityPatterns=;let lastEntity='';老实说,for{
for{
const mch=m.content.match;if lastEntity=mch;老实说,}
}
if{
q=q.replace;}
return q,}
private expandWithContext:string{
if{
const lastUser=this.ctx.filter.pop?.content,if q=${q} }…),}
return q;}
private enhanceKeywords:string{
const synonyms={
再看'前端'。'组件':,'状态管理':,'渲染':
};let out=q,for){
if) out+=});}
return out;}
}

进阶方案: 使用轻量本地 LLM在浏览器完成一次语义 可进一步提高召回质量且费用远低于主模型。

三、向量检索缓存:IndexedDB 存储高频查询结果

Pain Point:L​LM 每次都要重新计算 embedding 并请求后端向量库,导致响应时间>1s 且成本累积。


interface CachedRetrievalResult{
query这方面,string;documents:Array<>;timestamp:number;hitCount:number;}

interface RetrievedDocument{ id这方面,string;怎么说呢,content:string;score:number;metadata:{ 至于source,string;chunkIndex:number;},}

class RAGFrontendCache{ private dbName='rag-cache';private storeName='retrievals';private db,:IDBDatabase;说起来,

async init{ this.db= await this.openDB;}

async get:Promise<>"> { const tx=this.db.transaction;const store=tx.objectStore;const rec=await store.get;if return null;

// 超时失效 if-rec.timestamp>){ await this.delete;return null,}

// 更新命中次数 rec.hitCount++;const wtx=this.db.transaction;wtx.objectStore.put;return rec as CachedRetrievalResult;}

async set>) { const tx=this.db.transaction;tx.objectStore.put({ …result,timestamp:Number)。hitCount:Number });}

async delete{…} async cleanup{…}

private openDB:Promise<$IDBDatabase>"…省略实现,";}

使用示例

typescript class RAGFrontendOptimizer{ private cache=new RAGFrontendCache;constructor{ this.cache.init;}

async retrieve{ const rewritten=new QueryRewriter.rewrite;let cached = await this.cache.get;怎么说呢,if{ console.log;return cached.documents;} // 未命中 -> 调用后端 API const docs = await fetch('/api/rag/retrieve'。{method:"POST",body:JSON.stringify}).n);await this.cache.set),hitCount:-});return docs,} }

四、文档切片可视化

Pain Point:L​LM 给出的答案往往缺乏来源说明,使得业务方难以审计或追溯。


interface ChunkHighlight{
documentId:string;怎么说呢,chunkIndex:number;content:string;score:number;isHighlighted:boolean;}

class RAGVisualizationPanel{ private container!:HTMLElement;

constructor{ this.container = containerElmt;} render>) { this.container.innerHTML='';const header=document.createElement;header.className='rag-header';header.textContent=参考文档;this.container.appendChild;

chunks.forEach)));}

private createChunkItem>) { const el=document.createElement;el.className=rag-chunk ${c.isHighlighted?'highlighted':''};el.dataset.chunkId=c.chunkIndex.toString;el.dataset.documentId=c.documentId;不过,

el.innerHTML= <div class="rag-chunk-header"> < span class="rag-source">${c.documentId}</span> < span class="rag-score">${.toFixed}%</span> </div> < div class="rag-chunk-content">${this.truncate}</div>;

el.addEventListener=>this.expandChunk);return el,}

private truncate{return txt.length<=len?txt:text.slice+'...';}

private expandChunk>) { alert;// 实际项目可以弹出 modal 并同步高亮答案对应段落 } }

五、使用者反馈驱动的 Rerank 信号采集

Pain Point:L​M 模型无法直接感知哪些检索块被使用者认为有价值,导致持续出现“无关答案”。


interface RAGFeedback{
至于query,String,chunkId:String,documentId:String,feedbackType:"relevant"|"irrelevant"|"partially_relevant"。userAction:"clicked"|"ignored"|"expanded"|"copied",timestamp:Number,}

class RAGFeedbackCollector{ private feedbacks:RAGFeedback=;setCurrentQuery{this.currentQuery=q;怎么说呢,} record{ this.feedbacks.push;// 实时上报至后端用于模型再训练 / 排序微调 fetch('/api/rag/feedback',{method:"POST"。headers:{'Content-Type':'application/json'},body: JSON.stringify}).catch=>console.warn);} observe{ containerElmt.addEventListener=>{ const target=.closest;ifreturn,const cid=target.dataset.chunkId!,const did=target.dataset.documentId!,this.record({ 说到query,this.currentQuery,chunkId:id,documentId:didd。feedbackType:"relevant",userAction:"clicked",timestamp:Number) });}),} private currentQuery='';}

六、RAG 前端调整完整模块


class RAGFrontendEnhancer{
private rewriter=new QueryRewriter;private cache=new RAGFrontendCache;private visualizer!:RAGVisualizationPanel;private feedbackCollector=new RAGFeedbackCollector;其实,

constructor{ this.visualizer=new RAGVisualizationPanel;this.cache.init;this.feedbackCollector.observe;}

async query:Promise<{answer:String,sources:Array<>}>{ // 步骤1:查询 const rewritten=this.rewriter.rewrite;this.feedbackCollector.setCurrentQuery;不过,

// 步骤2:缓存读取 let cached = await this.cache.get;let docs:Array<>;

if{ console.log;docs=cached.documents;}else{ // 步骤3:后端向量检索 docs = await fetch('/api/rag/retrieve',{ 至于method。"POST",headers:{'Content-Type':'application/json'},body) }).n);

await this.cache.set({ 说到query。s,documents:DOCS,timestamp:Number),hitCount:-1});}

// 步骤4:可视化展示 this.visualizer.render(docs.map(d=>({ documentId:d.metadata.source。chunkIndex:d.metadata.chunkIndex,content:d.content,score:d.score,isHighlighted:false})) );

// 步骤5:基于检索块生成答案 const answer = await fetch('/api/rag/generate'。{ 说到method,"POST",headers:{'Content-Type':'application/json'},body) }).n);

return {answer:s.answer,sources:this.visualizer||};} }

实践任务 – FunctionCallingExecutor 实现要求

  • 实现一个支持动态注册 / 注销工具的 Executor;
  • 使用 Zod 完成参数 Schema 校验;
  • 实现 read / write / dangerous 三层权限控制;
  • 支持多工具并行调用;
  • 加入超时控制与错误兜底;
  • 实现敏感信息过滤逻辑。
  • <\/ul>

    实践任务 – RAG 前端提高模块实现要求

    • 查询 器需实现指代消解、上下文 和关键词提高;
    • 使用 IndexedDB 缓存高频查询,每条记录默认保留1 小时;
    • 提供 Chunk 可视化面板。展示来源、相似度及内容预览,并支持点击展开;
    • 收集使用者对每个 Chunk 的点击 / 展开等行为并实时上报后端 API;怎么说呢,
    • <\/ul>

      面试题解析 – FunctionCalling 流程要点

      Q :前端如何处理 LLM 的 Function Calling 流程?

      • 协议理解:> arguments 为 JSON 字符串,需要安全 parse。<\/ li>
      • 执行步骤:> 查找工具 → 权限检查 → 参数校验 → XSS 防护 → 沙箱或普通执行 → 超时控制 → 格式化返回。\<\/ li>
      • 并发处理:> 多 tool_calls 使用 Promise.allSettled 容忍局部失败。\<\/ li>
      • 多轮循环:> 工具结果回传后继续让 LLM 基于新上下文决定是否 调用。\<\/ li>
      • 安全防线:> 参数 Schema + XSS 清理 + 敏感字段过滤 + 最大轮数限制。\<\/ ul>

        Q :RAG 在前侧可以做哪些调整?

        • 基于对话上下文进行指代消解与关键词同义词 让向量召回更精准。<\/ li>
        • 利用 IndexedDB 缓存 embedding 与检索结果,大幅降低网络 RTT 与算力成本。<\/ li>
        • 将每个命中文档块以卡片形式呈现。并标注相似度与来源,提高透明度与信任感。<\/ l i>
        • 捕获点击 / 展开 / 忽略等行为,将结构化反馈上报用于离线 rerank 或在线排序微调。<\/ l i>

        /主要洞察/<\/ p>


标签: 工程

SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback