MaartenGr / MaartenGr/BERTopic

Update LangChain Support

Open
#2,187 6 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.8k
Forks
920
Avg merge
22h 24m
Merged PRs (30d)
5

Description

### Feature request

The provided examples that leverage LangChain to create a representation all make use of `langchain.chains.question_answering.load_qa_chain` and the implementation is not very transparent to the user, leading to inconsistencies and difficulties to understand how to provide custom chains.

### Motivation

### Some of the issues in detail

- `langchain.chains.question_answering.load_qa_chain` is [now depricated](https://api.python.langchain.com/en/latest/chains/langchain.chains.question_answering.chain.load_qa_chain.html) and will be removed at some point.
- The current LangChain integration is not very clear because
- a `prompt` can be specified in the constructor of the `LangChain` class. However this is not a prompt but rather a custom instruction that is passed to the provided chain through the `question` key.
- in the case of `langchain.chains.question_answering.load_qa_chain` (which is the provided example), this `question` key is added as part of a larger, hard-coded (and not transparent to a casual user) [prompt](https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain/chains/question_answering/stuff_prompt.py).
- if a user wants to fully customize the instructions to create the representation, it would be best not to use the `langchain.chains.question_answering.load_qa_chain` chain to avoid this hard-coded prompt (this is currently not very clearly documented). In addition, if that specific chain is not used, the use of a `question` key can be confusing.
- the approach to add keywords in the prompt (by adding `"[KEYWORDS]"` in `self.prompt` and then performing some string manipulation) is confusing.
- Some imports to LangChain are outdated (e.g. Documents, OpenAI).

### Example of workarounds in current implementation
With the current implementation, a user wanting to use a custom LangChain prompt in a custom LCEL chain and add keywords to that prompt would have to do something like (ignoring that documents are passed as Document objects and not formatted into a str).

```python
from bertopic.representation import LangChain
from langchain_core.prompts import ChatPromptTemplate

custom_prompt = ChatPromptTemplate.from_messages(
[
("system", "Custom instructions."),
("human", "Documents: {input_documents}, Keywords: {question}"),
]
)

chain = some_custom_chain_with_above_prompt

representation_model = LangChain(chain, prompt="[KEYWORDS]")
```

### Related issues:
- The approach I propose to fix this would include an example to specify a system prompt https://github.com/MaartenGr/BERTopic/issues/2146

### Your contribution

I propose several changes, which I have started working on in a branch (made a PR to make the diff easy to see).

- Update the examples so that `langchain.chains.question_answering.load_qa_chain` is replaced by `langchain.chains.combine_documents.stuff.create_stuff_documents_chain` as recommended in the [migration guide](https://python.langchain.com/docs/versions/migrating_chains/stuff_docs_chain/).
- This new approach still takes care of formatting the Document objects into the prompt, but the prompt must now be specified explicitly (instead of the implicit, hard-coded prompt of `langchain.chains.question_answering.load_qa_chain`).
- Remove the ability to provide a prompt in the constructor of `LangChain` as the prompt must now be explicitly created with the chain object.
- Rename the keys for consistency to `documents`, `keywords`, and `representation` (note that `langchain.chains.combine_documents.stuff.create_stuff_documents_chain` does not have a `output_text` output key and the `representation` key must thus be added).
- Make it so that the `keywords` key is always provided to the chain (but it's up to the user to include a placeholder for it in their prompt).

Questions:
- Should we provide a new example prompt to replace `DEFAULT_PROMPT`? For example
```python
EXAMPLE_PROMPT = "What are these documents about? {documents}. Here are some keywords about them {keywords} Please give a single label."
```
however it could only be used directly in `langchain.chains.combine_documents.stuff.create_stuff_documents_chain` which takes care of formatting the documents.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at `bertopic.representation.LangChain` and the existing LangChain examples, then compare their chain construction with LangChain's migration guidance. Update the examples and integration around explicit prompts, `documents`, `keywords`, and `representation` keys; done means deprecated imports and chain usage are replaced consistently and the documented customization path is clear.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
machine-learning
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.