본문 바로가기
웹 개발

[llama] Flutter로 chatBot App 만들기

by doraemin_dev 2025. 2. 3.

STEP 0. 백엔드 준비 (이전 글 참조)

https://doraemin.tistory.com/120

 

[Docker] FastAPI container 설치 및 실행 with llama

도커 이미지 빌드 & 테스트# 0. 먼저, Docker Desktop 앱 실행하자.# Docker Desktop이 설치 안 되어있다면, https://www.docker.com/get-started/ 에서 설치.# 1. FestAPI.zip 압축파일의 압축 풀고 vsCode 실행# 2. 터미널을

doraemin.tistory.com

 

STEP 1. FastAPI 수정

PS C:\Users\032\SKT_AI\FastAPI> docker exec -it fastapi bash
>>
root@c40a0e51c864:/usr/src# pip install httpx

 

main.py 변경하기

플러터 앱과 통신을 위해 몇 가지 코드를 추가 했습니다.

from fastapi import FastAPI, Form
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
import httpx
import json

app = FastAPI()

# CORS 설정
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class RequestModel(BaseModel):
    model: str
    prompt: str

class Message(BaseModel):
    message: str

@app.post("/chat")
async def chat(message: Message):
    prompt = message.message
    # 요청할 URL
    url = "http://host.docker.internal:11434/api/generate"
    # 요청에 포함할 데이터
    data = {
        "model": "llama3.1:8b",
        "prompt": prompt
    }
    # 요청 헤더
    headers = {
        "Content-Type": "application/json"
    }
    
    async with httpx.AsyncClient() as client:
        response = await client.post(url, headers=headers, data=json.dumps(data))

    if response.status_code == 200:
        # 개별 JSON 객체로 분할
        json_objects = response.content.decode().strip().split("\n")
        # 각 JSON 객체를 Python 사전으로 변환
        data = [json.loads(obj) for obj in json_objects]
        res_text = ''
        # 변환된 데이터 출력
        for item in data:
            print(item)
            res_text += item['response']
    else:
        res_text = f"Error Code : {response.status_code}"
    return {"reply": res_text}

 


STEP 2.플러터 프로젝트 시작

플러터 설치 및 환경변수 설정은 아래 글 참고...

https://cafe.naver.com/aiclubcafe/673

 

Flutter - 개발환경 구축하기

1. Windows에서 설치 https://flutter-ko.dev/docs/get-started/install/windows 위 주소로 이동 합니다. "Flutter_wi...

cafe.naver.com

 

Android Studio를 실행하여, 몇가지 코드를 추가하자.

# pubspec.yaml > 37번째 줄에 아래 코드 추가

http: ^0.13.3 # 추가하자

# 이후 Pub get 클릭!

# Androidmanifest.xml > 2번째줄과 16번째 줄에 추가

<uses-permission android:name="android.permission.INTERNET" />

android:usesCleartextTraffic="true" > # 15번째 줄의 '>'닫는 괄호는 삭제

main.dart

먼저 최종 코드로 변경하기

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Chatbot',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChatScreen(),
    );
  }
}

class ChatScreen extends StatefulWidget {
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final TextEditingController _controller = TextEditingController();
  final List<Map<String, String>> _messages = [];

  Future<void> _sendMessage(String message) async {
    if (message.isEmpty) return;

    setState(() {
      _messages.add({'sender': 'user', 'text': message});
    });

    _controller.clear();

    final response = await http.post(
      Uri.parse('http://127.0.0.1:88/chat'), // 여러분의 FastAPI IP와 Port 에 맞게 수정해 주세요!
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{'message': message}),
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(utf8.decode(response.bodyBytes));
      setState(() {
        _messages.add({'sender': 'bot', 'text': data['reply']});
      });
    } else {
      setState(() {
        _messages.add({'sender': 'bot', 'text': '서버와의 통신 오류가 있습니다.'});
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Chatbot'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: _messages.length,
              itemBuilder: (context, index) {
                final message = _messages[index];
                final isUser = message['sender'] == 'user';
                return ListTile(
                  title: Align(
                    alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,
                    child: Container(
                      padding: EdgeInsets.all(10),
                      decoration: BoxDecoration(
                        color: isUser ? Colors.blue : Colors.grey,
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: Text(
                        message['text']!,
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: InputDecoration(
                      hintText: 'Enter your message...',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                    ),
                  ),
                ),
                SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () => _sendMessage(_controller.text),
                  child: Text('Send'),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

 

 

Chrome(web)으로, main.dart를 실행(초록색 버튼) !

자동으로 크롬 웹페이지가 뜨면서, Chatbot을 사용할 수 있다!

// 포트 번호는 이전에 설정한 포트 번호로 변경 ex.8000

 


참고 문서 ; 이경용 대표님 강의자료

OpenAI - ChatGPT

Llama 모델 챗봇 앱 만들기

라마 모델 사용하기 https://cafe.naver.com/aiclubcafe/823

라마 모델과 FastAPI와 연동하기 https://cafe.naver.com/aiclubcafe/943

라마 연동 플러터 챗봇 앱 만들기 https://cafe.naver.com/aiclubcafe/945

플러터 STT, TTS 라이브러리 활용해서 음성 챗봇 만들기 https://cafe.naver.com/aiclubcafe/946