java
主页 > 软件编程 > java >

使用React和Java实现文本摘要小工具

2024-11-19 | 佚名 | 点击:

在当今互联网时代,GPT、文心一言、通义千问等等模型的不断兴起,互联网可能正进入一个AI时代。本文讲通过一个小案列来讲述我们怎么通过AI给我们的项目、产品等赋能。本文将详细介绍如何使用 React 和 Java 搭建一个小型文本摘要工具,并基于 Hugging Face 提供的 API 来实现智能摘要功能。从功能分析到代码实现,我们将为你展现一个完整的技术实现过程。

项目目标

我们的目标是构建一个 Web 应用,用户可以通过简单的界面输入文本并快速获取摘要内容。具体功能包括:

技术栈

前端

后端

项目实现

1. 创建后端服务

1.1 项目结构

我们将采用分层架构,将代码分为以下模块:

目录结构如下:

backend/
├── src/main/java/com/lucifer/summarizer/
│   ├── config/            # 配置类
│   ├── controller/        # 控制器
│   ├── service/           # 服务层
│   ├── client/            # AI服务交互
│   ├── dto/               # 数据传输对象
│   ├── exception/         # 异常处理
│   └── SummarizerApplication.java
└── src/main/resources/
    ├── application.yml    # 配置文件
 

1.2 核心代码实现

1. 配置文件

application.yml

1

2

3

4

5

6

server:

  port: 8080

?

huggingface:

  api-key: your-huggingface-api-key

  model-url: https://api-inference.huggingface.co/models/facebook/bart-large-cnn

2. 配置类

HuggingFaceConfig.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

package com.lucifer.summarizer.config;

?

import lombok.Getter;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Configuration;

?

@Configuration

@Getter

public class HuggingFaceConfig {

?

    @Value("${huggingface.api-key}")

    private String apiKey;

?

    @Value("${huggingface.model-url}")

    private String modelURL;

}

?

3. 数据传输对象 (DTO)

TextInputDTO.java

1

2

3

4

5

6

7

8

9

10

11

12

13

package com.lucifer.summarizer.dto;

?

import jakarta.validation.constraints.NotBlank;

import lombok.Data;

?

import java.io.Serializable;

?

@Data

public class TextInputDTO implements Serializable {

?

    @NotBlank(message = "文本不能为空")

    private String text;

}

TextOutputDTO.java

1

2

3

4

5

6

7

8

9

10

11

package com.lucifer.summarizer.dto;

?

import lombok.AllArgsConstructor;

import lombok.Data;

?

@Data

@AllArgsConstructor

public class TextOutputDTO implements Serializable {

?

    private String summary;

}

4. 客户端

HuggingFaceClient.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

package com.lucifer.summarizer.client;

?

import com.lucifer.summarizer.config.HuggingFaceConfig;

import lombok.AllArgsConstructor;

import okhttp3.*;

import org.springframework.stereotype.Component;

?

import java.io.IOException;

?

@Component

@AllArgsConstructor

public class HuggingFaceClient {

?

    private final HuggingFaceConfig config;

?

    public String getSummary(String text) throws IOException {

        OkHttpClient client = new OkHttpClient();

?

        RequestBody body = RequestBody.create(

                "{"inputs":"" + text + ""}",

                MediaType.get("application/json")

        );

        Request request = new Request.Builder()

                .url(config.getModelURL())

                .addHeader("Authorization", "Bearer " + config.getApiKey())

                .post(body)

                .build();

?

        try (Response response = client.newCall(request).execute()) {

            if (response.isSuccessful()) {

                assert response.body() != null;

                return response.body().string();

            } else {

                throw new IOException("Failed to get summary: " + response.message());

            }

        }

    }

}

?

5. 服务层

SummarizerService.java

1

2

3

4

5

6

package com.lucifer.summarizer.service;

?

public interface SummarizerService {

?

    String summarizeText(String text);

}

SummarizerServiceImpl.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package com.lucifer.summarizer.service.impl;

?

import com.lucifer.summarizer.client.HuggingFaceClient;

import com.lucifer.summarizer.service.SummarizerService;

import lombok.AllArgsConstructor;

import org.springframework.stereotype.Service;

?

import java.io.IOException;

?

@Service

@AllArgsConstructor

public class SummarizerServiceImpl implements SummarizerService {

?

    private final HuggingFaceClient client;

?

    @Override

    public String summarizeText(String text) {

        try {

            return client.getSummary(text);

        } catch (IOException e) {

            throw new RuntimeException("Error while summarizing text", e);

        }

    }

}

6. 控制器

SummarizerController.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package com.lucifer.summarizer.controller;

?

import com.lucifer.summarizer.dto.TextInputDTO;

import com.lucifer.summarizer.dto.TextOutputDTO;

import com.lucifer.summarizer.service.SummarizerService;

import lombok.AllArgsConstructor;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import jakarta.validation.Valid;

?

@RestController

@AllArgsConstructor

@RequestMapping("/api/v1")

public class SummarizerController {

?

    private final SummarizerService summarizerService;

?

    @PostMapping("/summarizer")

    public ResponseEntity<TextOutputDTO> summarize(@Valid @RequestBody TextInputDTO input) {

        String summary = summarizerService.summarizeText(input.getText());

        return ResponseEntity.ok(new TextOutputDTO(summary));

    }

}

7. 异常处理

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package com.lucifer.summarizer.exception;

?

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

?

@ControllerAdvice

public class GlobalExceptionHandler {

?

    @ExceptionHandler(RuntimeException.class)

    public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error: " + ex.getMessage());

    }

?

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception ex) {

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Error: " + ex.getMessage());

    }

}

8. 服务启动

9. 接口测试

2. 创建前端界面

2.1 初始化 React 项目

使用 create-react-app 初始化项目:

1

2

npx create-react-app text-summary-app

cd text-summary-app

安装 Axios:

1

npm install axios

2.2 创建主界面组件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

import React, { useState } from "react";

import axios from "axios";

?

const TextSummary = () => {

  const [text, setText] = useState("");

  const [summary, setSummary] = useState("");

  const [loading, setLoading] = useState(false);

?

  const handleSubmit = async () => {

    if (text.trim().length < 10) {

      alert("请输入至少10个字符的文本!");

      return;

    }

?

    setLoading(true);

    try {

      const response = await axios.post("/api/v1/summarizer", { text });

      setSummary(response.data);

    } catch (error) {

      alert("请求失败,请稍后重试!");

    } finally {

      setLoading(false);

    }

  };

?

  return (

    <div style={{ padding: "20px", fontFamily: "Arial, sans-serif" }}>

      <h1>AI 文本摘要工具</h1>

      <textarea

        style={{ width: "100%", height: "150px", marginBottom: "20px" }}

        value={text}

        onChange={(e) => setText(e.target.value)}

        placeholder="输入需要摘要的文本..."

      ></textarea>

      <button onClick={handleSubmit} disabled={loading}>

        {loading ? "处理中..." : "生成摘要"}

      </button>

      {summary && (

        <div style={{ marginTop: "20px", padding: "10px", border: "1px solid #ccc" }}>

          <h2>摘要结果:</h2>

          <p>{summary}</p>

        </div>

      )}

    </div>

  );

};

?

export default TextSummary;

2.3 配置代理(开发环境)

在 package.json 中添加代理配置:

1

"proxy": "http://localhost:9527"

深入优化

1.用户体验:

2.性能优化:

3.错误处理:

4.扩展功能:

原文链接:
相关文章
最新更新