flutter3+deepseek手机端ai流式输出聊天模板

举报
yxybox 发表于 2025/06/03 06:16:19 2025/06/03
【摘要】 flutter3-deepseek:原创基于flutter3.27+dio+deepseek-v3+markdown从0-1纯手撸流式输出AI对话聊天小助手。集成 Flutter3 接入 DeepSeek-V3 会话大模型。支持代码高亮、本地会话存储、支持手机端/桌面端显示。

AI新作flutter3.27+deepseek+dio实战仿DeepSeek流式打字AI聊天对话模板。

uni-app+deepseek-v3跨三端ai流式输出对话模板

deepseek-v3+vue3.5网页版webai流式对话模板

基于vite6+deepseek-v3搭建智能ai聊天助手

未标题-2.png

未标题-k.png

运用技术

  • 技术框架:flutter3.27.1+dart3.6.0
  • AI对话模型:deepseek-v3
  • 网络请求:dio^5.8.0+1
  • 路由/状态管理:get^4.7.2
  • 本地存储:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮插件:flutter_highlight^0.7.0
  • 弹框组件:shirne_dialog^4.8.3
  • 图片预览:easy_image_viewer^1.5.1

p3.gif

p2.gif

项目结构目录

360截图20250523212439152.png

001360截图20250522215745701.png

002360截图20250522215833249.png

002360截图20250522215856401.png

002360截图20250522220014461.png

004360截图20250522225649758.png

002360截图20250522220428280.png

003360截图20250522221329540.png

003360截图20250522221513693.png

003360截图20250522223826901.png

003360截图20250522224758837.png

003360截图20250522225233589.png

004360截图20250522225726466.png

005360截图20250522225942714.png

006360截图20250522230031556.png

007360截图20250522232504342.png

007360截图20250522233245183.png

008360截图20250522233444039.png

008360截图20250522233956422.png

008360截图20250522234252862.png

flutter配置.env

# 项目名称
APP_NAME = 'Flutter3-DeepSeek'

# DeepSeek API配置
DEEPSEEK_API_KEY = your apikey
DEEPSEEK_BASE_URL = https://api.deepseek.com

main.dart配置

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

import 'controller/app.dart';
import 'controller/chat.dart';

// 引入路由配置
import 'router/index.dart';

void main() async {
  // 初始化存储服务
  await GetStorage.init();

  // 将.env文件内容加载到dotenv中
  await dotenv.load(fileName: '.env');

  // 注册GetxController
  Get.put(AppStore());
  Get.put(ChatStore());

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // 获取AppStore实例
    final appStore = AppStore.to;
    
    return GetMaterialApp(
      title: 'Flutter3 DeepSeek',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Color(0xFF4F6BFE)),
        useMaterial3: true,
        fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null,
      ),
      // 初始路由
      initialRoute: appStore.isLogin ? '/' : '/login',
      // 路由页面
      getPages: routePages,
      navigatorKey: MyDialog.navigatorKey,
      localizationsDelegates: [
        ShirneDialogLocalizations.delegate,
      ],
    );
  }
}

未标题-d.png

项目模板

@override
Widget build(BuildContext context) {
  return Scaffold(
    key: scaffoldKey,
    backgroundColor: Colors.white,
    appBar: AppBar(
      ...
      actions: [
        IconButton(icon: Icon(Icons.try_sms_star_outlined), onPressed: () => handleCreate(),),
      ],
    ),
    body: Center(
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxWidth: 750.0,
        ),
        child: Flex(
          direction: Axis.vertical,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Stack(
                children: [
                  GestureDetector(
                    child: ScrollConfiguration(
                      behavior: CustomScrollBehavior().copyWith(scrollbars: false),
                      // GetBuilder响应流式输出
                      child: Obx(() {
                        if (chatStore.currentMessages.isEmpty) {
                          // 欢迎信息
                          return Welcome(
                            onChanged: (value) {
                              textEditingController.text = value;
                            },
                          );
                        }
                        return ListView.builder(
                          keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, // 当滚动时候隐藏键盘
                          controller: scrollController,
                          padding: EdgeInsets.all(10.0),
                          reverse: true,
                          shrinkWrap: true,
                          itemCount: chatStore.currentMessages.length,
                          itemBuilder: (context, index) {
                            ...
                          }
                        );
                      }),
                    ),
                    onTap: () {
                      focusNode.unfocus();
                    },
                  ),
                  // 滚动到底部
                  AnimatedPositioned(
                    ...
                  ),
                ],
              ),
            ),
            // 底部编辑器区域
            ChatEditor(controller: textEditingController),
          ]
        ),
      ),
    ),
    // 侧边栏
    drawer: Drawer(
      child: Sidebar(),
    ),
  );
}

flutter配置markdown

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_highlight/flutter_highlight.dart';
import 'package:flutter_highlight/themes/github.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:easy_image_viewer/easy_image_viewer.dart';
import 'package:markdown/markdown.dart' as md;

class FMarkdown extends StatefulWidget {
  const FMarkdown({
    super.key,
    required this.data,
  });

  final String data;

  @override
  State<FMarkdown> createState() => _FMarkdownState();
}

class _FMarkdownState extends State<FMarkdown> {
  @override
  Widget build(BuildContext context) {
    return MarkdownBody(
      data: widget.data,
      fitContent: false,
      styleSheet: MarkdownStyleSheet(
        blockSpacing: 12.0,
        // 表格
        tableBorder: TableBorder.all(color: Colors.black12),
        // 水平线
        horizontalRuleDecoration: BoxDecoration(
          border: Border(top: BorderSide(color: Colors.black12, width: 1.0)),
        ),
        // 代码块
        codeblockDecoration: BoxDecoration(
          color: Color(0xfff8f8f8),
          borderRadius: BorderRadius.circular(10.0),
        ),
        // 引用
        blockquotePadding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
        blockquoteDecoration: BoxDecoration(
          border: Border(left: BorderSide(color: Colors.black12, width: 4.0)),
        )
      ),
      builders: {
        // 自定义代码/代码块构建
        'code': CustomCodeBuilder(),
      },
      // 自定义图片构建
      sizedImageBuilder: (config) => ImageBuilderWidget(config: config),
      // 点击链接
      onTapLink: (text, href, title) async {
        if (href != null) {
          if(await canLaunchUrl(Uri.parse(href))) {
            await launchUrl(Uri.parse(href));
          }else {
            debugPrint('无法访问 $href');
          }
        }
      },
    );
  }
}

未标题-7.png

flutter流式输出对话

final response = await dio.post(
  '$baseURL/v1/chat/completions',
  options: Options(
    // 响应超时
    receiveTimeout: const Duration(seconds: 60),
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer $apiKEY",
    },
    // 设置响应类型为流式响应
    responseType: ResponseType.stream,
  ),
  data: {
    // 多轮会话
    'messages': widget.multiConversation ? chatStore.historySession : [{'role': 'user', 'content': editorValue}],
    'model': 'deepseek-chat', // deepseek-chat对话模型 deepseek-reasoner推理模型
    'stream': true, // 流式输出
    'max_tokens': 8192, // 限制一次请求中模型生成 completion 的最大 token 数(默认使用 4096)
    'temperature': 0.4, // 严谨采样 越低越严谨(默认1)
  }
);

作者:xiaoyan2017
链接:https://www.cnblogs.com/xiaoyan2017/p/18894117
来源:博客园
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。