You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Streamlit的st.chat_input()添加类似谷歌搜索的自动补全建议

如何为Streamlit的st.chat_input()添加类似谷歌搜索的自动补全建议

没问题!要给Streamlit的st.chat_input()加上类似谷歌的实时自动补全,确实得借助一点JavaScript或者自定义组件,我给你两种实用的方案,你可以按需选择:

方案一:直接注入JavaScript(简单快捷,无额外依赖)

这种方式不需要安装其他包,直接通过st.markdown注入自定义JS代码,就能给原生的st.chat_input()加上补全功能。

完整代码示例

import streamlit as st

# 准备你的自动补全候选词库,可以根据需求动态调整
autocomplete_suggestions = [
    "how it work",
    "how to do data analysis",
    "how to deploy Streamlit app",
    "how to use pandas",
    "how to debug Python code"
]

# 初始化会话状态的消息列表(如果还没初始化的话)
if "sales_messages" not in st.session_state:
    st.session_state.sales_messages = []

# 原生的聊天输入框
if query1 := st.chat_input("Ask Here", key="chat1"):
    with st.spinner("AI is analyzing ..."):
        try:
            st.chat_message("user").markdown(query1)
            st.session_state.sales_messages.append({"role": "user", "content": query1})
            # 这里放你的AI响应生成逻辑,比如调用LLM接口
            # 示例:st.chat_message("assistant").markdown("这是AI的回复内容")
        except Exception as e:
            st.error(f"出错了: {str(e)}")

# 注入实现自动补全的JavaScript代码
st.markdown("""
<script>
// 等待页面所有元素渲染完成
document.addEventListener('DOMContentLoaded', function() {
    // 定位到chat_input对应的输入框(通过Streamlit的测试ID和key关联的元素)
    const inputField = document.querySelector('div[data-testid="stChatInput"][data-key="chat1"] input');
    if (!inputField) return;

    // 补全候选词,和Python端的列表保持同步
    const suggestions = """ + str(autocomplete_suggestions).replace("'", "\"") + """;
    
    // 创建存放补全建议的下拉容器
    const suggestionBox = document.createElement('div');
    Object.assign(suggestionBox.style, {
        position: 'absolute',
        top: `${inputField.offsetTop + inputField.offsetHeight + 4}px`,
        left: `${inputField.offsetLeft}px`,
        width: `${inputField.offsetWidth}px`,
        backgroundColor: 'white',
        border: '1px solid #e0e0e0',
        borderRadius: '4px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
        zIndex: '9999',
        display: 'none'
    });
    inputField.parentElement.style.position = 'relative';
    inputField.parentElement.appendChild(suggestionBox);

    // 监听输入框的输入事件,实时生成补全建议
    inputField.addEventListener('input', function() {
        const inputText = this.value.trim().toLowerCase();
        // 输入为空时隐藏建议框
        if (!inputText) {
            suggestionBox.style.display = 'none';
            return;
        }

        // 过滤出包含输入文本的候选词
        const matchedSuggestions = suggestions.filter(s => s.toLowerCase().includes(inputText));
        if (matchedSuggestions.length === 0) {
            suggestionBox.style.display = 'none';
            return;
        }

        // 清空并重新渲染建议项
        suggestionBox.innerHTML = '';
        matchedSuggestions.forEach(suggestion => {
            const suggestionItem = document.createElement('div');
            Object.assign(suggestionItem.style, {
                padding: '8px 12px',
                cursor: 'pointer',
                fontSize: '14px'
            });
            // 鼠标 hover 时的样式
            suggestionItem.addEventListener('mouseover', () => {
                suggestionItem.style.backgroundColor = '#f0f2f6';
            });
            suggestionItem.addEventListener('mouseout', () => {
                suggestionItem.style.backgroundColor = 'white';
            });
            // 点击建议项时填充到输入框并隐藏建议框
            suggestionItem.addEventListener('click', () => {
                inputField.value = suggestion;
                suggestionBox.style.display = 'none';
                // 可选:自动触发回车提交
                inputField.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
            });
            suggestionItem.textContent = suggestion;
            suggestionBox.appendChild(suggestionItem);
        });

        suggestionBox.style.display = 'block';
    });

    // 点击页面其他区域时关闭建议框
    document.addEventListener('click', (e) => {
        if (!inputField.contains(e.target) && !suggestionBox.contains(e.target)) {
            suggestionBox.style.display = 'none';
        }
    });
});
</script>
""", unsafe_allow_html=True)

方案要点说明

  • 我们通过document.querySelector精准定位到指定key的st.chat_input输入框,避免影响页面其他输入元素
  • JS中的候选词和Python端的列表保持同步,你也可以从st.session_state动态传递更新后的候选词
  • 实时监听输入事件,过滤匹配的建议项,点击建议即可快速填充内容,还支持自动提交
  • 加入了点击页面其他区域关闭建议框的交互,提升用户体验

方案二:用自定义组件实现(更灵活,适合复杂场景)

如果你的补全逻辑比较复杂(比如需要从后端异步获取建议、自定义样式需求高),可以用streamlit.components.v1创建专属的带补全功能的聊天输入组件。

完整代码示例

import streamlit as st
import streamlit.components.v1 as components

def chat_input_with_autocomplete(placeholder: str, key: str, suggestions: list):
    """自定义带自动补全的聊天输入框组件"""
    component_html = f"""
    <div style="position: relative; width: 100%;">
        <input 
            type="text" 
            id="{key}-input" 
            placeholder="{placeholder}" 
            style="width: 100%; padding: 10px; border-radius: 8px; border: 1px solid #ddd; font-size: 14px;"
        >
        <div id="{key}-suggestions" style="position: absolute; top: 42px; left: 0; width: 100%; background: white; border: 1px solid #e0e0e0; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); display: none; z-index: 999;"></div>
    </div>
    <script>
        const input = document.getElementById('{key}-input');
        const suggestionsBox = document.getElementById('{key}-suggestions');
        const suggestions = {str(suggestions).replace("'", "\"")};

        // 实时生成补全建议
        input.addEventListener('input', function() {{
            const inputText = this.value.trim().toLowerCase();
            if (!inputText) {{
                suggestionsBox.style.display = 'none';
                return;
            }}
            // 过滤匹配的建议
            const matchedSuggestions = suggestions.filter(s => s.toLowerCase().includes(inputText));
            if (matchedSuggestions.length === 0) {{
                suggestionsBox.style.display = 'none';
                return;
            }}
            // 渲染建议项
            suggestionsBox.innerHTML = matchedSuggestions.map(suggestion => `
                <div style="padding: 10px; cursor: pointer; font-size: 14px;" 
                     onmouseover="this.style.backgroundColor='#f0f2f6'"
                     onmouseout="this.style.backgroundColor='white'"
                     onclick="selectSuggestion('${suggestion}')">
                    ${suggestion}
                </div>
            `).join('');
            suggestionsBox.style.display = 'block';
        }});

        // 选择建议项并传递值回Streamlit
        function selectSuggestion(selectedText) {{
            input.value = selectedText;
            suggestionsBox.style.display = 'none';
            // 把选中的值发送给Streamlit
            window.parent.postMessage({{
                type: 'streamlit:setComponentValue',
                value: selectedText
            }}, '*');
        }}

        // 监听回车提交
        input.addEventListener('keydown', function(e) {{
            if (e.key === 'Enter' && this.value.trim()) {{
                window.parent.postMessage({{
                    type: 'streamlit:setComponentValue',
                    value: this.value.trim()
                }}, '*');
                this.value = '';
            }}
        }});
    </script>
    """
    # 渲染组件并获取返回值
    return components.html(component_html, height=60, key=key)

# 初始化消息列表
if "sales_messages" not in st.session_state:
    st.session_state.sales_messages = []

# 补全候选词库
autocomplete_suggestions = [
    "how it work",
    "how to do data analysis",
    "how to deploy Streamlit app",
    "how to use pandas"
]

# 使用自定义输入组件
user_query = chat_input_with_autocomplete("Ask Here", key="custom-chat-input", suggestions=autocomplete_suggestions)

# 处理用户输入
if user_query:
    with st.spinner("AI is analyzing ..."):
        st.chat_message("user").markdown(user_query)
        st.session_state.sales_messages.append({"role": "user", "content": user_query})
        # 这里添加你的AI响应逻辑
        # st.chat_message("assistant").markdown("AI的回复内容")

方案要点说明

  • 自定义组件完全掌控输入框和补全框的样式、交互逻辑,适配复杂需求
  • 通过window.parent.postMessage把用户输入或选中的建议值传递回Streamlit
  • 支持回车提交选中的内容,和原生st.chat_input的使用体验保持一致

注意事项

  1. Streamlit的DOM结构可能会在版本更新时微调,如果发现输入框定位失效,需要调整querySelector的选择器
  2. 如果候选词需要动态生成(比如基于用户历史输入、AI的常见问题),可以把候选词存在st.session_state中,再传递给JS或自定义组件
  3. 测试时建议开启Streamlit的自动刷新,确保代码修改后能实时看到效果

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 07:29:31