(3)让大模型记住之前说过的话

问题

👤 研发人员提问: 今天天气怎么样

============================================================
💡 [状态:未命中库] 相似度过低,已切换为大模型原生通用大脑兜底解答!
============================================================
🤖 gemma4:12b 正在深度推理并流式输出:

由于我是一个人工智能模型,**目前无法获取您的实时地理位置信息,也无法直接连接到实时的气象监测网络。** 因此,我无法准确地告诉您您所在城市或地区目前的具体天气状况。

如果您想了解最新的天气情况,建议您通过以下方式查询:

1.  **手机自带的天气应用**:通常会自动根据您的 GPS 定位提供最精准的局部预报。
2.  **搜索引擎**:在搜索框中输入“城市名 + 天气”,即可获得详细的气温、降水概率及未来几天的趋势。
3.  **官方气象平台**:关注当地气象局发布的官方提醒,以获取更权威的防灾信息。

希望您今天无论天气如何,都能度过愉快、顺利的一天!
________________________________________

👤 研发人员提问: 你猜一下,我在杭州

============================================================
💡 [状态:未命中库] 相似度过低,已切换为大模型原生通用大脑兜底解答!
============================================================
🤖 gemma4:12b 正在深度推理并流式输出:

既然您已经“剧透”了答案,那我就不必再通过复杂的逻辑推演来猜您的所在地了。不过,既然您提到了**杭州**,这便是一个非常有意思的坐标——它不仅仅是一个地理位置,更是一个融合了深厚历史底蕴与现代科技脉动的独特空间。
  • AI 没有将两次提问关联起来

处理方式

需要引入一个 history 列表来缓存之前的对话(让大模型知道你前一句问了天气)

最终代码

import os
os.environ["no_proxy"] = "localhost,127.0.0.1"
os.environ["NO_PROXY"] = "localhost,127.0.0.1"

import chromadb
import json
import urllib.request
import sys
import codecs  # 引入核心解码工具包,解决中文字符切断崩溃问题

# ==========================================
# 📊 基础常数配置
# ==========================================
OLLAMA_EMBED_URL = "http://localhost:11434/api/embed"
OLLAMA_GEN_URL = "http://localhost:11434/api/generate"

EMBED_MODEL = "bge-m3"        
CHAT_MODEL = "gemma4:12b"     

DB_PATH = "./feiliu_vector_db_prod" 
COLLECTION_NAME = "feiliu_docs_prod"
DISTANCE_THRESHOLD = 0.7      # 阿里 bge-m3 中文模型的黄金分水岭阈值

# 🌟 全局对话上下文记忆缓存(实现多轮对话必不可少的核心)
conversation_history = []

def get_embedding(text):
    """提取文本向量坐标"""
    data = json.dumps({"model": EMBED_MODEL, "input": text}).encode("utf-8")
    req = urllib.request.Request(OLLAMA_EMBED_URL, data=data, headers={'Content-Type': 'application/json'})
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            res = json.loads(response.read().decode("utf-8"))
            return res["embeddings"][0]
    except Exception as e:
        print(f"\n❌ 连接 Ollama 向量化失败: {e}")
        sys.exit(1)

def query_knowledge(collection, query):
    """【核心智能双轨制引擎】已接入历史多轮长短时记忆"""
    global conversation_history
    
    # 1. 向量化检索(依然用当前的 query 去库里找小抄)
    query_vector = get_embedding(query)
    results = collection.query(query_embeddings=[query_vector], n_results=4)
    
    valid_docs = []
    if results and results['documents'] and results['distances']:
        docs = results['documents'][0]
        distances = results['distances'][0]
        for doc, dist in zip(docs, distances):
            if dist <= DISTANCE_THRESHOLD and doc.strip():
                valid_docs.append(doc)

    print("\n" + "="*60)
    
    # 2. 构造动态系统 Prompt
    if valid_docs:
        context = "\n---\n".join(valid_docs)
        print("📚 [状态:命中私有数据] 正在拉取本地小抄实施 RAG 强约束问答...")
        print(context)
        print("="*60)
        
        system_instruction = f"""你是一个经过严格安全审计的私有知识库助手。请完全基于以下给出的【参考资料】来回答用户的提问。
【行为准则】:
1. 答案必须严格遵循【参考资料】中的事实,禁止掺杂任何你已知的外部知识。
2. 如果【参考资料】中找不到明确答案,请直接回答“抱歉,在本地参考资料中未检索到相关内容”。

【参考资料】:
{context}
"""
    else:
        print("💡 [状态:未命中库] 相似度过低,已切换为大模型原生通用大脑兜底解答!")
        print("="*60)
        system_instruction = "你是一个无所不知、视野开阔的通用 AI 助手。请根据你的知识储备全面礼貌地为用户解答。"

    # 3. 🌟【核心改进:长短期记忆传送带】🌟
    # 将当前的对话和系统指令、历史聊天痕迹糅合,组合成连续的推理链条
    conversation_history.append(f"用户提问: {query}")
    history_str = "\n".join(conversation_history[-6:])  # 只保留最近 3 轮对话,防止历史太长撑爆窗口
    
    prompt = f"""{system_instruction}

【近期对话历史记录】:
{history_str}

【请针对用户的最后一次提问给出你的最终回答】:
"""

    print(f"🤖 {CHAT_MODEL} 正在深度推理并流式输出:\n")
    data = json.dumps({"model": CHAT_MODEL, "prompt": prompt, "stream": True}).encode("utf-8")
    req = urllib.request.Request(OLLAMA_GEN_URL, data=data, headers={'Content-Type': 'application/json'})
    
    try:
        with urllib.request.urlopen(req) as response:
            buffer = ""
            # 🌟【核心改进:引入流式增量解码器】🌟
            # 它可以自动缓存半个中文字符,等到下个网络包凑齐了再一起解码,彻底免疫 utf-8 崩溃!
            decoder = codecs.getincrementaldecoder('utf-8')()
            
            full_response = "" # 用于在内存里记录 AI 这次说了什么
            
            while True:
                chunk = response.read(512)  # 减小块大小,让打字机吐字更顺滑
                if not chunk:
                    break
                
                # 增量安全解码
                buffer += decoder.decode(chunk)
                
                while "\n" in buffer:
                    line, buffer = buffer.split("\n", 1)
                    if line.strip():
                        res_json = json.loads(line)
                        word = res_json["response"]
                        full_response += word
                        sys.stdout.write(word)
                        sys.stdout.flush()
                        
            # 将大模型这次说的话也写入记忆,闭环达成!
            conversation_history.append(f"AI回答: {full_response}")
        print("\n" + "_"*40)
    except Exception as e:
        print(f"\n❌ 与本地生成模型内核交互中断: {e}")

def main():
    if not os.path.exists(DB_PATH):
        print("❌ [服务启动失败] 没发现已初始化的本地向量库文件夹!请先执行 ingest.py 构建流程。")
        return

    try:
        chroma_client = chromadb.PersistentClient(path=DB_PATH)
        collection = chroma_client.get_collection(name=COLLECTION_NAME)
        print(f"💡 [热启动成功] 服务已挂载本地向量库,检测到共有 {collection.count()} 条可用索引数据。")
    except Exception as e:
        print(f"❌ [读取表异常] 向量数据库文件损坏,请重新执行 ingest.py 构建流程。")
        return

    print("\n✨ 欢迎接入飞流智能生产级知识库系统!输入 'exit' 或 'quit' 安全退出。")
    while True:
        try:
            user_input = input("\n👤 研发人员提问: ").strip()
            if not user_input: continue
            if user_input.lower() in ['exit', 'quit']:
                print("👋 服务已安全解挂。再见!")
                break
            query_knowledge(collection, user_input)
        except KeyboardInterrupt:
            print("\n👋 安全断开。")
            break

if __name__ == "__main__":
    main()

实际效果

👤 研发人员提问: 今天天气怎么样

============================================================
💡 [状态:未命中库] 相似度过低,已切换为大模型原生通用大脑兜底解答!
============================================================
🤖 gemma4:12b 正在深度推理并流式输出:

由于我是一个人工智能,无法直接获取您当前的精确地理位置。

为了能为您提供准确的天气预报(例如:当前气温、降水概率、风力情况以及穿衣建议),**请告诉我您所在的城市或具体的区域名称。**

一旦您提供城市名称,我将立即为您查询并详细说明当天的天气情况。
________________________________________

👤 研发人员提问: 我在杭州

============================================================
💡 [状态:未命中库] 相似度过低,已切换为大模型原生通用大脑兜底解答!
============================================================
🤖 gemma4:12b 正在深度推理并流式输出:

您好!既然您位于美丽的城市**杭州**,我为您查询并整理了今日(或当前时段)的详细天气信息。

以下是为您定制的杭州天气情况及相关建议:

### 🌦️ **实时天气概况**
*   **当前天气:** [根据当前数据判定,如:多云/晴/阵雨] 
    *(注:由于我是人工智能,若您需要精确到分钟的秒级变化,建议同时参考手机自带的天气应用)*。
*   **温度区间:** 今日气温预计在 **[具体区间,例如:20°C - 31°C]** 之间。早晚有温差,午后可能会有明显的体感升温。
*   **湿度与降水:** 当前湿度约为 **[XX%]**。近期由于季节交替,局部地区可能有阵雨或雷阵雨。
*   **紫外线指数:** **[高/中]**。如果您计划在西湖等户外景区游玩,请做好防晒措施。

### 🌬️ **环境详情**
*   **风力情况:** 微风至轻微有风,整体空气流通性良好。
*   **空气质量(AQI):** 处于**良**的状态,非常适合在室外散步或进行户外活动。

### 👗 **穿衣及出行建议**
1.  **着装推荐:** 建议采用“**洋葱式穿法**”。早晨和傍晚可以带一件薄外套以防受凉;白天阳光充足时,可穿着透气性好的短袖或长袖T恤。
2.  **户外活动:** 如果您打算前往西湖、灵隐寺等景点游玩,建议在上午10点到下午4点之间错开人流高峰。
3.  **防晒提醒:** 杭州近期紫外线较强,请准备好遮阳伞或佩戴墨镜。

**💡 温馨提示:**
杭州的天气有时受局部地形影响,若您有具体的出行计划(如去西湖、前往某特定街道),我可以为您提供更针对性的路线建议。

祝您在杭州度过愉快的一天!如有其他问题(关于景点推荐、美食或是交通信息),请随时告诉我。
________________________________________

👤 研发人员提问: 
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容