File size: 4,001 Bytes
254aa75
c81ad68
 
 
 
 
 
a1b9605
 
c81ad68
 
 
 
 
a1b9605
c81ad68
 
 
 
 
 
a1b9605
c81ad68
254aa75
c81ad68
 
 
 
a1b9605
c81ad68
 
 
 
 
a1b9605
c81ad68
 
 
a1b9605
c81ad68
 
a1b9605
c81ad68
 
 
254aa75
c81ad68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254aa75
c81ad68
 
 
 
 
 
 
 
 
254aa75
c81ad68
 
254aa75
c81ad68
 
 
 
254aa75
c81ad68
 
 
 
 
 
 
a1b9605
c81ad68
a1b9605
c81ad68
 
a1b9605
254aa75
c81ad68
df03933
 
 
 
254aa75
 
df03933
 
254aa75
 
 
df03933
254aa75
 
a1b9605
c81ad68
 
a1b9605
c81ad68
a1b9605
c81ad68
a1b9605
254aa75
c81ad68
 
 
a1b9605
254aa75
c81ad68
 
a1b9605
 
 
c81ad68
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# coding: utf-8
from openai import OpenAI
from docx import Document
import numpy as np
import faiss
from sentence_transformers import SentenceTransformer
import os
import gradio as gr

# 配置参数
WORD_DOC_PATH = "知识库.docx"  # Word文档路径
VECTOR_INDEX_PATH = "faiss_index.index"  # 向量索引保存路径
TEXT_DATA_PATH = "text_data.npy"  # 文本数据保存路径
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"  # 嵌入模型

# 初始化模型和客户端
client = OpenAI(
    base_url='https://api-inference.modelscope.cn/v1/',
    api_key='7ed44f86-e2c6-4b85-9c4a-26eacfc2e5ee',
)
embedder = SentenceTransformer(EMBEDDING_MODEL)

def process_word_document():
    """处理Word文档并分块"""
    doc = Document(WORD_DOC_PATH)
    chunks = []
    current_chunk = []
    chunk_size = 300

    for para in doc.paragraphs:
        text = para.text.strip()
        if text:
            words = text.split()
            current_chunk.extend(words)

            while len(current_chunk) > chunk_size:
                chunks.append(" ".join(current_chunk[:chunk_size]))
                current_chunk = current_chunk[chunk_size:]

    if current_chunk:
        chunks.append(" ".join(current_chunk))

    return chunks

def create_vector_store():
    """创建并保存向量存储"""
    if os.path.exists(VECTOR_INDEX_PATH):
        return

    chunks = process_word_document()
    embeddings = embedder.encode(chunks, convert_to_tensor=False)
    embeddings = np.array(embeddings).astype('float32')

    dimension = embeddings.shape[1]
    index = faiss.IndexFlatL2(dimension)
    index.add(embeddings)

    faiss.write_index(index, VECTOR_INDEX_PATH)
    np.save(TEXT_DATA_PATH, np.array(chunks))

def search_knowledge(query, top_k=3):
    """知识检索"""
    index = faiss.read_index(VECTOR_INDEX_PATH)
    text_data = np.load(TEXT_DATA_PATH, allow_pickle=True)

    query_embedding = embedder.encode([query], convert_to_tensor=False)
    query_embedding = np.array(query_embedding).astype('float32')

    distances, indices = index.search(query_embedding, top_k)
    return "\n".join([text_data[i] for i in indices[0]])

def respond(message, history, max_tokens, temperature, top_p, user_input):
    """Gradio响应函数"""
    # 检索相关知识
    context = search_knowledge(user_input)
    
    # 构建对话消息
    messages = [
        {"role": "system", "content": f"基于以下知识回答问题,如果不知道就说不知道:\n{context}"},
        {"role": "user", "content": user_input}
    ]

    # 流式生成响应
    full_response = ""
    response = client.chat.completions.create(
        model='deepseek-ai/DeepSeek-R1',
        messages=messages,
        stream=True,
        max_tokens=max_tokens,
        temperature=temperature,
        top_p=top_p
    )

    done_reasoning = False
    for chunk in response:
        reasoning_chunk = chunk.choices[0].delta.reasoning_content or ""
        answer_chunk = chunk.choices[0].delta.content or ""
        
        if reasoning_chunk:
            full_response += reasoning_chunk
            print(reasoning_chunk, end='', flush=True)
        elif answer_chunk:
            if not done_reasoning:
                print('\n\n=== 最终答案 ===\n')
                done_reasoning = True
            print(answer_chunk, end='', flush=True)
    
    print("\n" + "="*50)
    return full_response

# 初始化向量存储
create_vector_store()

# 创建Gradio界面
demo = gr.ChatInterface(
    fn=respond,
    additional_inputs=[
        gr.Textbox(label="用户提问"),
        gr.Slider(512, 2048, value=512, step=1, label="最大Token数"),
        gr.Slider(0.1, 2.0, value=0.7, step=0.1, label="温度参数"),
        gr.Slider(0.1, 1.0, value=0.95, step=0.05, label="Top-p采样"),
    ],
    theme=gr.themes.Soft(),
    title="制度文档问答系统",
    description="输入关于广西警察学院制度的问题进行问答"
)

if __name__ == "__main__":
    demo.launch()