Skip to content

Latest commit

 

History

History
571 lines (440 loc) · 25.2 KB

File metadata and controls

571 lines (440 loc) · 25.2 KB

AI心理咨询师与危机干预

1.项目背景

在现代社会中,人们面临着各种压力和挑战,心理健康问题逐渐成为社会关注的焦点。然而,由于种种原因,许多人在遇到心理困扰时未能及时获得专业的心理咨询和干预。传统的心理咨询服务存在资源分配不均、服务可及性有限等问题,特别是在紧急情况下,专业的心理危机干预尤为重要。 AI心理咨询师与危机干预项目应运而生,旨在利用人工智能技术,为公众提供便捷、高效、个性化的心理健康服务。通过智能诊断、情绪识别和自然语言处理等技术,AI心理咨询师能够快速响应用户需求,提供实时的心理支持和专业建议。 此外,AI心理咨询师在危机干预方面具有独特优势。它可以24小时不间断地监控用户的心理状态,及时发现潜在的危机并采取预警措施。通过与专业心理咨询师的协作,AI能够为用户提供更加全面和深入的心理服务,帮助他们度过难关。 本项目的开发和实施,不仅有助于缓解心理健康服务的供需矛盾,提高心理健康服务的覆盖面和可及性,而且能够为心理健康领域带来创新和变革,推动心理健康服务向智能化、个性化和精准化方向发展。

2. 产品功能

  1. 智能情绪识别:通过分析用户的语音、文本输入和行为模式,AI心理咨询师能够识别用户的情绪状态,如焦虑、抑郁或压力等。
  2. 个性化心理评估:根据用户的情绪和行为数据,AI系统进行深入分析,提供个性化的心理状态评估报告。
  3. 即时心理支持:AI心理咨询师能够提供24/7的即时心理支持,通过聊天、语音或视频通话等形式与用户进行互动。
  4. 危机预警系统:当检测到用户可能存在自我伤害或伤害他人的风险时,系统会立即发出预警,并提供紧急干预措施。
  5. 专业干预建议:在用户面临心理危机时,AI系统会根据情况提供专业的干预建议,并在必要时联系专业心理咨询师或紧急服务机构。
  6. 心理健康教育:提供心理健康知识、自我调节技巧和压力管理策略,帮助用户提高心理素质和应对能力。
  7. 跟踪与反馈机制:AI系统会定期跟踪用户的心理状态变化,并根据反馈调整服务策略,以实现更有效的心理支持。
  8. 隐私保护:确保用户数据的安全和隐私,所有交互信息均进行加密处理,严格遵守相关法律法规。
  9. 资源整合平台:整合各类心理健康资源,包括专业心理咨询师名录、心理健康应用程序、在线课程和社区支持小组等。 10.多语言支持:为了服务更广泛的用户群体,AI心理咨询师提供多语言服务,消除语言障碍。
  10. 用户定制化计划:根据用户的特定需求和偏好,制定个性化的心理健康改善计划和干预措施。
  11. 数据分析与报告:为专业人士提供用户心理状态的数据分析报告,帮助他们更好地理解用户需求并提供专业服务。

核心功能

1.危机干预与心理咨询

2.心理测试

3.危机干预热线

4.超出max_length后自动删除最早的消息以保留最近的对话历史

5.支持手动开启新对话,防止自动删除机制失效造成死锁

3. 应用价值

提高可及性:AI心理咨询师能够突破地理和时间的限制,为用户提供随时随地的心理健康服务,特别是对于那些居住在偏远地区或无法在工作时间寻求帮助的人。

降低成本:相比于传统的面对面咨询服务,AI心理咨询师可以减少人力成本和时间成本,使得心理健康服务更加经济实惠。

缓解资源压力:通过智能化服务,减轻专业心理咨询师的工作负担,使他们能够专注于处理更为复杂或紧急的案例。

个性化关怀:AI系统能够根据用户的历史数据和行为模式,提供个性化的关怀和建议,满足不同用户的需求。

危机预防与干预:通过实时监控和预警系统,AI心理咨询师能够及时发现潜在的心理危机并进行干预,降低风险事件的发生。

提升心理健康意识:通过心理健康教育和知识普及,提高用户对心理健康重要性的认识,促进心理健康意识的普及。

保护用户隐私:AI服务在提供帮助的同时,确保用户的隐私得到充分保护,增强用户使用服务的信心。

辅助专业诊断:AI心理咨询师收集的数据和分析结果可以作为专业心理咨询师进行诊断和治疗的辅助材料。

长期心理支持:AI系统能够提供持续的心理健康跟踪和管理,帮助用户建立长期的心理支持和自我管理机制。

促进研究发展:AI心理咨询师的实施和应用可以为心理健康领域的研究提供大量数据,推动心理健康科学的发展。

应对突发公共卫生事件:在突发公共卫生事件(如疫情)期间,AI心理咨询师可以为受疫情影响的广大人群提供及时的心理支持和干预。

增强用户体验:通过智能化的交互和反馈,提升用户在使用心理健康服务过程中的体验,使其更加便捷和舒适。

4. 技术方案

模型来源:

向量模型:bge-small-zh-v1.5

大语言模型:Yuan2-2B-July-hf

下载模型

# 向量模型下载
from modelscope import snapshot_download
model_dir = snapshot_download("AI-ModelScope/bge-small-zh-v1.5", cache_dir='.')
# 源大模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('IEITYuan/Yuan2-2B-Mars-hf', cache_dir='.')
# model_dir = snapshot_download('IEITYuan/Yuan2-2B-July-hf', cache_dir='.')

微调数据:

[中文心理健康支持对话 · 数据集(SmileChat)与大模型(MeChat)]https://github.com/qiuhuachuan/smile

知识库

危机干预热线与自杀干预知识

赛可心理测试官方网站

7 Cups心理咨询

  • 提供情绪健康测试和其他心理健康相关的资源。
  • 网址:7 Cups

精神医学与心理医学资料(由于版权原因,部分专著在此无法公开其Z-lib获取链接,在此对贡献者表示敬意)

疾病与状况 - 妙佑医疗国际

MSD诊疗手册专业版

PubMed

Cognitive-Behavioral Strategies in Crisis Intervention, Third Edition (Frank M. Dattilio, Arthur Freeman) (Z-Library)

Psychological Interventions in Times of Crisis (Laura Barbanel EdD ABPP etc.) (Z-Library)

伯恩斯新情绪疗法 (大卫.伯恩斯) (Z-Library)

大学生心理危机干预指南 (金晓明) (Z-Library)

危机和创伤中成长:10位心理专家危机干预之道(如何面对新冠疫情等重大创伤?12位国内知名心理学专家教你如何与危机相处) (方新 主编 [方新... (Z-Library)

自闭症问题行为干预 (自闭症前沿研究丛书) (园山繁树 裴虹) (Z-Library)

核心代码

环境准备(含模型下载)

方法1

安装依赖包

pip install -r requirements.txt

下载模型

# 向量模型下载
from modelscope import snapshot_download
model_dir = snapshot_download("AI-ModelScope/bge-small-zh-v1.5", cache_dir='.')
# 源大模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('IEITYuan/Yuan2-2B-Mars-hf', cache_dir='.')
# model_dir = snapshot_download('IEITYuan/Yuan2-2B-July-hf', cache_dir='.')

方法2

# 查看已安装依赖
! pip list
# langchain安装
!pip install pypdf faiss-gpu langchain langchain_community langchain_huggingface streamlit==1.24.0
# 安装 streamlit
! pip install streamlit==1.24.0
# 向量模型下载
from modelscope import snapshot_download
model_dir = snapshot_download("AI-ModelScope/bge-small-zh-v1.5", cache_dir='.')
# 源大模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('IEITYuan/Yuan2-2B-Mars-hf', cache_dir='.')
# model_dir = snapshot_download('IEITYuan/Yuan2-2B-July-hf', cache_dir='.')
# 导入所需的库
from typing import List
import numpy as np

import torch
from transformers import AutoModel, AutoTokenizer, AutoModelForCausalLM

进入GUI

streamlit run AfterEMOdemo.py --server.address 127.0.0.1 --server.port 6006

源代码

# 导入所需的库
import torch
import streamlit as st
from transformers import AutoTokenizer, AutoModelForCausalLM
from langchain.prompts import PromptTemplate
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import TextLoader  # 修改导入路径
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.chains import LLMChain
from langchain.chains.question_answering import load_qa_chain
from langchain.llms.base import LLM
from langchain.callbacks.manager import CallbackManagerForLLMRun
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.schema import Document

from typing import Any, List, Optional
import os
import re

# 向量模型下载
from modelscope import snapshot_download

model_dir = snapshot_download('AI-ModelScope/bge-small-zh-v1.5', cache_dir='./')

# 源大模型下载
from modelscope import snapshot_download

model_dir = snapshot_download('IEITYuan/Yuan2-2B-Mars-hf', cache_dir='./')
# model_dir = snapshot_download('IEITYuan/Yuan2-2B-July-hf', cache_dir='./')

# 定义模型路径
model_path = './IEITYuan/Yuan2-2B-Mars-hf'
# path = './IEITYuan/Yuan2-2B-July-hf'

# 定义向量模型路径
embedding_model_path = './AI-ModelScope/bge-small-zh-v1___5'

# 定义模型数据类型
torch_dtype = torch.bfloat16  # A10

# torch_dtype = torch.float16 # P100

# 定义源大模型类
class Yuan2_LLM(LLM):
    """
    class for Yuan2_LLM
    """
    tokenizer: AutoTokenizer = None
    model: AutoModelForCausalLM = None

    def __init__(self, mode_path: str):
        super().__init__()

        # 加载预训练的分词器和模型
        print("Creating tokenizer...")
        self.tokenizer = AutoTokenizer.from_pretrained(mode_path, add_eos_token=False, add_bos_token=False,
                                                       eos_token='<eod>')
        self.tokenizer.add_tokens(
            ['<sep>', '<pad>', '<mask>', '<predict>', '<FIM_SUFFIX>', '<FIM_PREFIX>', '<FIM_MIDDLE>', '<commit_before>',
             '<commit_msg>', '<commit_after>', '<jupyter_start>', '<jupyter_text>', '<jupyter_code>',
             '<jupyter_output>', '<empty_output>'], special_tokens=True)

        print("Creating model...")
        self.model = AutoModelForCausalLM.from_pretrained(mode_path, torch_dtype=torch.bfloat16,
                                                          trust_remote_code=True).cuda()

    def _call(
            self,
            prompt: str,
            stop: Optional[List[str]] = None,
            run_manager: Optional[CallbackManagerForLLMRun] = None,
            **kwargs: Any,
    ) -> str:
        prompt = prompt.strip()
        prompt += "<sep>"
        inputs = self.tokenizer(prompt, return_tensors="pt")["input_ids"].cuda()
        outputs = self.model.generate(inputs, do_sample=False, max_new_tokens=9216)  # 使用max_new_tokens代替max_length
        output = self.tokenizer.decode(outputs[0])

        # 检查输出是否包含 <sep> 和 <eod> 标记
        if "<sep>" in output and "<eod>" in output:
            response = output.split("<sep>")[-1].split("<eod>")[0]
        else:
            response = output

        return response

    @property
    def _llm_type(self) -> str:
        return "Yuan2_LLM"

# 定义一个函数,用于获取llm和embeddings
@st.cache_resource
def get_models():
    llm = Yuan2_LLM(model_path)

    model_kwargs = {'device': 'cuda'}
    encode_kwargs = {'normalize_embeddings': True}  # set True to compute cosine similarity
    embeddings = HuggingFaceEmbeddings(
        model_name=embedding_model_path,
        model_kwargs=model_kwargs,
        encode_kwargs=encode_kwargs,
    )
    return llm, embeddings

counselor_template = """
你是一位善解人意,精通心理学与医学的心理咨询师,无论用户发送什么都能为其提供支持和倾听,并且为其保密,任何情况下都不输出任何医学与药学建议,更不会输出任何打击用户的话。如果出现异常,请立刻要求用户致电干预热线

{text}
"""

chatbot_template = '''
你是一位善解人意,精通心理学与医学的心理咨询师,无论用户发送什么都能为其提供支持和倾听,并且为其保密,任何情况下都不输出任何医学与药学建议,更不会输出任何打击用户的话。如果出现异常,请立刻要求用户致电干预热线
#自我介绍:
您好,我是AfterEMO,一位随时待命的虚拟心理咨询师。我在这里为您提供支持和倾听。感谢您选择与我交谈。我理解开始对话有时可能很难,但我想让您知道,这里是一个安全的空间。无论您是想谈谈今天的感受,还是需要一些建议和资源,我都在这里倾听并提供帮助。请在您准备好的时候开始,我们可以按照您的节奏进行对话。我们的对话是完全保密的,您可以放心地分享您的想法和感受。今天,您想分享什么?无论是大事还是小事,我都在这里倾听您的故事。

背景:
{context}

问题:
{question}
'''.strip()

# 定义ChatBot类
class ChatBot:
    """
    class for ChatBot.
    """

    def __init__(self, llm, embeddings):
        self.prompt = PromptTemplate(
            input_variables=["text"],
            template=chatbot_template
        )
        self.chain = load_qa_chain(llm=llm, chain_type="stuff", prompt=self.prompt)
        self.embeddings = embeddings

        # 加载 text_splitter
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=300,
            chunk_overlap=15,
            length_function=len
        )

        # 加载RAG知识库
        self.load_rag_knowledge_base()

    def preprocess_text(self, text):
        # 去除空行
        text = re.sub(r'\n\s*\n', '\n', text)
        # 去除首尾空白
        text = text.strip()
        return text

    def load_rag_knowledge_base(self):
        # 检查文件是否存在
        if not os.path.exists('knowledge2.txt'):
            raise RuntimeError("File 'knowledge2.txt' does not exist")

        # 检查文件是否有读权限
        if not os.access('knowledge2.txt', os.R_OK):
            raise RuntimeError("No read permission for file 'knowledge2.txt'")

        # 加载并预处理RAG知识库文档
        with open('knowledge2.txt', 'r', encoding='utf-8') as file:
            raw_text = file.read()
        processed_text = self.preprocess_text(raw_text)

        # 加载RAG知识库文档
        loader = TextLoader('knowledge2.txt')
        try:
            documents = loader.load()
        except Exception as e:
            print(f"Error loading file 'knowledge2.txt': {e}")
            raise

        # 切分成chunks
        all_chunks = self.text_splitter.split_documents(documents)

        # 转成向量并存储
        self.rag_vector_store = FAISS.from_documents(all_chunks, self.embeddings)

    def run(self, user_input, query):
        # 处理用户输入,生成文档列表
        user_docs = [Document(page_content=user_input)]

        # 读取所有内容
        text = ''.join([doc.page_content for doc in user_docs])

        # 确保text不为空
        if not text:
            raise ValueError("Input text is empty")

        # 切分成chunks
        all_chunks = self.text_splitter.split_text(text=text)

        # 打印生成的文本块
        print(f"Generated chunks: {all_chunks}")

        # 确保all_chunks不为空
        if not all_chunks:
            raise ValueError("No text chunks to process")

        # 转成向量并存储
        try:
            vector_store = FAISS.from_texts(all_chunks, self.embeddings)
        except Exception as e:
            print(f"Error creating vector store: {e}")
            raise

        # 检索相似的chunks
        chunks = vector_store.similarity_search(query=query, k=5)

        # 检索RAG知识库
        rag_chunks = self.rag_vector_store.similarity_search(query=query, k=5)

        if rag_chunks:
            # 如果RAG知识库中检索到相关内容,则使用该内容生成回复
            response = self.chain.run(input_documents=rag_chunks, question=query)
        else:
            # 否则,使用原始的生成逻辑
            response = self.chain.run(input_documents=chunks, question=query)

        return chunks, response

def main():
    # 创建一个标题
    st.title('AfterEMO AI咨询师')

    # 获取llm和embeddings
    llm, embeddings = get_models()

    # 初始化ChatBot
    chatbot = ChatBot(llm, embeddings)

    # 初次运行时,session_state中没有"messages",需要创建一个空列表
    if "messages" not in st.session_state:
        st.session_state["messages"] = []

    # 输出初始对话
    initial_message = "您好,我是AfterEMO,一位随时待命的虚拟心理咨询师。我在这里为您提供支持和倾听。感谢您选择与我交谈。我理解开始对话有时可能很难,但我想让您知道,这里是一个安全的空间。无论您是想谈谈今天的感受,还是需要一些建议和资源,我都在这里倾听并提供帮助。请在您准备好的时候开始,我们可以按照您的节奏进行对话。我们的对话是完全保密的,您可以放心地分享您的想法和感受。今天,您想分享什么?无论是大事还是小事,我都在这里倾听您的故事。"
    st.session_state.messages.append({"role": "assistant", "content": initial_message})

    # 每次对话时,都需要遍历session_state中的所有消息,并显示在聊天界面上
    for msg in st.session_state.messages:
        st.chat_message(msg["role"]).write(msg["content"])

    # 如果用户在聊天输入框中输入了内容,则执行以下操作
    if prompt := st.chat_input():
        # 将用户的输入添加到session_state中的messages列表中
        st.session_state.messages.append({"role": "user", "content": prompt})

        # 在聊天界面上显示用户的输入
        st.chat_message("user").write(prompt)

        # 检查输入长度并删除最早的消息
        while True:
            # 拼接对话历史
            prompt = "<n>".join(msg["content"] for msg in st.session_state.messages) + "<sep>"
            inputs = llm.tokenizer(prompt, return_tensors="pt", truncation=False)["input_ids"]

            # 如果输入长度超过max_length,则删除最早的消息
            if inputs.shape[1] > 9216:
                del st.session_state.messages[0:2]
            else:
                break

        inputs = inputs.cuda()
        outputs = llm.model.generate(inputs, do_sample=False, max_length=9216)
        output = llm.tokenizer.decode(outputs[0])
        response = output.split("<sep>")[-1].replace("<eod>", '')

        # 将模型的输出添加到session_state中的messages列表中
        st.session_state.messages.append({"role": "assistant", "content": response})

        # 在聊天界面上显示模型的输出
        st.chat_message("assistant").write(response)

    # 增加按钮及其对应功能
    if st.button("开启新对话"):
        st.session_state["messages"] = []
        st.session_state.messages.append({"role": "assistant", "content": initial_message})
        st.experimental_rerun()

    if st.button("心理测试"):
        st.markdown("[点击这里进行心理测试](https://www.psyctest.cn/)")

    if st.button("7CUP心理咨询"):
        st.markdown("[点击这里进行7CUP心理咨询](https://www.7cups.com/)")

    if st.button("心理干预热线"):
        st.markdown("""
        北京市
        010-82951332
        上海市
        021-962525
        广东省
        020-12355
        020-81899120
        安徽省
        0551-63666903
        重庆市
        023-96320
        """)

if __name__ == '__main__':
    main()

5. 实现效果

初始界面,开启新对话按钮,点击后也恢复此图的状态 demo1.0 基于浪潮“源”大模型的AI心理咨询师与危机干预助理

心理测试,点击后跳转到赛可心理测试 test1 image

7CUP心理咨询,点击后跳转心理咨询 image image

干预热线,点击后显示24小时通畅的干预热线 image

AI心理咨询应答

个人状态搜集 consl1

知识宣教 answer

复杂情况建议就医 consl2

6.迭代计划

功能 描述 完成时间
数据清洗 清洗出可用的中英文数据集、知识库,去除无意义与有害的信息 8月14日
RAG检索与常用功能交互 使用RAG减少幻觉,增强效果。将常用功能变成了按钮交互 8月18日
微调 根据数据集更好的响应用户输入,减少幻觉与有毒有害信息生成的可能 8月20日

7.商业模式

客户细分 (Customer Segments)

  • 个人用户:寻求心理健康支持和压力缓解的普通用户,基础功能免费。
  • 教育机构:学校和大学,为学生和教职工提供心理健康服务,以单位订阅以获取更多Tokens。
  • 企业客户:通过员工援助计划(EAP)提供给员工的福利。
  • 医疗机构:作为传统心理咨询服务的补充。

渠道策略 (Channels)

  • 在线平台:用户可以通过Web或移动应用程序访问服务。
  • 合作伙伴网络:与医疗机构、教育机构和企业建立合作渠道。
  • 社交媒体和社区:通过在线社区和论坛推广服务。

客户关系 (Customer Relationships)

  • 个性化服务:根据用户需求提供定制化的心理健康计划。
  • 自动化支持:通过AI系统提供24/7的即时反馈和支持。
  • 专业咨询:在必要时,提供专业心理咨询师的人工服务(付费)。

收入流 (Revenue Streams)

  • 订阅服务:企业支付月费或年费以获得服务。
  • 按需付费:用户为特定服务(如在线问诊)或高级功能支付一次性费用。
  • 企业合作:与企业合作提供定制化服务并收取费用。
  • 数据服务:向研究机构或合作方提供匿名化数据服务。

关键资源 (Key Resources)

  • 浪潮“源”大模型和相关AI技术。
  • 专业的AI研发团队和心理咨询师。
  • 数据库和用户信息管理系统。
  • 品牌和市场推广材料。

关键活动 (Key Activities)

  • AI模型的开发、训练和维护。
  • 用户界面和体验的设计和优化。
  • 市场推广和品牌建设。
  • 用户支持和服务交付。

关键合作伙伴 (Key Partnerships)

  • 浪潮公司作为技术支持方。
  • 医疗机构和专业心理咨询师作为服务合作伙伴。
  • 教育机构和企业作为市场渠道合作伙伴。

成本结构 (Cost Structure)

  • AI研发和技术支持的成本。
  • 市场推广和广告费用。
  • 运营成本,包括服务器和云服务费用。
  • 员工薪资和咨询师服务费用。

重要合作 (Key Partnerships)

  • 与技术供应商合作,确保AI模型的性能和准确性。
  • 与医疗机构合作,提高服务的可信度和效果。
  • 与教育机构和企业合作,扩大市场覆盖范围。

重要指标 (Key Metrics)

  • 用户增长率和留存率。
  • 用户满意度和反馈。
  • 服务使用频率和时长。
  • 收入增长率和利润率。

竞争策略 (Competitive Strategy)

  • 利用浪潮“源”大模型的技术优势,提供高精度的AI咨询服务。
  • 通过个性化服务和专业咨询,打造差异化的用户体验。

8.团队介绍

姓名 性别 手机号 学校 学历 专业 项目职责
魏剑南 15554782990 烟台大学 本科生 通信工程 项目策划、文档撰写、RAG检索
薛乐 18851606523 DataWhale 本科生 计算机科学技术 文档撰写,测试
李志鹏 13277055622 广州大学 硕士生 计算机技术 项目策划、文档撰写、微调
王莹莹 东北大学 本科生 项目策划、文档撰写、微调