实现右侧记忆面板可编辑

本次功能

右侧记忆面板可编辑

支持:

  • 手动新增记忆
  • 删除单条记忆
  • 修改单条记忆

1)改 server/memory_store.py

新增方法

ini 复制代码
def set_session_memories(session_id: str, memories: List[str]):
    if not session_id:
        return

    data = _load()
    cleaned = []

    for item in memories or []:
        text = str(item).strip()
        if text and text not in cleaned:
            cleaned.append(text)

    data[session_id] = cleaned[:50]
    _save(data)

2)改 server/app.py

补 import

javascript 复制代码
from memory_store import (
    get_session_memories,
    add_session_memories,
    delete_session_memories,
    set_session_memories,
)

新增请求模型

less 复制代码
@app.put("/api/memory/{session_id}", response_model=MemoryResponse)
def update_memory(session_id: str, req: UpdateMemoryRequest):
    if not session_id:
        raise HTTPException(status_code=400, detail="session_id不能为空")

    set_session_memories(session_id, req.memories)
    return MemoryResponse(memories=get_session_memories(session_id))

3)改 web/src/App.vue

新增状态

csharp 复制代码
const memoryDraft = ref('')
const editingMemoryIndex = ref(-1)
const editingMemoryValue = ref('')

新增方法

ini 复制代码
const saveMemories = async nextMemories => {
  if (!currentSessionId.value) return

  try {
    const res = await axios.put(`http://127.0.0.1:8000/api/memory/${currentSessionId.value}`, {
      memories: nextMemories,
    })
    memoryList.value = res.data.memories || []
  } catch (error) {
    console.error(error)
  }
}

const handleAddMemory = async () => {
  const text = memoryDraft.value.trim()
  if (!text) return

  await saveMemories([...memoryList.value, text])
  memoryDraft.value = ''
}

const handleDeleteMemory = async index => {
  const nextMemories = memoryList.value.filter((_, i) => i !== index)
  await saveMemories(nextMemories)

  if (editingMemoryIndex.value === index) {
    editingMemoryIndex.value = -1
    editingMemoryValue.value = ''
  }
}

const handleStartEditMemory = (item, index) => {
  editingMemoryIndex.value = index
  editingMemoryValue.value = item
}

const handleSaveEditMemory = async index => {
  const text = editingMemoryValue.value.trim()
  const nextMemories = [...memoryList.value]

  if (!text) {
    nextMemories.splice(index, 1)
  } else {
    nextMemories[index] = text
  }

  await saveMemories(nextMemories)
  editingMemoryIndex.value = -1
  editingMemoryValue.value = ''
}

const handleCancelEditMemory = () => {
  editingMemoryIndex.value = -1
  editingMemoryValue.value = ''
}

4)改模板

ini 复制代码
<aside class="memory-panel">
  <div class="memory-header">会话记忆</div>

  <div class="memory-editor">
    <input
      v-model="memoryDraft"
      class="memory-input"
      placeholder="手动新增一条记忆"
      @keydown.enter="handleAddMemory"
    />
    <button class="memory-add-btn" @click="handleAddMemory">新增</button>
  </div>

  <div v-if="memoryList.length" class="memory-list">
    <div v-for="(item, index) in memoryList" :key="index" class="memory-item">
      <template v-if="editingMemoryIndex === index">
        <input
          v-model="editingMemoryValue"
          class="memory-edit-input"
          @keydown.enter="handleSaveEditMemory(index)"
          @keydown.esc="handleCancelEditMemory"
        />
        <div class="memory-actions">
          <span class="memory-action" @click="handleSaveEditMemory(index)">保存</span>
          <span class="memory-action delete" @click="handleCancelEditMemory">取消</span>
        </div>
      </template>

      <template v-else>
        <div class="memory-text">{{ item }}</div>
        <div class="memory-actions">
          <span class="memory-action" @click="handleStartEditMemory(item, index)">编辑</span>
          <span class="memory-action delete" @click="handleDeleteMemory(index)">删除</span>
        </div>
      </template>
    </div>
  </div>

  <div v-else class="memory-empty">暂时还没有提取到长期记忆</div>
</aside>

5)补充样式

css 复制代码
.memory-editor {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.memory-input,
.memory-edit-input {
  flex: 1;
  min-width: 0;
  border: 1px solid #d1d5db;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 14px;
  outline: none;
  box-sizing: border-box;
  background: #fff;
}

.memory-add-btn {
  border: none;
  border-radius: 10px;
  background: #111827;
  color: #fff;
  padding: 0 14px;
  cursor: pointer;
  flex-shrink: 0;
}

.memory-text {
  line-height: 1.6;
  color: #111827;
  word-break: break-word;
}

.memory-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
}

.memory-action {
  font-size: 12px;
  color: #6b7280;
  cursor: pointer;
  user-select: none;
}

.memory-action:hover {
  color: #111827;
}

.memory-action.delete:hover {
  color: #dc2626;
}

6)验证

nice !

本次提交仓库

github.com/fhj414/ai-c...

有收获点个 star 🌟🌟🌟 谢谢~

相关推荐
2601_954526754 小时前
2026 生成式搜索引擎底层技术演进与 GEO优化服务商推荐:大模型检索增强(RAG)管道与语义对齐工程实战
大数据·人工智能·搜索引擎
我有满天星辰5 小时前
Spring AI Prompt 实战:System Prompt、User Prompt 与 PromptTemplate
人工智能·spring·prompt
A15362555 小时前
WMS 仓储管理系统推荐:企业如何选适配的仓储管理系统
大数据·人工智能
学习中.........5 小时前
Transformer 训练资源估算:以 CS336 GPT-2 XL 配置为例
人工智能·python·算法·机器学习·自然语言处理
Setsuna_F_Seiei9 小时前
前端的 AI 学习之路 02 之 Provider 与 Structured Output - 规范化模型输入输出
人工智能·agent·ai编程
JavaPub-rodert10 小时前
王仕宇RAG 实战教程(二):从 0 搭建一个可运行的 RAG 知识库——Embedding、Qdrant 与问答实战
人工智能·embedding
Setsuna_F_Seiei10 小时前
前端的 AI 学习之路 01 之 Agent API 调用 - 和 Agent 的基础对话
前端·人工智能·ai编程
覆东流10 小时前
7.Java数组
java·开发语言·后端
threerocks10 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
JavaPub-rodert10 小时前
王仕宇在 Go Context 如何解决协程泄漏与超时控制
开发语言·后端·golang·iphone·javapub·王仕宇