Spring AI 2.0 OA System: Architecture, RAG & Tool Calling Deep Dive

This article details the design of an AI-powered OA system built with Spring Boot 4, Vue 3, and Spring AI 2.0, covering three AI capabilities (smart leave forms, approval tracking, RAG policy QA), a four-role permission model, two-level approval engine, database schema, API endpoints, and vector retrieval configuration using Redis Stack and Alibaba Qwen models.

java1234
java1234
java1234
Spring AI 2.0 OA System: Architecture, RAG & Tool Calling Deep Dive

Project Overview

The system is an intelligent office automation (OA) platform for small and medium enterprises. On top of traditional OA core flows (leave, expense, approval), it deeply integrates Spring AI 2.0 to embed large model capabilities into real business scenarios, delivering three AI landing capabilities:

AI Smart Leave Form Fill : Employee inputs natural language like "day off next Wednesday"; system auto-calculates dates, determines leave type and days, and prompts annual leave balance and deduction rules. Technical means: Prompt engineering + structured output entity() + Tool Calling.

AI Approval Progress Query : User asks "help me check where last month's expense approval stands"; returns real node, approver, and comments. Technical means: Tool Calling (calls real business Service, not model hallucination).

Enterprise Policy RAG Q&A : Admin uploads policy files (leave, expense, seal); employees ask questions and get answers based on vector retrieval with source citations. Technical means: Tika parsing + token chunking + Redis vector store + QuestionAnswerAdvisor.

System characteristics:

Four-role permission system : ADMIN (system admin), BOSS (general manager), MANAGER (dept manager), EMPLOYEE (staff). Data scope and operation permissions isolated by level.

Two-level approval engine : Leave and expense share one approval model ( t_approval_record unified log). Thresholds on days/amount dynamically decide escalation to BOSS final review.

Four differentiated dashboards : Same /api/home/stats endpoint returns different dashboard data per login role; frontend renders ECharts charts.

Frontend-backend separation : Vue 3 + Element Plus SPA; Spring Boot provides stateless REST APIs; JWT carries login state.

Unified global time format : Date display as 2026-11-02, datetime as 2026-11-02 17:25:17 (backend Jackson unified yyyy-MM-dd HH:mm:ss, frontend utils/format.js fallback).

Business Logic Design

2.1 Role & Permission Matrix

A detailed matrix defines permissions for each role across functions: dashboard, dept management, employee management, leave/expense submission, approval center, knowledge base, announcements, AI assistant, personal center. Permission implementation is three-layered: frontend route guard via meta.roles → backend JwtInterceptor login check → method-level @RequireRole annotation auth; data scope enforced by each Service's applyScope() method assembling MyBatis-Plus query conditions per role.

2.2 User Login & Auth Flow

Diagram illustrates login process: username/password → JWT generation (HMAC-SHA, 24h expiry) → token stored in Pinia → subsequent requests carry Authorization header.

2.3 Leave Business Full Process

Leave is the most complex chain, linking AI form fill, balance check, two-level approval, and balance deduction. Key business rules:

Start node determined by applicant role ; day threshold evaluated only at department manager approval pass ( days > 3 escalates to BOSS).

Department manager's own leave skips manager node , goes directly to BOSS final review.

Admin and BOSS submissions are auto-approved (free pass).

Only PENDING state and own documents can be cancelled (to CANCELLED).

Leave balance deducted only at final approval pass ; marriage leave does not consume balance field.

New employee first balance query triggers EmployeeService.initBalance() to auto-initialize current year record (annual leave default 5 days).

2.4 Expense Business Process

Approval node permission validation ( ApprovalService.checkNodePermission): BOSS node only allow BOSS role; MANAGER node only allow MANAGER role with matching deptId; ADMIN has fallback pass-through for ops handling.

2.5 Knowledge Base Upload & Vectorization Flow

Diagram shows upload → Tika parsing → chunking → embedding via text-embedding-v4 (2048 dim) → Redis Stack HNSW/COSINE index oa-knowledge-index.

2.6 AI Assistant Conversation Flow (RAG + Tool Calling)

Diagram illustrates multi-turn chat with memory (20 messages), RAG retrieval (topK=5, threshold 0.45), and tool calls (LeaveTools, ExpenseTools, EmployeeTools). Anti-hallucination design: system prompt forces "balance and progress must call tools, no fabrication"; "if knowledge base lacks clause, explicitly answer not recorded"; tool internal user ID always from ToolContext / UserContext, preventing model from passing other user IDs for privilege escalation.

2.7 Business Rules Quick Reference

Table summarizing key rules with code locations:

Rule Item                     Value                     Code Location
Leave escalate BOSS threshold days > 3                  ApprovalService.approveLeave
Expense escalate BOSS threshold amount > 5000           ApprovalService.approveExpense
Document status             PENDING / APPROVED / REJECTED / CANCELLED   ApprovalStatusEnum
Approval node               MANAGER / BOSS / NONE       ApprovalService constants
Leave type                  Annual / Personal / Sick / Compensatory / Marriage  t_leave.leave_type
Expense type                Travel / Office / Entertainment / Transport / Other  t_expense.expense_type
Default password            123456 (MD5: e10adc3949ba59abbe56e057f20f883e)  EmployeeService.save / resetPassword
New employee annual leave   5 days                    EmployeeService.initBalance
Gender                      Only "Male/Female", default "Male"  t_sys_user.gender
Token expiry                24 hours                  oa.jwt.expire-hours
Upload root dir             D:/uploads54, access prefix /uploads  oa.upload.*

Technology Stack

3.1 Backend Stack

Category            Technology                              Version   Purpose
Base Framework      Spring Boot                             4.0.8     App skeleton, auto-config, embedded container
Web                 spring-boot-starter-webmvc              4.0.8     REST APIs, interceptors, static resources
Validation          spring-boot-starter-validation          4.0.8     Request param validation
AI Framework        Spring AI                               2.0.1     ChatClient, Advisor, Tool Calling, VectorStore
AI Model Access     spring-ai-starter-model-openai          2.0.1     OpenAI-compatible protocol to Alibaba Cloud Bailian
Vector Store        spring-ai-starter-vector-store-redis    2.0.1     Redis Stack vector retrieval
RAG                 spring-ai-vector-store-advisor          2.0.1     QuestionAnswerAdvisor knowledge augmentation
Doc Parsing         spring-ai-tika-document-reader          2.0.1     Unified parsing of txt/doc/pdf/markdown
Persistence         MyBatis-Plus (Spring Boot 4 Starter)    3.5.17    CRUD, Lambda conditions, pagination
SQL Parsing         mybatis-plus-jsqlparser                 3.5.17    Pagination plugin dependency
DB Driver           mysql-connector-j                       (Boot)    MySQL 8 connection
Cache/Vector        spring-boot-starter-data-redis + Jedis  Jedis 7.2.0 Redis connection & RediSearch vector index
Auth                JJWT                                    0.12.6    JWT generation & parsing
Runtime             JDK                                     17        Language version
Compatibility Note (Engineering Highlight) : Spring Boot 4 defaults to Lettuce, but Spring AI 2.0.1 Redis vector store depends on Jedis's RedisClient (provided since Jedis 7.2). Project explicitly upgrades Jedis and manually registers RedisVectorStore in RedisVectorStoreConfig (HNSW/COSINE). Meanwhile MyBatis-Plus requires 3.5.17 to adapt to Boot 4.0.8 removed APIs.

3.2 Frontend Stack

Category      Technology              Version   Purpose
Framework     Vue                   3.5.42    Composition API SPA
Build         Vite                  8.3.0     Dev server (5173) & production build
UI Components Element Plus          2.11.4    Table, form, dialog; table columns auto-fit browser width
Icons         @element-plus/icons-vue 2.3.2    Menu & button icons
State Mgmt    Pinia                 3.0.3     Login state, user info, roles
Routing       Vue Router            4.5.1     Route guards + role menu filtering
HTTP          Axios                 1.12.2    Request/response interceptors, token injection, unified error toast
Charts        ECharts               5.6.0     Dashboard statistics charts

3.3 Middleware & External Services

Component                 Configuration                                                           Description
MySQL 8                   127.0.0.1:3308 / db_ai_oa / root / 123456                               Primary business data store
Redis Stack 7.x           127.0.0.1:6379, requires RediSearch module, index oa-knowledge-index, HNSW + COSINE  Vector retrieval
Local File Storage        D:/uploads54/{avatar,knowledge,expense}, organized by yyyyMMdd, UUID naming  File storage
Alibaba Cloud Bailian     .../compatible-mode/v1, chat qwen3.8-27b (temp 0.3), embedding text-embedding-v4 (2048 dim)  LLM & embedding via OpenAI-compatible API

System Architecture Design

4.1 Overall Architecture

Classic frontend-backend separation + layered architecture , 10 layers top-down: User → Frontend Presentation → Frontend Support → Security Access → Controller → Business Service → AI Capability → Data Access → Data Storage → External Services. Layers depend unidirectionally; AI Capability layer and Business Service layer are peers and reuse same Services (ensuring AI answers and page data share same source).

4.2 Request Processing Chain

Diagram shows request flow through filters, interceptors, controllers, services, AI tools, and data layer.

4.3 Backend Package Structure

com.java1234
├── OaApplication.java                 Startup class
├── ai
│   ├── config                         AI-related config
│   │   ├── ChatClientConfig           ChatClient & ChatMemory (window 20)
│   │   ├── OpenAiCompatibleConfig     OpenAI compat adapter + fixed vector dim
│   │   ├── FixedDimensionEmbeddingModel Avoid remote dim detection at startup
│   │   ├── EmbeddingUsageCompatInterceptor Compat missing prompt_tokens in response
│   │   └── RedisVectorStoreConfig     Manual RedisVectorStore registration (HNSW/COSINE)
│   ├── service                        AiChatService / AiLeaveService / KnowledgeService
│   └── tool                           LeaveTools / ExpenseTools / EmployeeTools (@Tool)
├── common                             Result, PageResult, RoleEnum, ApprovalStatusEnum, BusinessException, GlobalExceptionHandler, LoginUser, UserContext (ThreadLocal), @RequireRole
├── config                             JacksonConfig (date format), MybatisPlusConfig (pagination), MetaObjectHandlerConfig (auto-fill), WebMvcConfig (CORS/interceptors/static mapping)
├── controller                         Auth / Home / Dept / Employee / Leave / Expense / Ai (7 controllers)
├── dto                                LoginRequest, LoginVO, PasswordDTO, ApprovalDTO, ChatRequest, ChatReplyVO, LeaveParseRequest, LeaveDraftVO
├── entity                             10 entities mapping 1:1 to tables (incl. transient display fields)
├── interceptor                        JwtInterceptor (login + role)
├── mapper                             10 BaseMappers + HomeStatMapper (annotation SQL stats)
├── service                            Auth / Employee / Dept / Leave / Expense / Approval / Home / Notice (8 services)
└── util                               JwtUtil, Md5Util, FileUtil
All classes and methods have Chinese comments; entity classes do not use Lombok, hand-written getters/setters.

4.4 Frontend Project Structure

client/src
├── main.js / App.vue
├── layout/index.vue          Main frame: side menu (role-filtered) + top bar
│                             Top-right avatar/name dropdown → Profile / Logout
├── router/index.js           Route table + meta.roles guard
├── stores/user.js            Pinia: token, user info, role
├── utils/request.js          Axios instance with bidirectional interceptors
├── utils/format.js           Date 2026-11-02, datetime 2026-11-02 17:25:17
├── components/AiAssistant    Global bottom-right floating AI assistant
└── views
    ├── login                 Login page
    ├── home                  Index dispatches by role → AdminHome / BossHome / ManagerHome / EmployeeHome
    ├── dept / employee       Dept & employee management
    ├── leave / expense       Leave & expense (incl. AI form fill, voucher upload)
    ├── approval              Approval center
    ├── knowledge / notice    Knowledge base & announcements
    ├── aichat                AI assistant full-screen page (session list + message stream + sources)
    └── profile               Personal center: left avatar upload + info, right password change

4.5 Key Technical Implementation Points

Theme                 Implementation
Stateless Auth        JWT carries id/username/realName/role/deptId/avatar, HMAC-SHA signature, 24h expiry
Role Auth             Custom annotation @RequireRole, interceptor reads method/class annotation vs role, 403 on fail
Login Context         UserContext based on ThreadLocal, cleaned in afterCompletion to avoid thread-pool leakage
Data Scope Isolation  Each Service's applyScope(): employee sees self, manager sees dept, BOSS/ADMIN see all pending
Unified Response      Result<T>{code,message,data}, pagination PageResult<T>{total,records}
Unified Exception     BusinessException + GlobalExceptionHandler, 401/403/500 structured output
Pagination            MyBatis-Plus PaginationInnerInterceptor
Time Format           Jackson global yyyy-MM-dd HH:mm:ss + timezone Asia/Shanghai
File Upload           FileUtil saves to subdir/yyyyMMdd/UUID.ext, returns /uploads/... relative URL, WebMvcConfig maps to disk
CORS                  Backend addCorsMappings allow; dev also Vite Proxy forwarding /api, /uploads
Password Security     MD5 digest storage, change password validates old password and new/confirm match
Home Statistics       HomeStatMapper annotation aggregation SQL (leave type pie, 6-month expense bar, dept headcount, status distribution, monthly expense total)

AI Capability Architecture

5.1 Three AI Pipelines Comparison

Dimension          Smart Leave Fill          Smart Assistant (Chat)          Knowledge Ingestion
Entry              POST /api/ai/leave/parse  POST /api/ai/chat               POST /api/knowledge/upload
Memory             None (single-turn)        MessageWindowChatMemory 20      —
Knowledge Enhance  None                      QuestionAnswerAdvisor (topK=5, threshold 0.45)  —
Tool Calling       LeaveTools                LeaveTools / ExpenseTools / EmployeeTools  —
Output Form        Structured entity(LeaveDraftVO.class)  Natural language text + source list  Vector write
Fallback           fillFallbackTip() with real balance tip  Empty answer fallback phrase  Failure sets vector_status=FAIL

5.2 Tool Calling Tool Catalog

Tool Class    Method                Parameters                          Purpose
LeaveTools    queryLeaveBalance     none (userId from ToolContext)      Query current year annual/personal/sick/compensatory quota & used
LeaveTools    queryLeaveProgress    keyword (optional)                  Query latest 5 leave requests status & current node
ExpenseTools  queryExpenseProgress  monthOffset (0/-1), keyword (opt)   Query latest 8 expense requests real approval progress, approver, comments
EmployeeTools queryMyInfo           none                                Query name, role, dept, entry date

5.3 Vector Retrieval Parameters

Parameter               Value
Index name              oa-knowledge-index
Key prefix              oa:kb:
Vector algorithm/distance HNSW / COSINE
Embedding model/dim     text-embedding-v4 / 2048
Chunk size              chunkSize=800, min chars 200, min embeddable 50
Retrieval topK/threshold 5 / 0.45
Metadata fields         docId (tag), docName (text), fileType (tag)

Functional Module Design

Four modules:

Basic Support : Login auth, personal center (avatar upload / info edit / password change, left-right layout), dept management, employee management, password reset, announcement management.

Process Office : Leave submit & cancel, leave balance, expense submit & voucher upload, approval center pending, approve/reject, approval log trace.

AI Intelligence : AI leave form fill, deduction & balance tips, multi-turn chat, session history, policy RAG Q&A with source citation, approval progress tool calls, knowledge base vectorization.

Data Dashboard : Admin global dashboard, manager approval desk, BOSS final review desk, employee personal desk; includes leave type pie, monthly expense bar, dept headcount, latest announcements.

Dashboard data differences per role:

Role      Metric Cards                                      Charts                                      List
ADMIN     Active staff, dept count, pending leave/expense   Leave type dist, 6-mo expense, dept headcount, leave status dist  Latest announcements
BOSS      Pending final review leave/expense, in-flight count, monthly expense total  6-mo expense, leave status dist  Pending final review leave/expense, announcements
MANAGER   Dept pending leave/expense, dept headcount, monthly dept expense  Dept leave type, dept 6-mo expense  Dept pending, announcements
EMPLOYEE  My pending leave/expense, approved leave, annual left  My leave type, my 6-mo expense, my leave status  My recent docs, announcements

Database Design

7.1 Design Overview

Database: db_ai_oa, charset utf8mb4 / utf8mb4_unicode_ci, MySQL 8 (port 3308).

All business tables prefixed t_, total 10 tables .

Primary key unified id BIGINT AUTO_INCREMENT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP.

Logical foreign keys (no physical constraints), service layer ensures consistency for sharding/migration ease.

Amount uses DECIMAL(12,2), days uses DECIMAL(6,1) to avoid floating errors.

Script location: server/src/main/resources/db/db_ai_oa.sql.

7.2 Table Catalog

#  Table Name          Chinese Name        Description
1  t_dept              Department          Dept base info & manager
2  t_sys_user          System User         Unified account for four roles
3  t_leave_balance     Leave Balance       Quota per user+year
4  t_leave             Leave Request       Leave application main table
5  t_expense           Expense Request     Expense application main table
6  t_approval_record   Approval Log        Shared approval log for leave & expense
7  t_knowledge_doc     Knowledge Doc       Policy files & vectorization status
8  t_chat_session      AI Session          Maps to Spring AI conversationId
9  t_chat_message      AI Message          Session messages & RAG sources
10 t_notice            Announcement        System announcements

7.3 Table Structure Details

Each table defined with columns, types, lengths, nullability, comments. Key highlights: t_dept: id, dept_name, dept_code, manager_id (logic FK to t_sys_user), parent_id (0=top), sort_num, remark, create_time. t_sys_user: id, username (unique), password (MD5, init 123456), real_name, role (ADMIN/BOSS/MANAGER/EMPLOYEE), dept_id, gender (Male/Female default Male), phone, email, avatar (relative path), entry_date, status (1 enabled/0 disabled), create_time. t_leave_balance: id, user_id, year_num, annual_total (default 10, new employee 5), annual_used, sick_used, personal_used, compensatory_total, compensatory_used. Unique constraint uk_user_year (user_id, year_num). t_leave: id, user_id, dept_id (redundant for dept isolation), leave_type (Annual/Personal/Sick/Compensatory/Marriage), start_date, end_date, days (DECIMAL(6,1), supports 0.5, >3 escalates), reason, status (PENDING/APPROVED/REJECTED/CANCELLED), current_node (MANAGER/BOSS/NONE), ai_generated (1/0), create_time. t_expense: id, user_id, dept_id, expense_type (Travel/Office/Entertainment/Transport/Other), amount (DECIMAL(12,2), >5000 escalates), expense_date, reason, attachment (comma-separated paths), status, current_node, create_time. t_approval_record: id, biz_type (LEAVE/EXPENSE), biz_id, node_name (MANAGER/BOSS), approver_id, approver_role, action_type (APPROVE/REJECT), comment_text, create_time. t_knowledge_doc: id, doc_name (original filename, used as RAG source), file_path, file_type (txt/doc/pdf/md), file_size, chunk_count, vector_status (PENDING/SUCCESS/FAIL), uploader_id, create_time. t_chat_session: id, session_id (UUID no hyphens, unique, maps to Spring AI conversationId), user_id (for ownership check), title (default "New Conversation", auto from first 20 chars), create_time, update_time (ON UPDATE). t_chat_message: id, session_id, role_name (user/assistant), content (MEDIUMTEXT ~16MB), sources_json (comma-separated doc names), create_time. t_notice: id, title, content (TEXT ~64KB), publisher, create_time.

7.4 Indexes & Constraints Summary

Table           Constraint/Index   Fields              Type
All tables      PRIMARY KEY        id                  PK, BIGINT auto-inc
t_sys_user      UNIQUE             username            Login account unique
t_leave_balance UNIQUE             uk_user_year        user_id, year_num  Employee yearly balance unique
t_chat_session  UNIQUE             session_id          Session UUID unique

7.5 Initialization Test Data

Table               Rows   Description
t_dept              4      HR, Tech, Finance, Marketing
t_sys_user          16     1 admin + 1 boss + 4 managers + 10 employees, password 123456 (MD5 stored)
t_leave_balance     14     2026 year balances
t_leave             25     Covers 5 leave types, 4 statuses, Apr-Sep 2026
t_expense           20     5 expense types, includes >5000 final review cases & voucher-attached pending
t_approval_record   18     Completed two-level approval logs
t_notice            3      AI assistant enable notice, holiday schedule, expense reminder

API Design

Unified prefix /api, unified response {"code":200,"message":"操作成功","data":{}}; except /api/auth/login all require Authorization: Bearer <token>.

Key endpoints (module, method, path, permission, description):

Auth        POST /api/auth/login          Public   Username/password login, returns token & user info
Auth        GET  /api/auth/info           Login    Current user details (incl dept name, role name)
Profile     PUT  /api/profile             Login    Update name, gender, phone, email
Profile     PUT  /api/profile/password    Login    Change password (verify old + confirm match)
Profile     POST /api/profile/avatar      Login    Upload avatar
Home        GET  /api/home/stats          Login    Returns dashboard data per role
Notice      GET  /api/notice/page         Login    Announcement pagination
Notice      POST/PUT/DELETE /api/notice   ADMIN    Announcement CRUD
Dept        GET  /api/dept/page, /list    Login    Dept pagination / full list
Dept        POST/PUT/DELETE /api/dept     ADMIN    Dept CRUD
Employee    GET  /api/employee/page, /{id} ADMIN,MANAGER Employee pagination (manager only own dept), detail
Employee    POST/PUT/DELETE /api/employee ADMIN    Employee CRUD
Employee    POST /api/employee/{id}/resetPassword ADMIN Reset password to 123456
Employee    GET  /api/employee/managers   Login    Dept manager candidate list
Leave       GET  /api/leave/page          Login    Pagination (status, leaveType, pendingOnly)
Leave       GET  /api/leave/{id}          Login    Detail + approval log
Leave       POST /api/leave               Login    Submit leave request
Leave       POST /api/leave/{id}/cancel   Login    Cancel own pending request
Leave       POST /api/leave/approve       NodeRole Approve / reject
Leave       GET  /api/leave/balance       Login    My leave balance
Expense     GET  /api/expense/page, /{id} Login    Pagination, detail
Expense     POST /api/expense             Login    Submit expense request
Expense     POST /api/expense/{id}/cancel Login    Cancel
Expense     POST /api/expense/approve     NodeRole Approve / reject
Expense     POST /api/expense/attachment  Login    Upload voucher images
AI          POST /api/ai/leave/parse      Login    Natural language → leave draft
AI          POST /api/ai/chat             Login    Multi-turn chat (RAG + tools)
AI          POST /api/ai/session          Login    New session
AI          GET  /api/ai/session/list     Login    Session list
AI          GET  /api/ai/session/{id}/messages Login Session messages
AI          DELETE /api/ai/session/{id}   Login    Delete session & memory
Knowledge   GET  /api/knowledge/page      ADMIN    Document pagination
Knowledge   POST /api/knowledge/upload    ADMIN    Upload & vectorize
Knowledge   DELETE /api/knowledge/{id}    ADMIN    Delete document & vectors
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

RAGLLM IntegrationTool CallingVue 3OA SystemSpring Boot 4Redis StackSpring AI 2.0
java1234
Written by

java1234

Former senior programmer at a Fortune Global 500 company, dedicated to sharing Java expertise. Visit Feng's site: Java Knowledge Sharing, www.java1234.com

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.